Aspnet-api-versioning: `UnsupportedApiVersion` is returned always in .NET Core

Created on 11 Jan 2019  路  2Comments  路  Source: microsoft/aspnet-api-versioning

It seems that I can't get the API Versioning System to work in my setup.

Given the following NuGet Packages:

  • Microsoft.AspNetCore.App 2.2.0
  • Microsoft.AspNetCore.Mvc.Versioning 3.1.1

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?

answered asp.net core question

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" );

[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 );

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.

All 2 comments

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" );

[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 );

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.

Thanks for clearing this out.

Was this page helpful?
0 / 5 - 0 ratings