Search code examples
c#.netasp.net-mvcasp.net-coreaspnet-api-versioning

ASP Versioning, UrlSegmentApiVersionReader, routes match nonsense version numbers


I am using the ASP Versioning library to version an MVC controller Rest API in a microservice.

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

[ApiController]
[ApiVersion("1")]
[ControllerName("example")]
[Route("v{version:apiVersion}/[controller]")]

within this controller I have a few actions, e.g. one to get the version:

[HttpGet("version")]
[Produces("text/plain")]
[ProducesResponseType(StatusCodes.Status200OK)]
public IActionResult GetVersion() => ...

If I perform a curl GET operation with any version number, I get the matched route for version. In some ways this is not surprising, because I am using version neutral matching for the action. However, given that the controller route has an [ApiVersion] of 1 only, I expected any other non-declared version number to result in a 404 not found.

curl -X GET http://localhost:8127/v1/system/version
0.0.0.0%                                                                                                                                                                                                                                                 
curl -X GET http://localhost:8127/v1337/system/version
0.0.0.0% 

Have I mis-configured this? Is it possible to have non-declared versions rejected rather than matched? With UrlSegmentApiVersionReader the default (and assume by default) is not specified for my code, as all versions have be explicitly provided for URL versions.

services.AddApiVersioning(opt =>
{
    opt.ApiVersionReader = new UrlSegmentApiVersionReader();
}).AddApiExplorer(opt =>
{
    opt.GroupNameFormat = "'v'V";
});

I have followed the example provided here under ASP.NET Core with MVC (Core)


Solution

  • What should happen if an API version doesn't match has long been a gray area. No scenario highlights it more than when versioning by URL segment. It's just one of the many issues with using that method of versioning (as well as not being RESTful).

    The existing behavior is to return 400. Starting in API Versioning 6.0, there are changes to the routing extensions that will lead to 404 when versioning by URL segment in some cases - but not all. In the cases that are not 404, the response is still 400. This is primarily to retain backward compatibility. If you want to return 404 instead, there is a simple escape hatch. You just need set the option:

    builder.Services
           .AddApiVersioning(options =>
            {
                options.ApiVersionReader = new UrlSegmentApiVersionReader();
                options.UnsupportedApiVersionStatusCode = 404;
            })
           .AddMvc()
           .AddApiExplorer(options => options.GroupNameFormat = "'v'V");
    

    This will still produce ProblemDetails if they are configured, but the status code will be 404 instead of 400.