Take advantage of the various ways to version your Web API to make it more flexible and adaptable to changes while keeping the functionality intact Credit: Matejmo / Getty Images You should always version your Web API while at the same time keeping as much of the same URI as possible. Imagine a situation where you have a Web API that is up and running in production and is being consumed by users. Now suppose you need more functionality in the Web API yet must keep the existing functionality intact. You may have a few users who still need the old API, while others will need a version with new or extended features. This is exactly where Web API versioning comes to the rescue. You can version your Web API in one of the following ways: Use URLs: Version information is specified in the URL as a query string. Use Custom Request Headers: Version information for your controller is specified in the request header sans the need for any changes in the URL. Use Accept Headers: Accept headers generally define the media type and character encodings. You can pass version information for your Web API via accept headers without having to change the URL. Versioning Web API using URLs Consider the following Web API controllers, which have been named AuthorsV1Controller and AuthorsV2Controller respectively. public class AuthorsV1Controller : ApiController { [HttpGet] public IEnumerable<string> GetAuthors() { return new string[] { "Joydip Kanjilal", "Gerben Wierda" }; } } public class AuthorsV2Controller : ApiController { [HttpGet] public IEnumerable<string> GetAuthors() { return new string[] { "Joydip Kanjilal, INDIA", "Gerben Wierda, Netherlands" }; } } To simplify this illustration, I’ve incorporated a method named GetAuthors() in each controller. While GetAuthors() in AuthorsV1Controller returns only the author names, GetAuthors() in AuthorsV2Controller (the new version) returns the author names along with the names of the countries in which the authors reside. The following code snippet shows how the two controllers use the Register method of the WebApiConfig class. config.Routes.MapHttpRoute( name: "IDGWebAPIV1", routeTemplate: "api/v1/{controller}/{id}", defaults: new { controller= "AuthorsV1Controller", action="GetAuthors", id = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "IDGWebAPIV2", routeTemplate: "api/v2/{controller}/{id}", defaults: new { controller = "AuthorsV2Controller", action = "GetAuthors", id = RouteParameter.Optional } ); You can now invoke the Web API method GetAuthors using the following URL. http://localhost/IDGWebAPI/api/v1/Authors/GetAuthors Versioning Web API using the request header You can also implement Web API versioning using the request header. To achieve this, you need to implement a custom class that extends the DefaultHttpControllerSelector class, then override SelectController in your custom class. Note that the DefaultHttpControllerSelector class implements the IHttpControllerSelector interface. SelectController calls GetControllerName internally and accepts an instance of HttpRequestMessage as a parameter. The following code snippet illustrates how you can retrieve version information from the request header. private string GetControllerVersionFromRequestHeader(HttpRequestMessage request) { var acceptHeader = request.Headers.Accept; const string headerName = "Version"; string controllerVersion = string.Empty; if (request.Headers.Contains(headerName)) { controllerVersion = "V"+request.Headers.GetValues(headerName).First(); } return controllerVersion; } Versioning Web API using the accept header The following method shows how you can retrieve version information for your Web API from the accept header. The method checks the MIME type and returns the version information appropriately. If the media type is not application/json, the default version is returned as V1. private string GetControllerVersionFromAcceptHeader(HttpRequestMessage request) { var acceptHeader = request.Headers.Accept; string controllerVersion = string.Empty; foreach (var mime in acceptHeader) { if (mime.MediaType.Equals("application/json")) { NameValueHeaderValue version = mime.Parameters.FirstOrDefault(v => v.Name.Equals("Version", StringComparison.OrdinalIgnoreCase)); controllerVersion = "V" + version.Value.ToString(); return controllerVersion; } } return "V1"; } You can invoke your Web API from Fiddler by passing the accept header as shown below. Accept: application/json; charset=utf-8;version=2 The following code listing illustrates how you can override SelectController to select a controller dynamically. Note how GetControllerVersionFromRequestHeader has been used. If you would like to retrieve the controller version from the accept header, you should leverage GetControllerVersionFromAcceptHeader instead. public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { try { string controllerName = base.GetControllerName(request); var controllers = GetControllerMapping(); var routeData = request.GetRouteData(); string controllerVersion = GetControllerVersionFromRequestHeader(request); controllerName = String.Format("{0}{1}", controllerName, controllerVersion); HttpControllerDescriptor controllerDescriptor; if (!controllers.TryGetValue(controllerName, out controllerDescriptor)) { string message = "No HTTP resource was found that matches the specified request URI {0}"; throw new HttpResponseException(request.CreateErrorResponse(System.Net.HttpStatusCode.NotFound, String.Format(message, request.RequestUri))); } return controllerDescriptor; } catch (Exception ex) { throw new HttpResponseException(request.CreateErrorResponse(System.Net.HttpStatusCode.NotFound, String.Format(ex.Message, request.RequestUri))); } } You should add the following line in the Register method of the WebApiConfig class to provide support for controller selection at runtime. config.Services.Replace(typeof(IHttpControllerSelector), new IDGControllerSelector((config))); You can now use Fiddler to test your Web API — use the composer tab of Fiddler and provide the URL and version information as appropriate. If you want version 2 of your Web API controller to be invoked, you should specify Version: 2 when composing the request header information in the Composer tab in Fiddler. Related content feature Designing the APIs that accidentally power businesses Well-designed APIs, even those often-neglected internal APIs, make developers more productive and businesses more agile. By Jean Yang Nov 18, 2024 6 mins APIs Software Development news AI accelerating API development, IBM says Generative AI is helping API teams complete projects faster, while APIs also are fueling the use of AI, company official says. By Paul Krill Nov 07, 2024 2 mins Generative AI APIs Artificial Intelligence news WSO2 API managers manage AI APIs WSO2 API Manager and WSO2 API Platform for Kubernetes now allow developers to manage AI services as APIs, with support for OpenAI, Mistral A,I and Microsoft Azure OpenAI. By Paul Krill Nov 05, 2024 3 mins Generative AI APIs Devops news Grounding with Google Search available in Google AI Studio, Gemini API By using Google’s search results to ground generative AI applications, developers can provide users with more accurate, relevant, and trustworthy information, the company said. By Paul Krill Oct 31, 2024 2 mins Google Cloud Platform Generative AI APIs Resources Videos