Implementing versioning in an ASP.NET MVC Web API ensures backward compatibility and allows different versions of the API to coexist. Here's how to implement API versioning effectively:
1. URL Path Versioning
This is the simplest method where the version is included in the URL.
Example:
/api/v2/values
Steps:
-
Update Route Configuration: Modify the
WebApiConfig
file.config.Routes.MapHttpRoute( name: "Version1", routeTemplate: "api/v1/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); config.Routes.MapHttpRoute( name: "Version2", routeTemplate: "api/v2/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); -
Separate Controllers for Each Version: Create separate controllers for each version:
public class ValuesV1Controller : ApiController
{
public IHttpActionResult Get() => Ok("This is version 1.");
}
public class ValuesV2Controller : ApiController
{
public IHttpActionResult Get() => Ok("This is version 2.");
}
2. Query String Versioning
Add the version as a query parameter.
Example:
/api/values?version=2
Steps:
-
Route and Custom Delegating Handler: Write a delegating handler to inspect the query parameter and redirect to the appropriate version.
public class VersioningHandler : DelegatingHandler
{
protected override async TaskSendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request.GetQueryNameValuePairs().Any(q => q.Key.Equals("version", StringComparison.OrdinalIgnoreCase)))
{
var version = request.GetQueryNameValuePairs() .FirstOrDefault(q => q.Key.Equals("version", StringComparison.OrdinalIgnoreCase)).Value;
if (version == "2")
{
request.Headers.Add("X-Version", "2");
}
}
return await base.SendAsync(request, cancellationToken);
}
}Register the handler in
WebApiConfig
:config.MessageHandlers.Add(new VersioningHandler()); -
Controller Versioning: Use the
X-Version
header in controllers to switch logic.
3. Header Versioning
The API version is specified in the request header.
Example:
Headers: X-API-Version: 1
Steps:
-
Custom Attribute for Versioning:
public class ApiVersionAttribute : ActionFilterAttribute
{
private readonly string _version;
public ApiVersionAttribute(string version) => _version = version;
public override void OnActionExecuting(HttpActionContext actionContext)
{
var versionHeader = actionContext.Request.Headers.FirstOrDefault(h => h.Key == "X-API-Version").Value?.FirstOrDefault();
if (versionHeader != _version)
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.BadRequest, "Invalid API Version.");
}
base.OnActionExecuting(actionContext);
}
} -
Apply the Attribute:
[ApiVersion("1")]
public class ValuesV1Controller : ApiController
{
public IHttpActionResult Get() => Ok("This is version 1.");
}
[ApiVersion("2")]
public class ValuesV2Controller : ApiController
{
public IHttpActionResult Get() => Ok("This is version 2.");
}
4. Use Microsoft.AspNet.WebApi.Versioning Library
The Microsoft.AspNet.WebApi.Versioning library simplifies versioning implementation.
Installation:
Install the NuGet package:
Steps:
-
Enable Versioning: Configure versioning in
WebApiConfig
:config.AddApiVersioning(options => { options.AssumeDefaultVersionWhenUnspecified = true; options.DefaultApiVersion = new ApiVersion(1, 0); options.ReportApiVersions = true; }); -
Controller Versioning: Annotate controllers with the version:
[ApiVersion("1.0")]
public class ValuesController : ApiController
{
public IHttpActionResult Get() => Ok("This is version 1.");
}
[ApiVersion("2.0")] [Route("api/v{version:apiVersion}/values")]
public class ValuesV2Controller : ApiController
{
public IHttpActionResult Get() => Ok("This is version 2.");
} -
Request Versioning:
- Via URL:
/api/v1/values
- Via Header:
X-Version: 1.0
- Via URL:
Best Practices
- Consistency: Choose a single versioning strategy across your API.
- Documentation: Clearly document available versions for consumers.
- Deprecation Policy: Define a strategy to deprecate older versions gracefully.
These methods provide robust API versioning options for different use cases.