ASP.Net Web API Versioning

In this tutorial, we are going to see how to support versioning for ASP.Net Web API endpoints. Versioning helps API owners to roll out enhanced functionalities to different customers on a time to time basis without breaking the old versions of endpoints. Usually we achieve versioning in Web API by creating a custom IHttpControllerSelector through which we will route the request to appropriate controller version based on custom header or URL pattern. Thanks to Chris Martinez for creating aspnet-api-versioning nuget, through which versioning was made easy.

Primarily API versioning can be done either through URL or with custom header. I personally prefer custom header approach, because in this case URL’s will be much cleaner and more inclined towards Restful nature.

Lets get started by creating a new Visual Studio Solution using VS Community 2015 Update 3 with name AspNetWebApi. Select Web API template.

image

Add the following Microsoft.AspNet.WebApi.Versioning nuget package (Right click References –> Manage Nuget Packages).

image

Now lets configure the versioning of Web API in Configuration method of Startup class. We are using HTTP Header based versioning. I removed Web API’s default files like RouteConfig.cs, WebApiConfig.cs etc., and made all the required configuration in Startup class as shown below.

using Microsoft.Owin;
using Owin;
using System.Web.Http;
using Microsoft.Web.Http.Versioning;
using Microsoft.Web.Http;

[assembly: OwinStartup(typeof(AspNetWebApi.Startup))]

namespace AspNetWebApi
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var configuration = new HttpConfiguration();
            var httpServer = new HttpServer(configuration);
            
            configuration.AddApiVersioning(o =>
            {
                o.ReportApiVersions = true;
                o.AssumeDefaultVersionWhenUnspecified = true;
                o.DefaultApiVersion = new ApiVersion(2, 0);
                o.ApiVersionReader = new HeaderApiVersionReader("api-version");
                o.ApiVersionSelector = new CurrentImplementationApiVersionSelector(o);
            }
            );
            configuration.MapHttpAttributeRoutes();
            app.UseWebApi(httpServer);
        }
    }
}

As shown above, we have different configuration options available for API versioning middleware.

ReportApiVersions: Will be used to send the supported API versions in response to the client.

AssumeDefaultVersionWhenUnspecified: Will be used to serve the request without a version. The assumed API version by default would be 1.0.

ApiVersionReader: This is used to configure the way API version is passed to server from client – URL Pattern, Query string or Request Header. In above sample, I have used custom Request header called api-version. We can create our own implementations of IApiVersionReader to support other formats like Accept header.

DefaultApiVersion: This property is used to specify default API version to be used when no version is specified in the request. This will default the version to 1.0.

ApiVersionSelector: This property is used to get more control on version selection process. If no API version is specified in the request and we want to have a default API version selection based on custom logic, then this property can be used. For example, lets say we have four versions – 1.0, 2.0, 3.0, 3.1-alpha. In above sample we have used Current Implementation Selector, now when a request comes without a version, then the latest stable version will be used i.e., 3.0. Similarly we can create our own implementation of IApiVersionSelector and have our own custom logic. If the outcome of this property got no match, then the logic will be fall backed to DefaultApiVersion.

There are other properties like CreateBadRequest (which can be used to send version related bad responses to client for example version not found) and Conventions (used to configure the versions for controllers and actions without using attributes through HasApiVersion and MapToApiVersion extension methods).

Lets create different API versions of same controller under different namespaces as shown below.

using Microsoft.Web.Http;
using System.Web.Http;

namespace AspNetWebApi.Controllers
{
    [ApiVersion("1.0")]
    [Route("api/values")]
    public class ValuesController : ApiController
    {
        public IHttpActionResult Get() => Ok("Value1");
    }

    [ApiVersion("2.0")]
    [Route("api/values")]
    public class Values2Controller : ApiController
    {
        public IHttpActionResult Get() => Ok("Value2");
    }

    [ApiVersion("3.0")]
    [Route("api/values")]
    public class Values3Controller : ApiController
    {
        public IHttpActionResult Get() => Ok("Value3");
    }

    [ApiVersion("3.1-alpha")]
    [Route("api/values")]
    public class Values4Controller : ApiController
    {
        public IHttpActionResult Get() => Ok("Value3-alpha");
    }
}

Now lets use Postman tool to evaluate the results.

When we make a request without an API version, we will get 3.0 results. This is because we have selected ApiVersionSelector to CurrentImplementationApiVersionSelector. If we remove CurrentImplementationApiVersionSelector, we will get 2.0 results because DefaultApiVersion is configured to 2.0.

image

Lets make a request with api-version header pointed to 3.1-alpha. We will 3.1-alpha version results.

image

If we look at the response headers, we will get the allowed versions.

image

That’s it for now, Happy Coding and Stay Tuned!!!

You may also like...