0
votes

I'm having trouble getting OData to work in a new .NET Core WebAPI solution (.NET 5.0).

I am getting data back via the standard "/api/entity" and using a custom filter, but I'd much prefer using the OData built-in $select, $filter, $count, $metadata, etc. features.

I've added the nuget package for Microsoft.AspNetCore.OData v7.5.8, and added the following to my Startup.cs:

ConfigureServices()...    
services.AddOData();
    
Configure()...
endpoints.MapODataRoute("odata", "odata", GetEdmModel()).Select().Filter().Expand().Count();

And the EDM Model method:

private static IEdmModel GetEdmModel()
        {
            ODataConventionModelBuilder builder = new();
            builder.EntitySet<Event>("Events");
            return builder.GetEdmModel();
        }

Everything compiles, and if I hit [rooturl]/odata, I see my entity, so I see it's basically working (I think).

However if I go to: [rooturl]/odata/events(1) I get page not found... however if I use the default [rooturl]/api/events/1 route, it works perfectly.

This is my first .NET Core WebAPI, after building countless .NET Standard WebForms, WCF, MVC, and WebAPI solutions. I am sure I'm just missing something simple... but I cannot figure out what.

I would like to be able to use OData like this:

[rooturl]/odata/Events?$top=10
[rooturl]/odata/Events?$filter=name eq "foo"
[rooturl]/odata/Events?$select=id,name,status

In .NET Standard MVC, OData functionality was available right off the bat. How do I get that with .NET Core?

Anyone have suggestions on what to add to get this wired up properly?

Many thanks in advance.

1

1 Answers

0
votes

After referring to one of my old WebAPI solutions (.NET Framework 4.8 MVC), I figured it out. Thankfully, most of the old patterns still work in .NET Core.

Posting the solution for those who may run into the same issues.

The Startup.cs needs the following code:

ConfigureServices()...
services.AddOData();

Configure()...
// removed app.UseUseMvc()...replaced with this...

app.UseEndpoints(endpoints =>
{
    //endpoints.EnableDependencyInjection();
    endpoints.Select()
             .OrderBy()
             .Filter()
             .SkipToken()
             .MaxTop(null)
             .Expand()
             .Count();
    endpoints.MapODataRoute("api", "api", GetEdmModel());
});

GetEdmModel()...
ODataConventionModelBuilder builder = new();
var events = builder.EntitySet<Events>("Events");            
return builder.GetEdmModel();

On the controller:

Add annotation [EnableQuery] to methods. Set output to IQueryable<Events> (and make sure you return the collection AsQueryable().

That did the trick and now I'm seeing all the OData options I need for this collection.