API Versioning in ASP.net Core

By | August 28, 2017

ASP.NET API versioning gives you the ability to improve and iterate on API’s without breaking contracts. At times the stagnation of innovation on an API is simply because of legacy decisions that cannot be reversed, especially on public API’s. But versioning can quickly get out of control, especially with custom implementations. The API versioning extensions define simple metadata attributes and conventions that you use to describe which API versions are implemented by your services.

Before implementing versioning in your application you should install required package from nuget package manager as below.

or via nuget package console:

Install-Package Microsoft.AspNetCore.Mvc.Versioning

In the ConfigureServices method of your startup.cs, you need to add the API Versioning services like so :

public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();

//Add Versioning
services.AddApiVersioning(x =>
{
x.ReportApiVersions = true;
x.AssumeDefaultVersionWhenUnspecified = true;
x.DefaultApiVersion = new ApiVersion(1, 0);
});
}

ReportAPIVersions: It is used to return versions in a response header. It’s optional.

AssumeDefaultVersionWhenUnspecified: It assume the default API version if we have not specify. For example if we are migrating an existing API to versioning Without it, then you will get an error “An API version is required, but was not specified.” as below image, this will be why.

DefaultApiVersion: It sets the default API version to 1.0 as above code. I thought it helpful to include it as a reminder that you can “auto update” any clients that aren’t specifying a default API version to the latest.

URL Query Based Versioning

Take a look at the following basic controllers. They have been decorated with an ApiVersion attribute.

[ApiVersion("1.0")]
[Route("api/values")]
public class ValuesV1Controller : Controller
{
// GET api/values
[HttpGet]
public string Get()
{
return "Version 1";
}
}

[ApiVersion("2.0")]
[Route("api/home")]
public class HomeV2Controller : Controller
{
// GET api/home
[HttpGet]
public string Get()
{
return "Version 2";
}
}

You’ll notice that the routes are actually the same, so how does ASP.net core determine which class to use?

Actually the default way that the versioning library uses is by using a query string of “api-version” to specify a version.

So when I call /api/home?api-version=2.0, I am returned “Version 2”. When I call /api/values?api-version=1.0 (Or no version at all), I am returned “Version 1”.

 

URL Path Based Versioning

Query string parameters are nice and easy but don’t always look the best (And they can be a pain for an external client to always tag on). In a big long query they can be missed in the sea of query parameters. A common alternative is to put the version in the URL path so it’s always visible at the start of the URL.

Take the following two controllers :

[ApiVersion("1.0")]
[Route("api/{version:apiVersion}/values")]
public class ValuesV1Controller : Controller
{
// GET api/1.0/values
[HttpGet]
public string Get()
{
return "Version 1";
}
}

[ApiVersion("2.0")]
[Route("api/{version:apiVersion}/home")]
public class HomeV2Controller : Controller
{
// GET api/2.0/home
[HttpGet]
public string Get()
{
return "Version 2";
}
}

Now when I call /api/1.0/values, I am returned “Version 2” and /api/2.0/home will return me “Version 2”.

 

Http Header Based Versioning

It is a very common way of using Versioning in Api. It allows your urls to stay clean without cluttering them with version information. To implement, we need add the option of an ApiVersionReader to your AddApiVersioning call in ConfigureServices method in startup.cs file as below :

services.AddApiVersioning(x => 
{ services.AddApiVersioning(x => { x.ApiVersionReader = new HeaderApiVersionReader("api-version");
 });

In above code, we set the version reader to use the header, you can no longer specify the version like so /api/home?api-version=2.0. If you wish to use both, you need to use the aptly named “QueryStringOrHeaderApiVersionReader” which is ridiculous name.

services.AddApiVersioning(x => 
{
services.AddApiVersioning(x => { x.ApiVersionReader = new QueryStringOrHeaderApiVersionReader("api-version"); 
});

Version A Single Action

There may come a time when you want to only create a new version of an action, but not the entire controller (Infact there will be plenty of times). There is a way to do this, but a word of warning is that it will mean at some point in the future, you will have a mismatch of controllers, actions and versions etc. It can be hard to manage.

But to version a single action, you can do something that looks like the following :

[ApiVersion("1.0")]
[ApiVersion("2.0")]
[Route("api/home")]
public class HomeController : Controller
{
[HttpGet]
public string Get()
{
return "Version 1";
}

[HttpGet, MapToApiVersion("2.0")]
public string GetV2()
{
return "Version 2";
}
}

Essentially we still need to tell the Controller that it supports 2.0, but within the controller we can use the “MapToApiVersion” attribute to tell it to be used with a specific version.

 

I hope you will enjoy the API Versioning in ASP.net Core. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

Like it? Share it