We would like to announce that we are planning a new major release of OData .NET core libraries in June. Ahead of this release, we have released preview versions of the libraries to get some early feedback from the community. Specifically, the following preview releases are now available on NuGet:
- Microsoft.OData.Core 8.0.0-preview.1
- Microsoft.OData.Edm 8.0.0-preview.1
- Microsoft.OData.Client 8.0.0-preview.1
- Microsoft.Spatial 8.0.0-preview.1
It has been almost 8 years since the last major release of OData .NET core libraries. This release presents an opportunity for us to modernize our stack, address some technical debt and take better advantage of investments in .NET. To make adoption and upgrading to the new version smooth, we have opted to limit the number of breaking changes. In many cases, you should be able to upgrade to the new release by changing the version number with minimal code changes. We share a list of breaking changes below.
The most disruptive change we are making in this release is dropping support for .NET Framework. The new release will only support .NET 8 and later. We understand that there are still a lot of people using .NET Framework. For this reason, we will continue to maintain OData .NET v7 suite of libraries for the foreseeable future. We currently have no plans to drop support for OData Core 7.x. We will eventually stop adding new features after the 8.0 major release.
With this release, we will also introduce an official support policy. The support policy will document the support lifecycle for the different official OData libraries. This will state which versions are supported and for how long and this should help customers plan their migration accordingly. We will also publish a comprehensive migration guide to help you move from version 7.x to 8.0.0.
We invite you to try out these new versions and share feedback with us. Feel free to create an issue on our GitHub repository if you run into any issues with the preview release.
OData .NET 8 release schedule
- April 26th, 2024: First preview release 8.0.0-preview.1
- May 16th, 2024: First release candidate 8.0.0-rc1
- June 20th, 2024: Official release 8.0.0
We may release additional preview versions or release candidates before the final release depending on the feedback we get. We also plan to release new versions of Microsoft.AspNetCore.OData and Microsoft.OData.ModelBuilder that take advantage of OData Core 8.x. We will communicate the dates for these releases soon.
Breaking changes in Version 8.0.0-preview.1
The sections below list the breaking changes introduced the preview release. For a full list of changes (including non-breaking changes and improvements), check the changelog.
General breaking changes
- Support for .NET 8 and later only: We dropped support for .NET Framework, NET Core 3.1 and lower, .NET 7 and lower.
Breaking changes in Microsoft.OData.Core
- Merged
IJsonWriter
,IJsonWriterAsync
,IJsonStreamWriter
,IJsonStreamWriterAsync
into a single interfaceIJsonWriter
that exposes synchronous, asynchronous and streaming APIs for writing JSON payloads - Merged
IJsonReader
,IJsonReaderAsync
,IJsonStreamReader
,IJsonStreamReaderAsync
into a single interfaceIJsonReader
that exposes synchronous, asynchronous and streaming APIs for reading JSON payloads - Changed the default value of the
leaveOpen
argument of theODataBinaryStreamValue
constructor fromtrue
tofalse
. This means that by default, when theODataBinaryStreamValue
object is disposed, the underlying stream will also be closed and disposed. - JSONP support has been deprecated and will be removed in Microsoft.OData.Core 9.
- The
IJsonWriterFactory.CreateJsonWriter
method now accepts aStream
instead of aTextWriter
. - The
DefaultStreamBasedJsonWriterFactory
class has been renamed toODataUtf8JsonWriterFactory
. - Remove our custom
IContainerBuilder
interface used for dependency injection in favor of the standard Microsoft.Extensions.DependencyInjection APIs. - Introduced a new extension method called
AddDefaultODataServices
toIServiceCollection
for registering default OData services. - Removed the
ODataSimplifiedOptions
class and moved its properties to more appropriate classes (see below). - Moved
EnableParsingKeyAsSegment
fromODataSimplifiedOptions
toODataUriParserSettings
. - Moved
EnableReadingKeyAsSegment
andEnableReadingODataAnnotationPrefix
fromODataSimplifiedOptions
toODataMessageReaderSettings.
- Moved
EnableWritingKeyAsSegment
,GetOmitODataPrefix
andSetOmitODataPrefix
fromODataSimplifiedOptions
toODataMessageWriterSettings
. - Removed the
ODataMessageReader.CreateODataDeltaReader
andCreateODataDeltaReaderAsync
methods. UseCreateODataDeltaResourceSetReader
instead. - Removed the
ODataMessageWriter.CreateODataDeltaWriter
andCreateODataDeltaWriterAsync
methods. UseCreateODataDeltaResourceSetWriterAsync
instead. - Added the
INavigationSourceSegment
interface that exposes aNavigationSource
property to provide a consistent way of retrieving the navigation source without having to perform a type cast.
Breaking changes in Microsoft.OData.Client
- Marked the
DataServiceContext.KeyComparisonGeneratesFilterQuery
property as deprecated and changed the default value fromfalse
totrue
. This means that the LINQ querycontext.People.Where(p => p.Id == 10)
will generate a URL filter query option like/People?$filter=Id eq 10
instead of/People(10)
by default. - Removed
HttpWebRequestMessage
class, and consequently, support for the legacyHttpWebRequest
API. All requests from the client will be made usingHttpClientRequestMessage
which is based onHttpRequestMessage
andHttpClient
. - Removed the
HttpRequestTransportMode
enum property fromDataServiceContext
. This property was used to switch betweenHttpClient
andHttpWebRequest
. Now all requests are made usingHttpClient
. - Added
DataServiceContext.HttpClientFactory
property that allows you inject yourHttpClient
instance by passing a customIHttpClientFactory
. This replaces the previous approach of configuring a http client using the customIHttpClientHandlerProvider
(see below). - Removed the
DataServiceContext.HttpClientHandleProvider
property and theIHttpClientHandlerProvider
interface. These were used to provide customHttpClient
configurations. TheDataServiceContext.HttpClientFactory
should be used instead. - Removed the
DataServiceContext.Credentials
property. TheDataServiceContext.HttpClientFactory
should be used to provide aHttpClient
instance configured with the right credentials if needed. - Removed the
HttpClientRequestMessage.ReadWriteTimeout
property. TheHttpClientRequestMessage.Timeout
can be used to set the request timeout. - Removed the
DataServiceQuery<TElement>.IncludeTotalCount(bool countQuery)
method. UseIncludeCount(bool countQuery)
instead. - Removed the
DataServiceQuery<TElement>.IncludeTotalCount()
method. UseDataServiceQuery<TElement>.IncludeCount()
instead. - Removed the
QueryOperationResponse.TotalCount
property. UseCount
instead.
Breaking changes in Microsoft.OData.Edm
- Added the
EntityType
property toIEdmNavigationSource
interface to make it easier to retrieve the entity type from a navigation source without having to perform a type cast.
Planned changes in Version 8.0.0
This section contains a list of planned changes that are expected to make it to the official 8.0.0 release that are not available in the first preview.
Planned changes in Microsoft.OData.Core
- Make
ODataUtf8JsonWriter
the default JSON writer implementation. - Use
ValueTask<T>
instead ofTask<T>
for async I/O operations where applicable. - Allow customers to include custom annotations in the payload that are not included in the
include-odata-annotations
preference header. - When writing the
Scale
attribute in XML CSDL, writevariable
in lowercase instead ofVariable
. - Change the
ODataLibraryCompatibility
enum into a flags enum where each bit will represent a different compatibility setting that can be used to enable some legacy serializaiton behaviour. - Remove deprecated APIs and behavior flags.
Is it still the intent with v8+ to use the Extensions Library for Client-based integration with Dependency Injection?
Also, will it ever be possible to use a custom name for the generated DataServiceContext class as currently we can only customise the namespace and file name?
Thanks,
Damien
It is great to see the progress with OData 8. Can we expect that the Blazor Webassembly clients will be able to use OData 8 without any restrictions as well? It would be a great experience to have a powerful and full featured data service interface available for webassembly clients…
Looking forward to a series of “Power of .NET” articles showing the benefits of rolling this out across M365 (Graph, SharePoint, Dynamics, etc.) – all desperately could use a consistency, functionality, and performance modernization in their OData implementations!
@Clement The only request I would make is to make sure it is easy to do the following:
* Take a LINQ query on the client and convert it to it’s OData representation. Give us lots of flexibility to send that OData representation to a server. Then allow us to reconstruct it back from the OData representation into an IQueryable on the server, where we can further manipulate, such as adding additional .Where clause, etc.
While I found I could do that with v7 following your standard patterns (using an ASP.NET Controller), I found it difficult to drop down to a lower level with the existing library. I spend at least a full day trying to get this to work, and almost got there before I gave up.
I suspect this might not require more work, and might just require better documentation and examples. But I would love if it was clearer how to break down to a lower level without needing to spend weeks trying to understand the internal architecture of the libraries.
All the best to your team and we look forward to the next release.
Hello David Taylor. Let me see if I understand the question: You would like an easy way to convert a LINQ query to an OData representation and from OData representation back to an IQueryable in a way that’s easy to manipulate? Would you share some of the challenges you’re currently facing using existing methods. One request we have received and are considering is to decouple the LINQ-to-OData query string and OData query string-to-IQueryable into standalone components that can be used with minimal dependencies on other parts of the libraries. I’d like to understand whether something along this direction would address your concerns. Could you open up an issue or discussion on GitHub at https://github.com/OData/odata.net so we can flesh out all the details to understand the requirements better?
Hi @Clément thanks for responding.
Yes what you have described is exactly what I am asking for (just some decoupling, or alternatively some additional examples explaining how to achieve this with the existing coupling). So converting form LINQ query to OData; or from OData to IQueryable with full control.
It was just that I spent a full day trying to work that out myself with the V7 libraries, searching for various examples, and trying to step through parts of the library. I kept hitting a context object, that then needed some other object. It was the coupling that threw me off a bit and as someone who did not really understand the internals I just found it to be really difficult where my expectation was it would have been simple. On the weekend I will take another look and raise an issue, but the existing request you have cited is effectively the same as what I am asking for; or alternatively just some good documentation on how to achieve this scenario in the simplest way even with the existing coupling in place (such as with dummy context objects, etc).
I like the updates to the “Microsoft.OData.Client”!
What I would like to ask though, is, what’s the OData teams opinion on generating OData clients with Kiota? The Microsoft Graph API is an OData API, and Kiota is used to generate the Microsoft Graph SDK… so it seems logical for me to also go that route.
This is not meant to discard or disrespect your work, I am just curious.
Do be careful @bytefish as I have been through a world of pain with Graph and OData. The older (OData / Connected Services) sharepoint API had great OData support, while Graph’s support is very lacking (at least viaLINQ). For example you could have a much more complex C# LINQ query translated to OData before Graph (and also today using these Microsoft.OData libraries) compared to Graph. For example try creating an items array of a few strings, then using an i => items.Contains(i) in a predicate. Graph (at least to sharepoint) will not translate that, while the older APIs do.
Then the most recent few versions of Graph don’t serialize certain field types in sharepoint unless you use the Kioto serializer against that specific field.
Basically it can be a world of pain. Maybe think of Graph as supporting some light OData usage, and probably not via C# and LINQ.
But these Microsoft.OData libraries are fantastic. You can string together all kinds of magic with these libraries. Keep up the good work.
It’s great to see the commitment to OData! I have tried to update my sample project (https://github.com/bytefish/WideWorldImporters) to the latest Previews, but the latest version of “Microsoft.AspNetCore.OData” requires a version of “Microsoft.Spatial” less than 8.0.0. So I’ll run into version conflicts, when trying to update “Microsoft.Spatial” to the 8.0.0-preview. Is it possible to also do a pre-release for “Microsoft.AspNetCore.OData” with updated dependency constraints?
Hello, we’ll soon release a version of Microsoft.AspNetCore.OData that supports the new versions of OData Core, Edm, and Spatial libraries.
Hi there! When do you plan to release the mentioned version of Microsoft.AspNetCore.OData with all the support? Thanks
We’ll release a new preview version of Microsoft.AspNetCore.OData by June 7 based on the recently released Microsoft.OData.Core 8.0.0-preview.3
I have been able to update to the latest preview3 versions. It worked without any problems. Great work! 👍