Resolve enumerations as string in URL when using oData in .net Core 2.0

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

As an example here is an oData-request fetching all jobs where the field Status equals Error:


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...
        // some other stuff

   private Microsoft.OData.Edm.IEdmModel GetEdmModel(IServiceProvider provider)
        var builder = new ODataConventionModelBuilder(provider);
    [...] // insert other model-classes here
        return builder.GetEdmModel();

I hope this saves you some searching-time and frustration.
Happy coding!

Schreibe einen Kommentar