Search code examples
c#asp.net-core-webapiaspnet-api-versioning

Keep getting AmbiguousMatchExceptions with aspnet-api-versioning


I'm sure it's just me, but after using multiple sources, approaches, and many takes, I just can't seem to get even the simplest example of aspnet-api-versioning to work. I keep getting AmbiguousMatchExceptions for different versions of an endpoint. What am I doing wrong? What should I change in order to make it work?

using Asp.Versioning;
using Microsoft.AspNetCore.Mvc;

internal class Program
{
    private static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);
        builder.Services.AddControllers();

        builder.Services
            .AddApiVersioning()
            .AddMvc();

        var app = builder.Build();
        app.MapControllers();
        app.Run();
    }
}

[ApiVersion("1.0"), Route("v{version:apiVersion}/hello")]
public class HelloV1Controller : ControllerBase
{
    [HttpGet]
    public string Get() => "v1";
}

[ApiVersion("2.0"), Route("v{version:apiVersion}/hello")]
public class HelloV2Controller : ControllerBase
{
    [HttpGet]
    public string Get() => "v2";
}

Solution

  • This is happening because the setup is incomplete. It should be:

    builder.Services.AddApiVersioning().AddMvc();
    

    The names are intentionally similar, but contrary to some people's belief, this doesn't add the full MVC stack. API Versioning 6.0 adds a new IApiVersioningBuilder so that all related extensions can be grouped together. Minimal APIs are supported in 6.0, which means there is no longer any dependency on any part of MVC Core. This is what AddApiVersioning() now does. To add in MVC Core to support controllers the way that it worked in previous versions, you have to call AddMvc(). This gives you the most flexiblity in choosing how you want to version your APIs. You can even mix and match Minimal APIs and controllers.

    For quick reference, here is the gambit of configuration options:

    services.AddApiVersioning()     // Core API Versioning services with support for Minimal APIs
            .AddMvc()               // API version-aware extensions for MVC Core
            .AddApiExplorer()       // API version-aware API Explorer extensions
            .AddOData()             // API versioning extensions for OData
            .AddODataApiExplorer(); // API version-aware API Explorer extensions for OData
    
    

    Obviously, if you're not using the API Explorer or OData packages, those extensions do not apply.

    In addition, each controller must be decorated with [ApiController] so that API Versioning can disambiguate between an API controller and a UI controller, which otherwise have the same base type. You can also use [assembly: ApiController] to make all controllers in the project an API controller.

    AddEndpointsApiExplorer() is completely unrelated. If you're not using Minimal APIs, then it's unnecessary. If you're adding OpenAPI to document your APIs, then you'll want to add the API Explorer extensions.

    There are a lot of notes in the discussions and release notes, but the documentation isn't up-to-date. There is an issue tracking that and updates are coming. The best place to start for reference is to look at the latest examples.