Posted on 5/19/2020 11:45:18 AM by Admin

Web API versioning using Accept Header

This is the continuation of Web API Versioning Series, in the previous four articles we have learnt
  • why Versioning is required Read here and
  • Versioning using URI Read here
  • Versioning using Query String Read Here
  • Versioning using Custom Header Read Here

In this article we will learn how to implement versioning using Accept Header. We already have two API Controllers :-
  1. SilverEmployeeController, which returns Employee's Name ,Id and Salary.
  2. GoldEmployeeController , which returns Employee's First Name ,Last Name, Id and Salary.

Our Client know nothing about the real implementation ,they just know that they are consuming EmployeeService and there exists two versions of the service. In order to consume the service they have to pass the version number too along with the URL , it's our duty to tell our client how they can pass the version number. There are many ways with which version number can be passed like:-
  1. In the Form of routed data .(versioning using URI)
  2. In the form of query string (versioning using query string)
  3. In the form of Custom Header (versioning using custom header)
  4. In the form of Accept Header (versioning using accept header)
  5. In the form of Custom Media Types (versioning using Custom media types).

In the previous article, we had created a custom header for versioning , actually creating a custom header just for versioning is not that required as we can achieve the same with the standard Accept header as well. We can add parameters to the Accept header to send any additional data along with the request to the server. For example, we can specify the version of the service we want using the version parameter as shown below.

Web API versioning using Accept Header simply means the clients are going to specify the version number as parameter with the help of Accept Header.

Versioning using Accept Header
Passing Version Number as parameter with Accept Header

So, our work is to tell web API to select appropriate controller based on the version number specified by the client in the Accept Header as additional Parameter.
  • If client passes, Accept:application/json;version=1, then we have to tell web API to select SilverEmployeeService Controller.
  • If client passes , Accept:application/json;version=2, then we have to tell web api to select GoldEmployeeService Controller.

From the previous article ,we know how web API selects the controller based on the information from URL , we also know how to override the default behavior of controller selection.

In the previous article, we have implemented a CustomControllerSelector. At the moment, this CustomControllerSelector is retrieving the version number from custom Accept Header.

To implement versioning using a Accept Header, all we have to do is change the logic slightly into the CustomControllerSelector class to read the version number from the Accept header instead of from Custom version header.


   namespace MyFirstAPIProject.Custom
     {
    
        public class CustomControllerSelector : DefaultHttpControllerSelector
        {
            private HttpConfiguration _config;
            public CustomControllerSelector(HttpConfiguration config)
                : base(config)
            {
                _config = config;
            }

            public override HttpControllerDescriptor
                SelectController(HttpRequestMessage request)
            {
                // Get all the available Web API controllers
                var controllers = GetControllerMapping();
                // Get the controller name and parameter values from the request URI
                var routeData = request.GetRouteData();

                // Get the controller name from route data.
                // The name of the controller in our case is "EmployeeService"
                var controllerName = routeData.Values["controller"].ToString();

                // Default version number to 1
                string versionNumber = "1";
                 //Get the version number from the Accept header

                                // Users can include multiple Accept headers in the request
                                // Check if any of the Accept headers has a parameter with name version
                                var acceptHeader = request.Headers.Accept.Where(a => a.Parameters
                                                    .Count(p => p.Name.ToLower() == "version") > 0);

                                // If there is atleast one header with a "version" parameter
                                if (acceptHeader.Any())
                                {
                                    // Get the version parameter value from the Accept header
                                    versionNumber = acceptHeader.First().Parameters
                                                    .First(p => p.Name.ToLower() == "version").Value;
                                }
                

               
                if (versionNumber == "1")
                {
                    // if version number is 1, then prepend "Silver" to the controller name.
                    // So at this point the, controller name will become SilverEmployeeService
                    controllerName = "Silver"+controllerName;
                }
                else
                {
                    // if version number is 2, then prepend "Gold" to the controller name.
                    // So at this point the, controller name will GoldEmployeeService
                    controllerName ="Gold"+controllerName;
                }

                HttpControllerDescriptor controllerDescriptor;
                if (controllers.TryGetValue(controllerName, out controllerDescriptor))
                {
                    return controllerDescriptor;
                }

                return null;
            }
        }
    
     }

The implementation is simple and straight forward, we are getting version number from Accept header and accordingly changing the controller Name.

Now , run the application and fire two get request on the behalf of two different client like below and test the results.

Versioning with Accept Header
Response for version=2

As you can see ,for the Accept:application/json;version=2, we are getting list of GoldEmployee back ,it means our custom controller selector is successfully working and versioning is successful.