odata.net: the OData protocol libraries that WebApi and RESTier sit on
ODataLib: Open Data Protocol - .NET Libraries and Frameworks
At a glance
- What is it?
- Microsoft's open source .NET implementation of OData, split into a payload and URI library, an entity data model library, a spatial library and a LINQ client. If you build an OData service with WebApi or consume one with the .NET client, this is the layer underneath, and it is where the protocol details actually live.
- Who is it for?
- Adopt odata.net if you are building or consuming an OData service on .NET, either directly through the libraries or through WebApi and RESTier which are built on them. Skip it if you are only a client of a service that already works, since the client package alone is enough.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What OData is and where this library sits in it
OData stands for the Open Data Protocol. It was initiated by Microsoft and is now an ISO ratified OASIS standard. OData enables the creation and consumption of REST APIs which allow resources, identified using URLs and defined in a data model, to be published and edited by web clients using simple HTTP requests.
That description hides the difficulty. A plain REST API lets you fetch a resource by URL. OData adds a query language, a standard way to describe the shape of the data, and a standard way to express relationships, filters and projections. Once a service speaks it, a generic client can explore and query the whole service without knowing anything about its domain.
This repository is the .NET implementation of the protocol itself. The project includes the implementation of core functionalities of OData protocol on the .NET platform, specifically URI parsing, request and response reading and writing, Entity Data Model building, and a .NET OData client which can be used to consume an OData service. It is a fully open sourced project maintained by the Microsoft OData team.
The audience is therefore two groups. If you are building a service, the project documentation points you to RESTier for an OData v4 service, to the OData WebApi library, and to the .NET client. If you are consuming one, the .NET client is the entry point. Both sit on top of the libraries in this repository.
Four packages, and the dependency order between them
The main branch ships a set of libraries under a consistent naming scheme, each on NuGet with its own namespace.
ODataLib, the package Microsoft.OData.Core with namespace Microsoft.OData.Core, contains classes to serialize and deserialize OData JSON payloads, and to parse OData Urls. This is the payload and URI layer.
EdmLib, the package Microsoft.OData.Edm with namespace Microsoft.OData.Edm, contains classes to represent, construct, parse, serialize and validate entity data models. The EDM is the schema of the service, so this is the layer that knows what an entity type and a complex type are.
Microsoft.Spatial, under the namespace Microsoft.Spatial, is the spatial library with classes and methods that facilitate geography and geometry spatial operations. That matters because OData has defined spatial types, and the geometry helpers are substantial enough to warrant their own package.
The OData Client for .NET, the package Microsoft.OData.Client with namespace Microsoft.OData.Client, is built on top of ODataLib and EdmLib and provides LINQ-enabled client APIs for issuing OData queries and constructing and consuming OData JSON payloads.
That layering is the thing to understand. EdmLib describes the data model, ODataLib reads and writes the wire format and the URLs, and the client sits on both and adds LINQ. If you are writing a server that is not WebApi or RESTier, you would use ODataLib and EdmLib directly, and you would be implementing the HTTP layer yourself.
There is also a WASM sample in the tree, with a client and a server project and its own solution file, which is a hint about one of the more awkward corners of this stack.
Branches are the versioning story, and there are a lot of them
The branch layout in this repository is the single most confusing thing about adopting it, so it is worth reading carefully.
The project currently has a main branch and three archived branches: maintenance-6.x, maintenance-5.x, and maintenance-wcf-dataservice-v4. Separately from those, the readme also describes a dev-8.x branch as the active development branch for ODataV4 8.x, while the main branch is described as the active development branch for ODataV4 7.x, producing libraries targeting .NET 4.5 as well as .NET Standard 1.1 and 2.0, and building with Visual Studio 2019.
The archived branches have different characters. The maintenance-6.x branch holds the libraries for ODataV4 6.x maintenance releases. The maintenance-5.x branch holds the .NET libraries for OData V1-3 releases only, and it has similar libraries to the 6.x branch except for some differences in namespaces and two additional libraries, which are ODataLib for OData v1-3 under the namespace Microsoft.Data.Core, EdmLib for OData v1-3, System.Spatial, the WCF Data Services Client for OData v1-3, the WCF Data Services Server for OData v1-3, and the WCF Data Services EntityFramework Provider for entity framework version 6.0 or higher.
Those libraries are in maintenance mode, and the policy is stated: only security bugs will be accepted, and the release will be irregular depending on the bugs fixed. That is a different promise from the main branch.
The third archived branch, maintenance-wcf-dataservice-v4, holds the source of the OData V4 parity of the WCF Data Services Server for OData v1-3. It is provided for demo purposes only, has no binary release and does not accept contributions, and the documentation recommends WebApi or RESTier for building new OData services.
The release history tells the same story from the other side: 9.0.0 RC on 2026-05-05, 9.0.0 on 2026-07-28, and 8.4.4 on 2026-07-14. So there are parallel version lines and the newest major is not on the branch the readme still calls main.
The build assumes Visual Studio and a local database
The build and test section is short and it tells you what kind of project this is.
Since the project is built on VS2019, LocalDB v12.0 or above will be used, which is part of VS2019 and needs no additional installation. The database will be automatically initialized by the test code if it does not exist. So there is no separate database to provision and no migration step to run before the tests, which is convenient if you have Visual Studio and unhelpful if you do not.
The tree shows the surrounding machinery. There is a build.cmd and a build.ps1 for command line builds, a build.root, and a Build.props file for shared MSBuild properties. The continuous integration configuration is a set of Azure Pipelines files: azure-pipelines-rolling.yml, azure-pipelines-nightly.yml, nightly.yml, buildandtest.yml, benchmarks.yml, loadtests.yml and credscan.yml. The readme's build status table at the top of the file shows a Rolling build and a Nightly build, which matches the pipeline file names.
The distinction between rolling and nightly matters if you consume these libraries from CI. A rolling build is the one that feeds the package feed continuously, while a nightly build is a broader sweep that can run the heavier suites. The presence of benchmarks.yml and loadtests.yml also tells you the project cares about query performance and load behaviour, and credscan.yml suggests credential scanning is part of the pipeline.
There is a PerformanceBuild.ps1 script at the root, plus a test.runsettings file and separate test and tools directories. The samples directory holds the WASM sample and, further in, other sample projects referenced from the readme's guidance on adopting the libraries.
Where OData services get built, and why the protocol layer matters
The project documentation is explicit that odata.net is not usually the thing you install to build a service. For how to adopt these and related libraries to build or consume an OData service, it points to three resources: build an OData v4 service with the RESTier library, build an OData v4 service with the OData WebApi library, and the OData .Net client for consuming.
WebApi and RESTier are the two server stacks, and both are described as using the libraries in this repository. That is the practical shape of the ecosystem. You do not assemble an OData service out of ODataLib by hand unless you have a reason to, because the server side of OData involves a lot of protocol surface: query options, $expand, $select, $orderby, batch requests, metadata documents, and the various response formats.
RESTier is described as the recommended approach for new services in the context of the archived WCF branch. That is a useful signal, because the older WCF Data Services Server is the previous generation of the same idea and it is archived and demo only, so the direction of travel is clear.
The client side is different, because the .NET client is the supported way to consume OData, and it is where the LINQ-enabled API turns a query into an OData URL and materialises the result. If your application is on .NET and talks to an OData service, that is the package you need.
So the dividing line is roughly this. Consuming an OData service from .NET means installing Microsoft.OData.Client. Building one means picking RESTier or WebApi and letting them use the libraries here. Reaching for ODataLib and EdmLib directly is for the cases where neither of those fits, and the WASM sample in the tree is evidence of one such case.
The licence is custom, and the version lines are the real risk
Two things deserve a careful reading before you commit.
The first is the licence. This repository is published under a custom licence that GitHub cannot classify, with the terms in the LICENSE file. There is no short identifier to quote and no assumption of a permissive grant you can rely on without checking. If you ship a product that links these libraries, read LICENSE.txt rather than inferring terms from the fact that the project is open sourced and maintained by Microsoft. The repository also carries a SECURITY.md, which is where to look for how security issues are handled.
The second is the version sprawl, and it is the more practical problem. A service built on the 8.x line and a client built on the 9.0.0 packages are different pieces of a protocol implementation, and the 1-3 libraries on the 5.x maintenance branch are a different namespace world entirely, Microsoft.Data.Core and Microsoft.Data.Edm rather than Microsoft.OData.Core and Microsoft.OData.Edm. The readme is candid that there are namespace differences between branches, so mixing versions across lines is not a supported configuration.
A third, softer constraint is the target framework on the main branch, .NET 4.5 as well as .NET Standard 1.1 and 2.0. If your application targets a modern .NET runtime, the .NET Standard assets are what you get, and if your application is on the older frameworks you are pinned to a build with Visual Studio 2019, which is itself an end-of-life toolchain for building.
None of these are reasons to reject the libraries. They are reasons to decide deliberately which line you are on, and to check that the branch you pick is still the one your service and client both reference.
Against hand rolling HTTP, and against a plain REST client
Two comparisons put the value of this stack in perspective.
The first is against hand writing HTTP calls against an OData service. That is entirely possible and it works, until the first $expand, the first metadata request, the first batch call and the first service that returns a bare 200 with an error body. The OData payload format has specific rules about how nulls, navigation properties and annotations are represented in JSON, and the metadata document is a specific format that describes the whole service. ODataLib exists to encode those rules, and the client exists to let you write a LINQ query and have the URL and the materialisation handled correctly. Rebuilding that is a project, not an afternoon.
The second is against a plain REST client such as one built on HttpClient. Here the difference is about what you get back. A generic REST client gives you the raw response and you interpret it. An OData client gives you typed entities, and, more importantly, gives you the ability to query the service without knowing its schema in advance, because the service publishes that schema and the client can read it.
That last capability is the reason OData exists and the reason this repository still matters. An API where the client must be regenerated whenever a field is added is an API with a maintenance cost per change. An OData service describes itself, so a generic client can discover and query it. If your problem is only to call a handful of known endpoints with known shapes, a plain REST client is less machinery and the right choice. If you want a client that can explore an unfamiliar service, this stack is what gives you that.
Editorial conclusion
Adopt odata.net if you are building or consuming an OData service on .NET, either directly through the libraries or through WebApi and RESTier which are built on them. Skip it if you are only a client of a service that already works, since the client package alone is enough. Verify first which branch and version line matches the OData version your service speaks, because the main branch and the dev-8.x branch target different lines, and check the LICENSE.txt terms before you ship, since this repository is published under a custom licence rather than a standard one.
Frequently asked questions
What does the odata.net repository contain?
It contains the .NET implementation of OData protocol core functionality: URI parsing, request and response reading and writing, Entity Data Model building, and a .NET client for consuming an OData service. It is a fully open sourced project maintained by the Microsoft OData team.
What are the main packages in odata.net?
ODataLib as Microsoft.OData.Core for serialising and deserialising OData JSON payloads and parsing OData URLs, EdmLib as Microsoft.OData.Edm for entity data models, Microsoft.Spatial for geography and geometry operations, and the OData Client for .NET as Microsoft.OData.Client, which is built on the other two and offers LINQ-enabled client APIs.
Which branch of odata.net should I use?
The main branch is described as the active development branch for ODataV4 7.x targeting .NET 4.5 and .NET Standard 1.1 and 2.0, while dev-8.x is the active development branch for ODataV4 8.x. The maintenance-5.x, maintenance-6.x and maintenance-wcf-dataservice-v4 branches are archived, and the 5.x libraries accept only security fixes with irregular releases.
Do I need odata.net to build an OData service?
Usually not directly. The project documentation points to RESTier and the OData WebApi library for building an OData v4 service, and both use the libraries in this repository. Reach for ODataLib and EdmLib yourself only when neither server stack fits.
How is odata.net built and tested?
The project is built on VS2019 and uses LocalDB v12.0 or above, which ships with Visual Studio and needs no separate installation. The database is initialised automatically by the test code if it does not exist. The tree also contains build.cmd and build.ps1 for command line builds, and the Azure Pipelines files for rolling and nightly builds.
What licence does odata.net use?
A custom licence that GitHub cannot classify, with the terms in LICENSE.txt at the root of the repository. The project is not archived and the last push was on 2026-10-19, with the ODL 9.0.0 release published on 2026-07-28.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/odata-odata-net)Was this useful?