21
NovASP.NET Web API Versioning Strategies
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:
URI
QueryString parameter
Custom Header parameter
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 Snippetpublic 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.