srikanth kolla
srikanth kolla

Reputation: 21

AspNetCore 3.1 routing AmbiguousMatchException

I am trying to migrate my webapp from .net core 2.1 to 3.1 and in the process changed the routing to app.UseRouting() and app.UseEndpoints(default endpoint) method and removed app.UseMvc() as mentioned in the breaking changes document.

https://learn.microsoft.com/en-us/dotnet/core/compatibility/2.2-3.1#shared-framework-removed-microsoftaspnetcoreall

Post that, facing this issue.

Details

I have 3 controllers mentioned below in the code which are correctly versioned using the attributes

Example of V2 Controller


    [Microsoft.AspNetCore.Mvc.ApiVersion("2.0")]
    [Route("v{version:apiVersion}")]

Controllers have similar actions methods and when I try to hit any action (example: http://localhost:xxxx/v1/GetData). I get the below exception.

Microsoft.AspNetCore.Routing.Matching.AmbiguousMatchException: 'The request matched multiple endpoints. Matches:


    Stateless1.Controllers.V3.SAPClientV3Controller.GetSap (SampleWebApp)
    Stateless1.Controllers.V2.SAPClientV2Controller.GetSap (SampleWebApp)
    Stateless1.Controllers.V1.SAPClientController.GetSap 

PS: I have tested by removing this action method in rest of the two controllers and the call got through to the other controller irrespective of v1 or v2 or v3 in the http://localhost:xxxx/v1/GetData URL.

The code which supports multiple api versioning is also present in the start up.


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

Upvotes: 2

Views: 1325

Answers (1)

rjso
rjso

Reputation: 1614

I had the exact same issue, and I found this ticket in microsoft's github issues https://github.com/microsoft/aspnet-api-versioning/issues/574

We need to specify the [ApiController] parameter so that the API versioning kicks in. This only started to happen when I migrated from dotnet core 2.0 to 3.1

For clarity here is what works:

     [ApiController]
        [ApiVersion("1.0")]
        [Route("api/v{version:apiVersion}/[controller]")]
        public class MyController : Controller
        {
            [MapToApiVersion("1.0")]
            public async Task<IActionResult> MethodA([FromBody] int? id)
            {
              return Ok();
            }
        }
        }



[ApiController]
        [ApiVersion("2.0")]
        [Route("api/v{version:apiVersion}/[controller]")]
        public class MyControllerV2 : Controller
        {
            [MapToApiVersion("2.0")]
            public async Task<IActionResult> MethodAV2([FromBody] int? id)
            {
              return Ok();
            }
        }
        }

I gave V2 names for the sake of the example, but I believe the best way to version is to use it with namespaces like V2.Home.MyController

Upvotes: 4

Related Questions