It seems that I can't get the API Versioning System to work in my setup.
Given the following NuGet Packages:
The following services are registered:
services.AddMvcCore()
.AddJsonFormatters();
services.AddApiVersioning(apiVersioningOptions =>
{
apiVersioningOptions.ReportApiVersions = true;
apiVersioningOptions.ApiVersionReader = new HeaderApiVersionReader("API");
});
This is my controller implementation:
[ApiVersion( "1.0" )]
[ApiVersion( "2.0" )]
[Route("api/[controller]")]
public sealed class LogController : Controller
{
[HttpPost]
[MapToApiVersion("1.0")]
public IActionResult CreateLogEventV1()
{
return Ok("Response from Version 1.0");
}
[HttpPost]
[MapToApiVersion("2.0")]
public IActionResult CreateLogEventV2()
{
return Ok("Response from Version 2.0");
}
[HttpOptions]
public IActionResult Options()
{
return Ok();
}
}
Given the following HTTP Request:
POST /api/log? HTTP/1.1
Host: localhost:5000
API: 1.0
cache-control: no-cache
The following data is returned:
{
"error": {
"code": "UnsupportedApiVersion",
"message": "The HTTP resource that matches the request URI 'http://localhost:5000/api/log' does not support the API version '1.0'.",
"innerError": null
}
}
The same is true when I'm making a request with the API HTTP Header value set to 2.0
Given the following call:
OPTIONS /api/log HTTP/1.1
Host: localhost:5000
cache-control: no-cache
A 200 Status Code is returned, but the available API Versions are not available in the HTTP Response Headers.
Am I missing something here or is there a bug in the API Versioning package?
This is happening because your controller _looks_ like a UI controller to API versioning (now). This is a behavioral change starting in 3.1+ and is called out in the release notes. Many people have asked for this behavior, but it wasn't feasible until there was a hard dependency on ASP.NET Core 2.1+, which first occurred in 3.1 of API Versioning.
To resolve your issue, do one of the following:
Decorate your controller with [ApiController]:
```c#
[ApiVersion( "1.0" )]
[ApiVersion( "2.0" )]
[ApiController]
[Route( "api/[controller]" )]
public sealed class LogController : Controller
{
[HttpPost]
[MapToApiVersion( "1.0" )]
public IActionResult CreateLogEventV1() => Ok( "Response from Version 1.0" );
[HttpPost]
[MapToApiVersion( "2.0" )]
public IActionResult CreateLogEventV2() => Ok( "Response from Version 2.0" );
[HttpOptions]
public IActionResult Options() => Ok();
}
#### Option 2
Disable API behaviors. The default is now `true`.
```c#
services.AddApiVersioning( options => options.UseApiBehavior = false );
Define a custom IApiControllerSpecification that determines whether a controller is an API controller. The documentation as well as an example is provided in the UseApiBehavior wiki topic.
You would likely choose this option if you have a lot of controllers that inherit from ControllerBase instead of Controller and you don't want to apply [ApiController] to them all. You might also choose this option based on how your code is segmented. For example, maybe all of your API controllers are in a folder and namespace which you can apply an IApiControllerSpecification rather than [ApiController].
I hope that helps.
Thanks for clearing this out.
Most helpful comment
This is happening because your controller _looks_ like a UI controller to API versioning (now). This is a behavioral change starting in 3.1+ and is called out in the release notes. Many people have asked for this behavior, but it wasn't feasible until there was a hard dependency on ASP.NET Core 2.1+, which first occurred in 3.1 of API Versioning.
To resolve your issue, do one of the following:
Option 1
Decorate your controller with
[ApiController]:```c#
[ApiVersion( "1.0" )]
[ApiVersion( "2.0" )]
[ApiController]
[Route( "api/[controller]" )]
public sealed class LogController : Controller
{
[HttpPost]
[MapToApiVersion( "1.0" )]
public IActionResult CreateLogEventV1() => Ok( "Response from Version 1.0" );
}
Option 3
Define a custom IApiControllerSpecification that determines whether a controller is an API controller. The documentation as well as an example is provided in the UseApiBehavior wiki topic.
You would likely choose this option if you have a lot of controllers that inherit from ControllerBase instead of Controller and you don't want to apply
[ApiController]to them all. You might also choose this option based on how your code is segmented. For example, maybe all of your API controllers are in a folder and namespace which you can apply an IApiControllerSpecification rather than[ApiController].I hope that helps.