question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Route conflicts after switching from ODataConventionModelBuilder to VersionedODataModelBuilder

See original GitHub issue

Hi, I have an AspNetCore 2.2 web application which uses ODataControllers, ApiControllers, AspNetCore routing, OData attribute routing, Api exploring, and swagger all at once. This setup used to work before I throw Api versioning into the mix, using both asp convention routing and odata routing on different route prefixes. OData models used to get build by this code:

var odataConfig = serviceProvider.GetRequiredService<ODataConfig>();

             //Enabling OData routing.
             routes.Select().Expand().Filter().OrderBy().MaxTop(100).Count(); 
             routes.CustomMapODataServiceRoute("odata", "odata", 
                                                 odataConfig.BuildGeneralViewModel(serviceProvider), 
                                                 null, 
                                                 serviceProvider);

             // Workaround: https://github.com/OData/WebApi/issues/1175
            
             routes.EnableDependencyInjection();

which was essentially a straightforward use of new ODataConventionModelBuilder().GetEdmModel() followed by some configurations. Now, after trying to jam in Api versioning, I’m using

//Enabling OData routing.
            routes.Select().Expand().Filter().OrderBy().MaxTop(100).Count();
            var modelBuilder = serviceProvider.GetRequiredService<VersionedODataModelBuilder>();
            routes.MapVersionedODataRoutes("odata", "odata", modelBuilder.GetEdmModels()) ;
            
            // Workaround: https://github.com/OData/WebApi/issues/1175
            routes.EnableDependencyInjection();   

I pretty much followed along the lines depicted by the sample recommended for AspNetCore + OData + Swagger + Api Versioning.

But I get this exception at application start up:

Application startup exception: System.InvalidOperationException: Cannot use 'Microsoft.AspNet.OData.Routing.ODataRoute' with Endpoint Routing.
   at Microsoft.AspNetCore.Builder.MvcApplicationBuilderExtensions.UseMvc(IApplicationBuilder app, Action`1 configureRoutes)

Almost all of my controllers have a scheme of somewhat like this:

    [Produces("application/json")] [ApiConventionType(typeof(DefaultApiConventions))]
    [ApiController] [ApiExplorerSettings(IgnoreApi=false)] [ApiVersionNeutral]
    [Route("Customers")] [ODataRoutePrefix("Customers")]
    public class CustomersController : ODataController
    {
        private readonly IMapper _mapper;
        public CustomersController(..)
        {
            ...
        }

        [HttpGet] [ODataRoute]
        [GuardQuery]
        public IQueryable<Views.Customers.Customer> Get()
        {
			...
        }

        [HttpGet("{id}")] [ODataRoute("({id})")]
        // [ProducesResponseType(200)]
        // [ProducesResponseType(404)]
        [GuardQuery]
        public SingleResult<Views.Customers.Customer> GetById([FromODataUri] long id)
        {
			...
        }

        [HttpPost]
        // [ProducesResponseType(201)]
        // [ProducesResponseType(400)]
        public async Task<ActionResult<Views.Customers.Customer>> Post([FromBody] Views.Customers.Customer value) 
        { 
            ...
        }

Default api version and api version assumption are also already set, as mentioned:

            services.AddODataApiExplorer(options =>
            {
                options.GroupNameFormat = "'v'VVV";
                options.SubstituteApiVersionInUrl = true;
                options.AssumeDefaultVersionWhenUnspecified = true;
                options.DefaultApiVersion = new ApiVersion(1,0);
            });

            services.AddApiVersioning(option =>
            {
                option.AssumeDefaultVersionWhenUnspecified = true;
                option.DefaultApiVersion = new ApiVersion(1,0);
                option.ReportApiVersions = true;
            });

Finally, commenting out the conventional aspnet route (which used to work) does not seem to come of any help:

            app.UseMvc(routes =>
            {
                // routes.MapRoute(
                //     name: "default",
                //     template: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

                routes.UseODataVersioningRoute(app.ApplicationServices);
            });

Please let me know, what am I doing wrong?

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:1
  • Comments:5

github_iconTop GitHub Comments

28reactions
kooshancommented, Oct 7, 2018

Found the solution!

It turned out that Endpoint Routing is a new routing scheme introduced in AspNetCore 2.2 Here.

To work around this problem as of now (until at least ODataRouteAttribute evolve to encompass this new feature) one has two choices. Either fix compatibility version to a version prior to 2.2:

            services.AddMvc()
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Or simply use the MvcOptions to disable EndPoint Rounting altogether:

services.AddMvc(options => 
            {
                // https://blogs.msdn.microsoft.com/webdev/2018/08/27/asp-net-core-2-2-0-preview1-endpoint-routing/
                // Because conflicts with ODataRouting as of this version
                // could improve performance though
                options.EnableEndpointRouting = false;
            })
            .SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

0reactions
lemarcelocommented, Nov 28, 2019

Thanks @kooshan

Read more comments on GitHub >

github_iconTop Results From Across the Web

Route conflicts after switching from ...
Hi, I have an AspNetCore 2.2 web application which uses ODataControllers, ApiControllers, AspNetCore routing, OData attribute routing, ...
Read more >
NET MVC 5 OData Custom Action Bound to Entity with ...
Show activity on this post. I was able to successfully create a custom action and custom function on a route with the following...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found