API Versioning in .NET Core
.NET Core is a great framework for building out front- and backend applications. Read on to learn how to version the APIs your app's call using this framework.
Join the DZone community and get the full member experience.
Join For FreeIn this post, we will see how to use different options for versioning in .NET Core API projects. Versioning APIs is very important and it should be implemented in any API project. Let's see how to achieve this in .NET Core.
Prerequisites:
- Visual Studio 2017 community edition, download here.
- .NET Core 2.0 SDK from here (I have written a post to install SDK here).
Create the API App Using a .NET Core 2.0 Template in VS 2017
Once you have all these installed, open your Visual Studio 2017 -> Create New Project -> Select Core Web application:
Click on Ok and in the next window, select API as shown below:Visual Studio will create a well-structured application for you.
Install the NuGet Package for API Versioning
The first step is to install the NuGet package for API Versioning.
Search with "Microsoft.AspNetCore.Mvc.Versioning" in the NuGet Package Manager and click on Install:
This NuGet package is a service API versioning library for Microsoft ASP.NET Core.
Changes in Startup Class
Once the NuGet package is installed, the next step is to add the API Versioning service in the ConfigureService
method as shown below:
services.AddApiVersioning(o => {
o.ReportApiVersions = true;
o.AssumeDefaultVersionWhenUnspecified = true;
o.DefaultApiVersion = new ApiVersion(1, 0);
});
Some points here:
The
ReportApiVersions
flag is used to add the API versions in the response header as shown below:
- The
AssumeDefaultVersionWhenUnspecified
flag is used to set the default version when the client has not specified any versions. Without this flag, theUnsupportedApiVersion
exception will occur when the version is not specified by the client. - The
DefaultApiVersion
flag is used to set the default version count.
Create Multiple Versions of the Sample API
Once the API versioning service is added, the next step is to create multiple versions of our Values API.
For now, just keep the GET method and remove the rest of the methods and create version 2 of the same API, as shown below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace ApiVersioningSampleApp.Controllers {
[ApiVersion("1.0")]
[Route("api/Values")]
public class ValuesV1Controller: Controller {
// GET api/values
[HttpGet]
public IEnumerable < string > Get() {
return new string[] {
"Value1 from Version 1",
"value2 from Version 1"
};
}
}
[ApiVersion("2.0")]
[Route("api/Values")]
public class ValuesV2Controller: Controller {
// GET api/values
[HttpGet]
public IEnumerable < string > Get() {
return new string[] {
"value1 from Version 2",
"value2 from Version 2"
};
}
}
}
In the above code:
- We have applied the attribute [ApiVersion("1.0")] for Version 1.
- We have applied the attribute [ApiVersion("2.0")] for Version 2.
- Also changed the GET value to understand which version is getting called.
Just run your application and you will see the Version 1 API is getting called because we did not specify any specific version; thus the default version (1.0 in our case) will be called:
There are some ways by which you can specify the version of the API, we'll discuss below.
Query String-Based Versioning
In this, you can specify the version of the API in the query string. For example, to call version 2 of the Values API, the below call should work:
/api/values?api-version=2.0
URL-Based Versioning
There are many people who do not like query based patterns, in which case we can implement URL-based versioning by changing the route as shown below:
[Route("api/{v:apiVersion}/Values")]
In such a case, the below call will return the version 2 of the API:
/api/2.0/values
This approach is more readable.
HTTP Header-Based Versioning
If you do not wish to change the URL of the API then you can send the version of API in the HTTP header.
To enable this, the version reader needs to be added to the ConfigureService
method as shown below:
o.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
Once you enable this, the query string approach will not work. If you wish to enable both of them then just use the below code:
o.ApiVersionReader = new QueryStringOrHeaderApiVersionReader("x-api-version");
Once the API Version reader is enabled, you can specify the API version while calling this particular API. For example, I have given Version 1 while calling the API from Postman:
Some Useful Features
Deprecating the Versions
Sometimes we need to deprecate some of the versions of the API, but we do not wish to completely remove that particular version of the API.
In such cases, we can set the Deprecated
flag to true
for that API, as shown below:
[ApiVersion("1.0", Deprecated = true)]
[Route("api/Values")]
public class ValuesV1Controller: Controller {
//// Code
}
It will not remove this version of the API, but it will return the list of deprecated versions in the header, api-deprecated-versions, as shown below:
Assign the Versions Using Conventions
If you have lots of versions of the API, instead of putting the ApiVersion
attribute on all the controllers, we can assign the versions using a conventions property.
In our case, we can add the convention for both the versions as shown below:
o.Conventions.Controller<ValuesV1Controller>().HasApiVersion(new ApiVersion(1, 0));
o.Conventions.Controller<ValuesV2Controller>().HasApiVersion(new ApiVersion(2, 0));
Which means that we are not required to put [ApiVersion] attributes above the controller
API Version Neutral
There might be a case when we need to opt out the version for some specific APIs.
For example, Health checking APIs which are used for pinging. In such cases, we can opt out of this API by adding the attribute [ApiVersionNeutral]
as shown below:
[ApiVersionNeutral]
[RoutePrefix( "api/[controller]" )]
public class HealthCheckController : Controller {
////Code
}
Other Features to Consider:
Add
MapToApiVersion
in the attribute if you wish to apply versioning only for specific action methods instead of the whole controller. For example:
[HttpGet, MapToApiVersion("2.0")]
public IEnumerable<string> Get() {
return new string[] { "value1 from Version 2", "value2 from Version 2" };
}
- We can get the version information from the method
HttpContext.GetRequestedApiVersion();
, this is useful to check which version has been requested by the client. - Version Advertisement can be used by each service to advertise the supported and deprecated API versions it knows about. This is generally used when the service API versions are split across hosted applications.
- We can allow clients to request a specific API version by media type. This option can be enabled by adding the below line in the API versioning options in the
ConfigureService
method:
options => options.ApiVersionReader = new MediaTypeApiVersionReader();
Hope this helps.
You can find my all .NET core posts here.
Published at DZone with permission of Neel Bhatt, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments