0
votes

The main thing I want to do is I want my AspNet.Core 3.1 API to support Odata. The main thing is WebApi exposes Dto object which internally maps to entity object. I have implemented changes however keep getting 404 error. The changes I did were:

  • Install AspNetCore.OData 7.3.

  • Added changes to Startup.cs

public class Startup { public void ConfigureServices(IServiceCollection services) services.AddOData(); services.AddMvc(options => options.EnableEndpointRouting = false);

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
   IEdmModel model = GetEdmModel();
   app.UseMvc(builder =>
   {
            builder.Select().Expand().Filter().OrderBy().MaxTop(100).Count();
            builder.MapODataServiceRoute("odata", "odata", model);
   });

public static IEdmModel GetEdmModel()
    {
        if (_edmModel == null)
        {
            var builder = new ODataConventionModelBuilder();
            builder.EntitySet<CustomerDto>("CustomerDtos");                
            _edmModel = builder.GetEdmModel();
        }
        return _edmModel;
    }

} - CustomersController changes

public class CustomersController : ControllerBase 
{
    public ICustomerRepository _customers;
    public CustomersController(DbContext context)/
    {
        _customers = new CustomerRepository(context);
    }

    [HttpGet]        
    [EnableQuery]
    public async Task<ActionResult<IEnumerable<CustomerDto>>> Get()
    {
        return Ok((await _customers.GetCustomers()).Select(c=>CustomerDto.MapToCustomerDto(c)));
    }
}

However this constantly gives 404 error odata/customers

1

1 Answers

1
votes

If you use url/odata/customers, customers refers to an entity set named Customers. The controller name is always derived from the entity set at the root of the OData path.

Refer to https://docs.microsoft.com/en-us/odata/webapi/built-in-routing-conventions#built-in-routing-conventions-1

Solutions:

One way is keeping EntitySet name but modifying controller name

(CustomersController->CustomerDtosController ):

public class CustomerDtosController : ControllerBase

Url: /odata/customerDtos

Another way is keeping controller name but modifying EntitySet name:

builder.EntitySet<CustomerDto>("Customers");

Url: odata/customers