Implementing API Versioning in ASP.NET Core Web API

As APIs evolve, changes and improvements can lead to breaking changes. API versioning helps maintain backward compatibility while enabling new features. ASP.NET Core provides built-in support for API versioning, making it easy to maintain different API versions efficiently. In this blog post, I discuss different ways to implement API versioning in ASP.NET Core Web API. Let's start with the first and most important part.


Why is API Versioning Important?

API versioning allows you to manage changes to your API without disrupting existing clients. As your API evolves, clients who rely on specific features may not be ready or able to migrate to the latest version. Versioning ensures that clients can continue using the API while developers can introduce new features, enhancements, and fixes.


Types of API Versioning

There are several strategies for versioning an API:

URI Versioning: The version is included in the URL path like /api/v1/.

Query String Versioning: The version is passed as a query parameter like /api/products?version=1.

Header Versioning: The version is passed in the request header like { 'version': '1' , 'Content-Type': 'application/json' }.

Setting Up API Versioning in ASP.NET Core

ASP.NET Core provides a powerful and flexible way to handle API versioning. I'll use the Microsoft.AspNetCore.Mvc.Versioning NuGet package to enable and configure API versioning in our ASP.NET Core application, let's install it.

dotnet add package Microsoft.AspNetCore.Mvc.Versioning


Once installed, configure API versioning in the Program.cs file:

  // Enable API versioning
  services.AddApiVersioning(options =>
  {
      options.ReportApiVersions = true;  // Add the API version in response headersabout:blank#blocked
      options.AssumeDefaultVersionWhenUnspecified = true;  // Default to the latest version if no version is specified
      options.DefaultApiVersion = ApiVersion.Default;  // Set the default API version
      options.ApiVersionReader = new UrlSegmentApiVersionReader();  // Use URI versioning (e.g., /api/v1/)
  });
  services.AddControllers();


Here, we have enabled API versioning and configured it to use URI versioning by reading the version from the URL segment (e.g., /api/v1/products).

The version is part of the URL, such as /api/v1/products and /api/v2/products.

Define API versions in controllers

Once versioning is enabled, you can specify versions for your API endpoints. You can use the ApiVersion attribute to indicate which version(s) an API action supports.

Here’s an example with two versions of a ProductsController:

[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
public class ProductsController : ControllerBase
{
    // GET api/v1/products
    [HttpGet]
    [MapToApiVersion("1.0")]
    public IActionResult GetV1()
    {
        return Ok(new { Version = "1.0", Products = "List of products in v1" });
    }

    // GET api/v2/products
    [HttpGet]
    [MapToApiVersion("2.0")]
    public IActionResult GetV2()
    {
        return Ok(new { Version = "2.0", Products = "List of products in v2 with enhancements" });
    }
}

  • MapToApiVersion("1.0") specifies that the GetV1 action is available in version 1.0.
  • MapToApiVersion("2.0") specifies that the GetV2 action is available in version 2.0.

Testing API Versioning

With the configuration in place, you can test your API versions by sending requests to the corresponding versioned endpoints:

GET /api/v1/products will call the GetV1 action.

GET /api/v2/products will call the GetV2 action.

You can also check the response headers for API versioning information. If you have enabled ReportApiVersions, the Api-Version header will appear in the response, informing the client of the API versions available.

Handling API Versioning in the Response

If you want to communicate available API versions to your users, you can use the ReportApiVersions option which adds the Api-Version header to every response. This will help clients know which versions are available.


Versioning Strategies and Best Practices

While URI versioning is the most straightforward, it is essential to choose the right versioning strategy based on your project’s needs. Here are some best practices:
Use Semantic Versioning: It’s helpful to follow semantic versioning (Major.Minor.Patch), where:
Major version changes indicate breaking changes.
Minor version changes introduce backward-compatible new features.
Patch versions are for backward-compatible bug fixes.
Avoid Breaking Changes: Add new features rather than modify existing functionality when possible. This approach reduces the need for breaking changes.
Deprecation Notices: If you plan to remove an old version, notify clients early by using deprecation headers or a deprecation route.
Provide Documentation: Always document the API versioning scheme and clearly specify what’s changed in each version.


Conclusion

API versioning is crucial for maintaining backward compatibility while allowing improvements in newer versions. ASP.NET Core makes it easy to implement versioning using URL segments, query strings, or headers. By following this approach, you ensure a smooth transition for API consumers as your application evolves. By following the guidelines and using Microsoft.AspNetCore.Mvc.Versioning, you can build scalable, maintainable, and flexible APIs for your users, ensuring that clients are never left behind when new versions are released.