ASP.NET Web API Versioning Strategies

ASP.NET Web API Versioning Strategies

04 Sep 2022
Advanced
118K Views
7 min read

Web API Versioning is required as the business grows and business requirement changes with the time. As Web API can be consumed by multiple clients at a time, Versioning of Web API will be necessarily required so that Business changes in the API will not impact the client that are using/consuming the existing API.

Web API Versioning Ways

Web API Versioning can be done by using the following methods:

  1. URI

  2. QueryString parameter

  3. Custom Header parameter

  4. Accept Header parameter

Web API Versioning using URI

In this method, Web API URI is changed with the help of routing and is more readable. Let’s say, we have an existing running API in which one URI returns some response. All Clients are consuming the same API and one client wants some changes by requesting to add new properties. With Versioning, we can achieve the same without breaking the existing API flow. In this case, Web API Versioning using URI is one of the best ways to achieve the same.

For Demonstration, we have two controller EmployeeV1 and EmployeeV2. Both will return different data as EmployeeV1 return employees details with ID, Name, Age, City, State property and EmployeeV2 returns employees with ID, FirstName, LastName (In V1, we have name property), DOB (In V1 we have Age property), City, State, Country etc. property.

Image: EmployeeV1Controller

Image: EmployeeV2Controller

Now open WebApiConfig.cs file and configure the route as mentioned in below image.

Image: WebApiConfig.cs

In the above image, we have configured the route so that if Web API receives an HTTP request, it tries to match with the one of the routes in the routing table and call the mapped API controller. Let’s try to hit the API with the Postman.

Image: Hitting the V1 API with the Postman

In the above image, we hit the Web API with the configured V1 route. As we already specified in the route, “/api/v1/employee” will call the EmployeeV1Controller. Now, let's call the V2 API with the Postman. In the below image, we can clearly see that we are able to call EmployeeV2Controller without any issue.

Image: Hitting the V2 API with the Postman

We can also use attribute-based routing for URI based API Versioning.

Image: Attribute based routing in Web API

Web API Versioning using QueryString parameter

In Web API Versioning using Query String, a query string parameter is added to the query string in order to find the controller or Action to which request is sent. Whenever a request comes, SelectController() method of DefaultHttpControllerSelector Class selects the controller information from the information passed in the URI. In order to achieve the versioning with Query String, we need to create a Custom DefaultHttpControllerSelector and override the SelectController() method.

Code Snippet
 public class CustomSelectorController : DefaultHttpControllerSelector
 {
 HttpConfiguration _config;
 public CustomSelectorController(HttpConfiguration config):base(config) {
 _config = config;
 }
 
 public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
 {
 //returns all possible API Controllers
 var controllers = GetControllerMapping();
 //return the information about the route
 var routeData = request.GetRouteData();
 //get the controller name passed
 var controllerName = routeData.Values["controller"].ToString();
 string apiVersion = "1";
 //get querystring from the URI
 var versionQueryString = HttpUtility.ParseQueryString(request.RequestUri.Query);
 if (versionQueryString["version"]!=null)
 {
 apiVersion = Convert.ToString(versionQueryString["version"]);
 }
 if (apiVersion=="1") {
 controllerName = controllerName + "V1";
 }
 else
 {
 controllerName = controllerName + "V2";
 }
 //
 HttpControllerDescriptor controllerDescriptor;
 //check the value in controllers dictionary. TryGetValue is an efficient way to check the value existence
 if (controllers.TryGetValue(controllerName,out controllerDescriptor)) {
 return controllerDescriptor;
 }
 return null;
 }
 }

Before running the API, remove the routing attribute added in the Web API Versioning using URI. Replace the IHttpControllerSelector with CustomSelectorController in WebApiConfig.cs file.

Image: Replace IHttpControllerSelector with CustomSelectorController

Now, let’s hit the API and fetch the data from the version 1 i.e. EmployeeV1Controller using Postman.

Image: Fetch Data using Query string i.e. from EmployeeV1Controller

And get data from EmployeeV2Controller with as version=2 as a query string parameter and an id to fetch the value of particular employees.

Image: using Query string i.e. from EmployeeV2Controller with id=2

Web API Versioning using Custom Header parameter

Custom Headers are used for providing additional information, troubleshooting and implementing server-side logic, etc. We will send the version information in the custom header and check the its value and return the response according to its value.

Code Snippet
 //Web API Versioning using Custom Headers
 public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
 {
 //returns all possible API Controllers
 var controllers = GetControllerMapping();
 //return the information about the route
 var routeData = request.GetRouteData();
 //get the controller name passed
 var controllerName = routeData.Values["controller"].ToString();
 string apiVersion = "1";
 //Custom Header Name to be check
 string customHeaderForVersion = "X-Employee-Version";
 if (request.Headers.Contains(customHeaderForVersion)) {
 apiVersion=request.Headers.GetValues(customHeaderForVersion).FirstOrDefault();
 }
 
 if (apiVersion == "1")
 {
 controllerName = controllerName + "V1";
 }
 else
 {
 controllerName = controllerName + "V2";
 }
 //
 HttpControllerDescriptor controllerDescriptor;
 //check the value in controllers dictionary. TryGetValue is an efficient way to check the value existence
 if (controllers.TryGetValue(controllerName, out controllerDescriptor))
 {
 return controllerDescriptor;
 }
 return null;
 }

Now, hit the API using Postman with the custom headers mentioned in the code.

Image: Custom Header for API Versioning

But in case user pass same headers multiple times, request.Headers.GetValues(customHeaderForVersion).FirstOrDefault() will return multiple values separated by comma. Let’s try the same scenario with Postman. Add the break point In the CustomSelectorController.cs so that It can be analyzed on hitting the send button from the Postman.

Image: Same Custom Header added multiple times

You will see comma separated as same Custom header is passed multiple times.

Image: Comma Separated custom header values

In order to fix that, first check that apiVersion variable contains a comma. If true, then pick the first value separated by the comma from the headers.

Web API Versioning using Accept Header parameter

Accepts Headers requests the server about the file format of the data required by the browser. This data is expressed as MIME Types which stands for “Multipurpose Internet Mail Exchange”. The MIME type is generally case-insensitive, but traditionally written in small letters. We need to make small changes in the above code in order to accept the version parameter value from the accept header.

Pass the accept header using the postman in order to test the API Versioning.

Image: Get request with Accept Parameter using Postman

Summary

As the application grows and business need increase, Versioning of the API is one of the difficult and important part of the API as it makes the API backward compatible. We can do Versioning in ASP.NET Web API with URI, QueryString, Custom Headers and Accept Header parameters, etc. We saw each way in details as well. Along with that, another important thing is to have usable and accurate API documentation. I hope this will help you.

Share Article
About Author
Anoop Sharma (Author and Senior Software Engineer)

Anoop Sharma is working as a Senior Software Engineer in an MNC. He has vast experience in .Net Technologies. He has good knowledge of Asp.Net MVC, Asp.Net WebForm, SQL Server, SignalR, Entity Framework, Web API, MongoDB, Typescript, Angular, WinForms etc. He loves to share his knowledge by writing blogs on online tech communities.
Accept cookies & close this