In our current project we are using oData V4 with .Net Core 2.0. Everything woked fine using different filters and query options until we started working with enumertaions. It was important to us to have the enumatraions represented as a string so we can use the enum-value itself as a filter – and not a represented number.
The field Status
is represented as an enum within the c# code like
public enum StatusEnum { Pending, Processing, Done, Canceled, Error }
As an example here is an oData-request fetching all jobs where the field Status
equals Error
:
http://localhost:12345/odata/jobs?$count=true&$filter=Status%20eq%20%27Error%27&$skip=0&$top=10
We received the following error calling the URL mentioned above:
{"@odata.context":"http://localhost:12345/odata/$metadata#Edm.String","value":"The query specified in the URI is not valid. A binary operator with incompatible types was detected. Found operand types 'Models.StatusEnum' and 'Edm.String' for operator kind 'Equal'."}
After a lot of coffee and search-engine consulting I have found several possible solutions, but none worked for me. Either they used a different .net core version, or a different oData version or did not use MVC or whatever.
But finally I managed to implement a version that worked with my setup:
Within the startup.cs
in the function Configure
– I inserted the following code-block:
public void Configure( ... ) { // some stuff... app.UseMvc(config => { config.Count().Filter().OrderBy().Expand().Select().MaxTop(null); // enable oData query options Microsoft.OData.Edm.IEdmModel model = GetEdmModel(app.ApplicationServices); ODataUriResolver resolver = new ODataUriResolver(); // his is where the magic happens: to resolve enumerators as string resolver = new StringAsEnumResolver(); config.MapODataServiceRoute("odata", "odata", builder => builder .AddService(Microsoft.OData.ServiceLifetime.Singleton, sp => model) .AddService<IEnumerable<IODataRoutingConvention>>(Microsoft.OData.ServiceLifetime.Singleton, sp => ODataRoutingConventions.CreateDefaultWithAttributeRouting("odata", config)) .AddService(Microsoft.OData.ServiceLifetime.Singleton, sp => resolver)); [..] // perhaps insert some routing here... config.EnableDependencyInjection(); }); // some other stuff } private Microsoft.OData.Edm.IEdmModel GetEdmModel(IServiceProvider provider) { var builder = new ODataConventionModelBuilder(provider); builder.EntitySet<SomeClass>("someClasses").EntityType.Expand(SelectExpandType.Automatic); [...] // insert other model-classes here return builder.GetEdmModel(); }
I hope this saves you some searching-time and frustration.
Happy coding!