Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AssumeDefaultVersionWhenUnspecified is not working as expected

I have been using asp net core versioning component for my WebAPI. Need your help in understanding how AssumeDefaultVersionWhenUnspecified is working. (tried searching for documentation, but couldn't find one)

My startup looks like below

services.AddApiVersioning(o => {
            o.ReportApiVersions = true;
            o.AssumeDefaultVersionWhenUnspecified = true;
            o.DefaultApiVersion = new ApiVersion(2, 0);
            o.ApiVersionReader = new UrlSegmentApiVersionReader();
        });

When the route attribute is something like below

[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/values")]
[ApiController]
public class ValuesV2Controller : ControllerBase
{
...
}

The above route works only when the api version is specified. ie: http://localhost:55401/api/v2/values If I call like http://localhost:55401/api/values, getting 404 error

My question is this... How AssumeDefaultVersionWhenUnspecified works. Wouldn't it ignore the version in Route? Looks like Route attribute takes precedence over AssumeDefaultVersionWhenUnspecified. If I choose QueryString or Header versioning and when the Route looks like

[ApiVersion("2.0")]
[Route("api/values")]

the default routing reaches the API

Am I missing anything or is my understanding wrong? How shall I achieve default routing to the latest version API using url versioning?

like image 668
Athi S Avatar asked Sep 25 '18 03:09

Athi S


2 Answers

I am also trying to achieve the same functionality. By looking into [https://github.com/Microsoft/aspnet-api-versioning/issues/351#issuecomment-425106940] I am assuming that we can't achieve default API version AssumeDefaultVersionWhenUnspecified functionality with only a single style of versioning uses a URL segment [Route("api/v{version:apiVersion}/[controller]")]

We have to define two routes separately as follow

  1. [Route("api/[controller]")]
  2. [Route("api/v{version:apiVersion}/[controller]")]

and to hide the two implementations from swagger you can achieve using this link

like image 89
Niraj Trivedi Avatar answered Nov 13 '22 18:11

Niraj Trivedi


Summarizing the the solution from the github issue linked by Athi S, here's what you need to do :

In ConfigureServices inside Startup.cs file :

        services.AddApiVersioning(o =>
        {
            o.AssumeDefaultVersionWhenUnspecified = true;
            o.ApiVersionSelector = new CurrentImplementationApiVersionSelector(o);
            //  o.DefaultApiVersion = new ApiVersion(1, 0);
        });

You can optionally set ApiVersionSelector to a new instance of CurrentImplementationApiVersionSelector. What this does is, it automatically selects the highest api version registered in controllers. E.g. A controller decorated with [ApiVersion("1.2")] takes precedence over [ApiVersion("1.1")].

If you want to specify default api version explicitly, you can do so by leaving ApiVersionSelector to DefaultApiVersionSelector and setting DefaultApiVersion to your required api version.

In your controllers :

Register the required routes by decorating your controllers with the given Route attributes

[Route("api/[controller]")]

Or if you want the api to work both with and without the api version number specified, you can do so by declaring two routes for the controller.

[Route("api/[controller]")]
[Route("api/v{version:apiVersion}/[controller]")]
like image 43
chaosifier Avatar answered Nov 13 '22 16:11

chaosifier