0

I try to versioning ASP.NET Core MVC API with Asp.Versioning.Mvc.

I create a new project like :

dotnet new webapi --framework net7.0
dotnet add package Asp.Versioning.Mvc --version 7.0.1

Next, I remove all controllers and edit Program.cs like :

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

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddApiVersioning();


var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();


app.Run();


[ApiVersion(1.0)]
[Route("api/v{version:apiVersion}/helloworld")]
public class HelloWorldController : ControllerBase
{
    public string Get() => "Hello world! v1";
}

[ApiVersion(2.0)]
[Route("api/v{version:apiVersion}/helloworld")]
public class HelloWorld2Controller : ControllerBase
{
    public string Get() => "Hello world! v2";
}

But when I start the API and call http://localhost:5069/api/v1.0/helloworld, I get this error :

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

HelloWorldController.Get (ApiVersioningPoc)
HelloWorld2Controller.Get (ApiVersioningPoc)
   at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ReportAmbiguity(CandidateState[] candidateState)
   at Microsoft.AspNetCore.Routing.Matching.DefaultEndpointSelector.ProcessFinalCandidates(HttpContext httpContext, CandidateState[] candidateState)
   at Microsoft.AspNetCore.Routing.Matching.DfaMatcher.MatchAsync(HttpContext httpContext)
   at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

I found this similar question :

Asp.Versioning.Http AmbiguousMatchException: The request matched multiple endpoints on controllers

I try to add AddMvc (from the answer) without success.

vernou
  • 6,818
  • 5
  • 30
  • 58

1 Answers1

2

You definitely need AddMvc() after the AddApiVersioning() part because you are using Controllers instead of the Minimal APIs approach in this example.

After that you need to add the [ApiController] attribute to both of your Controllers like this:

[ApiVersion(1.0)]
[ApiController]
[Route("api/v{version:apiVersion}/helloworld")]
public class HelloWorldController : ControllerBase
{
    public string Get() => "Hello world! v1";
}

[ApiVersion(2.0)]
[ApiController]
[Route("api/v{version:apiVersion}/helloworld")]
public class HelloWorld2Controller : ControllerBase
{
    public string Get() => "Hello world! v2";
}

The library needs this attribute setup for all of your controller to work properly.

Jonas Weinhardt
  • 913
  • 4
  • 11
  • Sound like I miss `[ApiController]` on controllers. Thank. – vernou Aug 30 '23 at 14:37
  • 2
    It's also worth mentioning that if you don't want apply the attribute to each controller **and** all of your controllers are API controllers, then you can apply the attribute to the assembly for all controllers just once. E.g. `[assembly: ApiController]` – Chris Martinez Aug 30 '23 at 15:10