I'm working on converting an ASP.NET Web API 2 to a .Net 6 Web API and ran into a problem when using Versioning.
The problem I'm running into concerns named routes.
I want my API to be able to be called with the version in the query string, route, and headers. ie:
https://localhost:1234/api/v1/helloworld
https://localhost:1234/api/helloworld?api-version=1.0
https://localhost:1234/api/v2/helloworld
https://localhost:1234/api/helloworld?api-version=2.0
One of my controller methods already has 3 different routes. The reason is because the code is all the same except the call to the database. I use a switch
statement to determine which route
was called. For this, I give each route a name. ie:
[...]
[ApiVersion("1.0")]
[Route("api/[controller]")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class HelloWorldController : ControllerBase {
[HttpGet("1", Name="Route1")]
[HttpGet("2", Name="Route2")]
[HttpGet("3", Name="Route3")]
public async Task<IActionResult> Get() {
List<Car> model;
switch (ControllerContext.ActionDescriptor.AttributeRouteInfo?.Name) {
case "Route1":
model = await _repo.FindByRoute1(...).ToListAsync();
case "Route2":
model = await _repo.FindByRoute2(...).ToListAsync();
case "Route3":
model = await _repo.FindByRoute3(...).ToListAsync();
}
return Ok(model);
}
}
[...]
The error I am getting is
Error 1:
Attribute routes with the same name 'Route1' must have the same template:
Action: 'Controllers.V2.HelloWorldController.Get' - Template: 'api/helloworld/1'
Action: 'Controllers.V2.HelloWorldController.Get' - Template: 'api/v{version:apiVersion}/helloworld/1'
How can I use named routes AND multiple base routes?
Jsut as the error indicates,your controller methods have 6 routes instead of 3 routes,your codes would perform the same as below:
[ApiController]
[Route("api/{version}/[controller]/1", Name = "Route1")]
[Route("api/[controller]/1", Name = "Route1")]
[Route("api/{version}/[controller]/2", Name = "Route2")]
[Route("api/[controller]/2", Name = "Route2")]
[Route("api/{version}/[controller]/2", Name = "Route3")]
[Route("api/[controller]/2", Name = "Route3")]
public class HelloWorldController : ControllerBase
{
.....
}
And in .net core Route names must be unique application-wide as mentioned in this document