Web API Versioning using Query string Parameter

Web API Versioning using Query String Parameter

In this article, I am going to discuss Web API Versioning using the Query String Parameter with an example. Please read our previous article before proceeding to this article as we are going to work with the same example. In our previous article, we discussed the following things in detail.

  1. Why Web API versioning is required?
  2. Different options are available in Web API to maintain the versioning.
  3. How to version a Web API using URI’s?

In this article, we want to implement versioning a Web API service using Query String Parameter. Let’s have a look at the following table

Web API Versioning using Query String Parameter

So when we pass the query string v=1 then we want to return Version 1 of the Web API service and similarly when we pass v=2 then we need to return version 2 of the Web API service. If we don’t specify the query string then by default it will return the version 1 of the Web API Service.

How the Web API Framework select a Controller?

Before we start implementing the Web API versioning using a query string parameter, let first understand how the Web API Framework selects a controller when a request is issued to a Web API service. For example, let us understand how the Web API framework selects the controller when a request is issued to the following URI

/api/employees/1
In ASP.NET Web API, there is a class called DefaultHttpControllerSelector. This class has a method called SelectController() which will select the controller based on the information it has in the URI. 

The above class uses the below algorithm to find the controller:

  1. First, it will look at the route dictionary collection for the key “controller”.
  2. Secondly, it takes the value for the “controller” key and appends the string “Controller” to get the controller type name.
  3. Finally, it looks for a Web API controller with this type name.

For example, if the route dictionary contains the key-value pair “controller” = “Employees”, then the controller type is “EmployeesController”. If there is no matching type found, or it found multiple matches, then the ASP.NET WEB API Framework simply returns an error to the client.

In our example, in the URI we have
  1. The name of the controller, in this case, Employees
  2. The id parameter value, in this case, 1

So from the URI, the SelectController() method takes the name of the controller in this case “Employees” and try to find the “EmployeesController” in the route dictionary and if it founds then returns it. This is the default implementation to select the Web API Controller. If you want to learn more about the controller and action selector in Web API, then please refer to the following article.

The Controller and Action Selector in Web API

The above default implementation of Controller Selection will not work for us because in our Web API Service we do not have any controller with the name EmployeesController. Instead we have the following two controllers

1. EmployeesV1Controller and
2. EmployeesV2Controller
So, when a request is issued to the following URI, depending on the query string parameter “v” value we want to select the appropriate controller. If the value is 1, then we need to select the EmployeesV1Controller, and if the value is 2, then we need to select the EmployeesV2Controller.

/api/employees?v=1 

How to Maintain Web API service versioning using a query string parameter?

Step1: As we already discussed, the default implementation of controller selection provided by Web API Framework will not work for us, so we need to provide our own custom controller selector implementation.

To do this, add a new folder to your project with the name “Custom” and then add a class file within the Custom Folder and name it as “CustomControllerSelector“. Once you add the class file, then copy and paste the following code. The code is self-explained so please go through the comments.

using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;

namespace WebAPIVersioning.Custom
{
    // Derive the CustomControllerSelector from the DefaultHttpControllerSelector class
    public class CustomControllerSelector : DefaultHttpControllerSelector
    {
        private HttpConfiguration _config;
        public CustomControllerSelector(HttpConfiguration config) : base(config)
        {
            _config = config;
        }

        public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
        {
            // First fetch all the available Web API controllers
            var controllers = GetControllerMapping();

            // Get the controller name and the 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 "Employees"
            var controllerName = routeData.Values["controller"].ToString();

            // Set the Default version number to 1
            string versionNumber = "1";
            var versionQueryString = HttpUtility.ParseQueryString(request.RequestUri.Query);
            if (versionQueryString["v"] != null)
            {
                versionNumber = versionQueryString["v"];
            }

            if (versionNumber == "1")
            {
                // if the version number is 1, then append V1 to the controller name.
                // So at this point the, controller name will become EmployeesV1
                controllerName = controllerName + "V1";
            }
            else
            {
                // if version number is 2, then append V2 to the controller name.
                // So at this point the controller name will become EmployeesV2
                controllerName = controllerName + "V2";
            }

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

            return null;
        }
    }
}
Step2: 

Now we need to replace the default controller selector with our custom controller selector and we need to do this within the WebApiConfig.cs file. Notice, here we are replacing the IHttpControllerSelector, with our CustomControllerSelector. The DefaultHttpControllerSelector implements IHttpControllerSelector, so that is the reason we are replacing IHttpControllerSelector.

Web API Versioning using Query String Parameter

Step3: Include the following default route in WebApiConfig.cs

Web API Versioning using Query String Parameter

After the above two changes in the WebApiConfig.cs file, your WebApiConfig.csfile should looks as shown below.

using System.Web.Http;
using System.Web.Http.Dispatcher;
using WebAPIVersioning.Custom;

namespace WebAPIVersioning
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.MapHttpAttributeRoutes();
            
            config.Services.Replace(typeof(IHttpControllerSelector),
                               new CustomControllerSelector(config));
            
            config.Routes.MapHttpRoute(
                name: "DefaultRoute",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}
Step4: 

Finally remove the [Route] attribute, from all the action methods of both EmployeesV1Controller and EmployeesV2Controller as shown below.

Web API Versioning using Query String Parameter

EmployeesV2Controller

Web API Versioning using Query String Parameter  

That’s it; we have done with our implementation. Now run the application and navigates the following URI and you will see the output as expected.

/api/employees
/api/employees?v=1
/api/employees?v=2

In the next article, I am going to discuss how to implement the Web API Versioning using Custom Header with an example. Here, In this article, I try to explain how to implement Web API Versioning Using Query String parameter step by step with an example. I hope this article will help you with your needs. I would like to have your feedback. Please post your feedback, question, or comments about this article.

Leave a Reply

Your email address will not be published. Required fields are marked *