Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
How to do versioning with accept header in C# ASP.NET WebAPI?
The Accept header in HTTP tells the server what file format the client wants the response data in. These formats are commonly called MIME-types (Multipurpose Internet Mail Extensions). In ASP.NET Web API, you can use the Accept header to implement API versioning by including version information as a parameter in the Accept header.
This approach allows you to maintain multiple API versions while using the same URL endpoints, routing requests to different controllers based on the version specified in the Accept header.
How Accept Header Versioning Works
When a client makes a request, it includes an Accept header with version information −
Accept: application/json; version=1 ? Routes to StudentsV1Controller Accept: application/json; version=2 ? Routes to StudentsV2Controller
Creating a Custom Controller Selector
To implement Accept header versioning, you need a custom controller selector that reads the version from the Accept header and routes to the appropriate controller −
using System.Linq;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Controllers;
using System.Web.Http.Dispatcher;
namespace WebAPI.Custom
{
public class CustomControllerSelector : DefaultHttpControllerSelector
{
private HttpConfiguration _config;
public CustomControllerSelector(HttpConfiguration config) : base(config)
{
_config = config;
}
public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
var controllers = GetControllerMapping();
var routeData = request.GetRouteData();
var controllerName = routeData.Values["controller"].ToString();
string versionNumber = "";
var acceptHeader = request.Headers.Accept.Where(a =>
a.Parameters.Count(p => p.Name.ToLower() == "version") > 0);
if (acceptHeader.Any())
{
versionNumber = acceptHeader.First().Parameters
.First(p => p.Name.ToLower() == "version").Value;
}
HttpControllerDescriptor controllerDescriptor;
if (versionNumber == "1")
{
controllerName = string.Concat(controllerName, "V1");
}
else if (versionNumber == "2")
{
controllerName = string.Concat(controllerName, "V2");
}
if (controllers.TryGetValue(controllerName, out controllerDescriptor))
{
return controllerDescriptor;
}
return null;
}
}
}
Configuring the Custom Controller Selector
Replace the default controller selector with your custom implementation in the WebApiConfig.cs file −
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Services.Replace(typeof(IHttpControllerSelector),
new CustomControllerSelector(config));
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Version 1 Controller Implementation
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace DemoWebApplication.Controllers
{
public class StudentV1Controller : ApiController
{
List<StudentV1> students = new List<StudentV1>
{
new StudentV1 { Id = 1, Name = "Mark" },
new StudentV1 { Id = 2, Name = "John" }
};
public IEnumerable<StudentV1> Get()
{
return students;
}
public StudentV1 Get(int id)
{
var studentForId = students.FirstOrDefault(x => x.Id == id);
return studentForId;
}
}
public class StudentV1
{
public int Id { get; set; }
public string Name { get; set; }
}
}
Version 2 Controller Implementation
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace DemoWebApplication.Controllers
{
public class StudentV2Controller : ApiController
{
List<StudentV2> students = new List<StudentV2>
{
new StudentV2 { Id = 1, FirstName = "Roger", LastName = "Federer" },
new StudentV2 { Id = 2, FirstName = "Tom", LastName = "Bruce" }
};
public IEnumerable<StudentV2> Get()
{
return students;
}
public StudentV2 Get(int id)
{
var studentForId = students.FirstOrDefault(x => x.Id == id);
return studentForId;
}
}
public class StudentV2
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
}
How to Test Accept Header Versioning
Use the following Accept headers in your HTTP requests −
For Version 1: Accept: application/json; version=1 For Version 2: Accept: application/json; version=2
The same URL endpoint /api/Student will route to different controllers based on the version parameter in the Accept header, allowing you to maintain backward compatibility while introducing new API versions.
Conclusion
Accept header versioning in ASP.NET Web API provides a clean way to version APIs without changing URLs. By implementing a custom controller selector, you can route requests to different controllers based on the version specified in the Accept header, maintaining multiple API versions seamlessly.
