API Versioning in .NET Core


26 June 2018

API versioning is a fundamental concept in the development of RESTful APIs. As your API evolves over time, it’s crucial to maintain backward compatibility while allowing for new features and improvements. Without a solid versioning strategy, clients consuming your API could experience breaking changes, leading to confusion and frustration.

In this post, we’ll explore why API versioning is important and how to implement API versioning in .NET Core using custom headers or route parameters.


Why API Versioning is Important

As your application grows, you might need to introduce breaking changes—new endpoints, modified responses, or different data structures. Without versioning, any changes made to the API could break existing client applications.

API versioning provides a structured way to introduce new features without disrupting the services of clients already using your older API versions. It helps ensure that:

  • Backward Compatibility: Clients can continue using the old version of the API while you develop new versions.
  • Flexibility: It allows the API to evolve and introduce new functionality.
  • Clear Communication: The API version signals to clients when changes are introduced, making it clear which version they are working with.

Implementing API Versioning in .NET Core

.NET Core provides various ways to implement API versioning. You can use different strategies, including custom headers and route parameters, to control the versioning of your Web API. Below, we’ll discuss how to set up and implement both methods.


1. API Versioning with Route Parameters

One of the most common methods of versioning an API is by using route parameters. This allows you to specify the version directly in the URL, making it clear which version of the API the client is interacting with.

Example:

[Route("api/v{version:apiVersion}/products")]
public class ProductsController : ControllerBase
{
    private readonly IProductService _productService;

    public ProductsController(IProductService productService)
    {
        _productService = productService;
    }

    [HttpGet]
    public IActionResult GetProducts()
    {
        var products = _productService.GetAllProducts();
        return Ok(products);
    }
}

In this example, the API version is part of the route template (v{version:apiVersion}). The client will call the endpoint like so:

GET /api/v1/products

You can define different controllers or methods for different versions of your API and handle versioning in a clean, organized manner.


2. API Versioning with Custom Headers

Another common way to implement versioning is by using custom headers in the HTTP request. This allows the version to be specified separately from the URL, making it less visible but still clear and easy to maintain.

To set up versioning with custom headers, you first need to configure the versioning middleware in your Startup.cs.

Step 1: Install the API Versioning Package

In your project, you need to install the Microsoft.AspNetCore.Mvc.Versioning package to use versioning features:

dotnet add package Microsoft.AspNetCore.Mvc.Versioning

Step 2: Configure API Versioning in Startup.cs

In ConfigureServices inside your Startup.cs, enable API versioning and specify how versioning should be handled (using custom headers in this case).

public void ConfigureServices(IServiceCollection services)
{
    services.AddApiVersioning(options =>
    {
        options.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
        options.AssumeDefaultVersionWhenUnspecified = true;
        options.DefaultApiVersion = new ApiVersion(1, 0);
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

In this configuration, the version is determined by the x-api-version header. For example:

GET /api/products
x-api-version: 1.0

Step 3: Implement API Versioning in Controllers

You can now define different versions of your API using the ApiVersion attribute.

[ApiVersion("1.0")]
[Route("api/products")]
public class ProductsV1Controller : ControllerBase
{
    private readonly IProductService _productService;

    public ProductsV1Controller(IProductService productService)
    {
        _productService = productService;
    }

    [HttpGet]
    public IActionResult GetProducts()
    {
        var products = _productService.GetAllProductsV1();
        return Ok(products);
    }
}

[ApiVersion("2.0")]
[Route("api/products")]
public class ProductsV2Controller : ControllerBase
{
    private readonly IProductService _productService;

    public ProductsV2Controller(IProductService productService)
    {
        _productService = productService;
    }

    [HttpGet]
    public IActionResult GetProducts()
    {
        var products = _productService.GetAllProductsV2();
        return Ok(products);
    }
}

In this example, we have two versions of the ProductsController, each handling different versions of the GET /api/products request. The client can specify which version to use by setting the x-api-version header.


Best Practices for API Versioning

Here are some best practices to follow when implementing API versioning:

  1. Use Semantic Versioning: Consider using semantic versioning (major.minor.patch) to communicate changes to your API clearly.
    • Major version: Introduces breaking changes.
    • Minor version: Introduces new features without breaking existing functionality.
    • Patch version: Fixes bugs or issues without changing the API’s functionality.
  2. Deprecate Old Versions: After releasing a new version, make sure to notify users of deprecating older versions. You can provide a deprecation notice in the response headers or documentation.
  3. Avoid Versioning Everything: Not all APIs need to be versioned. Only version the parts of your API that are likely to change over time.
  4. Use Clear Naming Conventions: Whether using route parameters or headers, keep your versioning scheme simple and consistent.

Conclusion

API versioning is a critical aspect of maintaining a stable and scalable Web API. In this post, we explored two common strategies for implementing API versioning in .NET Core:

  • Route Parameters: The version is embedded in the URL (e.g., /api/v1/products).
  • Custom Headers: The version is specified in the HTTP headers (e.g., x-api-version: 1.0).

By using these techniques, you can ensure that your Web API evolves over time while maintaining backward compatibility, allowing your clients to use different versions of the API seamlessly.

In the next post, we’ll continue exploring more advanced .NET Core topics. Stay tuned!


Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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