dotnet / aspnet-api-versioning

Provides a set of libraries which add service API versioning to ASP.NET Web API, OData with ASP.NET Web API, and ASP.NET Core.
MIT License
3.03k stars 702 forks source link

'api-supported-versions' not working as expected #561

Closed bobznguo closed 4 years ago

bobznguo commented 4 years ago

Hi,

Thanks for the great library!

V1/ValuesController.cs

    [ApiVersion("1")]
    [RoutePrefix("api/v{version:apiVersion}/values")]
    public class ValuesController : ApiController
    {
        // GET api/values
        [Route("")]
        public virtual IEnumerable<string> Get()
        {
            return new string[] { "version 1" };
        }
    }

V2/ValuesController.cs

    [ApiVersion("2")]
    [RoutePrefix("api/v{version:apiVersion}/values")]
    public class ValuesController : Controllers.ValuesController
    {
        [Route("")]
        public override IEnumerable<string> Get()
        {
            return new string[] { "version 2" };
        }

        // New Api endpoint which is only avaiable in version 2
        [Route("{id}")]
        public virtual string Get(int id)
        {
            return "value";
        }
    }

WebApiConfig.cs

        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            // Web API routes
            var constraintResolver = new DefaultInlineConstraintResolver
            {
                ConstraintMap =
                {
                    ["apiVersion"] = typeof( ApiVersionRouteConstraint )
                }
            };

            // Web API routes
            config.MapHttpAttributeRoutes(constraintResolver);
            config.AddApiVersioning(opt => opt.ReportApiVersions = true);
        }

packages.config

 <package id="Microsoft.AspNet.WebApi" version="5.2.4" targetFramework="net452" />
 <package id="Microsoft.AspNet.WebApi.Core" version="5.2.4" targetFramework="net452" />
 <package id="Microsoft.AspNet.WebApi.Versioning" version="3.0.4" targetFramework="net452" />

With the above code, if I call /api/v2/values/1, the 'api-supported-version' in the response header is:

api-supported-versions : 1, 2

But apparently /api/v2/values/{id} is only available in version 2. Seems to me that the inheritance (ValuesController version 2 inherits from version 1) is causing the confusion here.

Is this intentional or is this actually a bug?

Thanks.

commonsensesoftware commented 4 years ago

This is by design. Inheritance isn't a factor here. The aggregation of supported and deprecated versions doesn't inspect or otherwise consider route templates. To do so is quite complex and there are a number of edge cases which have to be considered; for example, api/values/{id} and api/values/{id:int} are semantically equivalent. There are other considerations such as the supported HTTP methods. The intention is to advertise the versions of api/values in totality, but not its individual actions. There's no easy way to convey that in this context. The API Explorer (which can be used with Swagger/OpenAPI) provides more robust information. Naturally, if you request an unsupported version, you'll get the correct behavior, but rolling things up isn't as simple as it may seem.

In practice, it's been my experience that clients usually onboard to api/values/*. The purpose of these headers is to let a client know that a particular version will go away or a new version is available. Stepping up a version usually involves changing an entire suite of APIs and/or regenerating a code-generated client.

I hope that helps clears things up.

bobznguo commented 4 years ago

Thanks for the detailed answer.

Okay, understood. However, still think it would be great if individual actions can also be taken into account when advertising the versions of api/values because we don't want the clients to think that the new endpoint api/values/{id:int} which is added to api/v2/values is also available in api/v1/values. Fortunately, when I use the API Explorer with Swagger, it only shows api/values/{id:int} in version 2.

Hope that it is something that could be considered in future releases.