How do you implement versioning in Web APIs?

4 minintermediateASP.NET-Coreweb-apiversioning

Quick Answer

API versioning lets multiple API versions coexist so you can evolve without breaking clients, typically via the `Asp.Versioning` package. Common strategies: URL path (`/api/v1/...`), query string (`?api-version=1.0`), header, or media-type versioning. You register versioning services, mark controllers with `[ApiVersion]`, and optionally expose a version explorer for Swagger.

Detailed Answer

API versioning allows you to maintain multiple versions of your API simultaneously.

Installation:

dotnet add package Asp.Versioning.Mvc
dotnet add package Asp.Versioning.Mvc.ApiExplorer

Method 1: URL Path Versioning (Most Common)

// Program.cs
builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new ApiVersion(1, 0);
    options.AssumeDefaultVersionWhenUnspecified = true;
    options.ReportApiVersions = true;
});

// Controller
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("1.0")]
public class ProductsV1Controller : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 1.0");
}

[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiVersion("2.0")]
public class ProductsV2Controller : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok("Version 2.0 with new features");
}

// Usage:
// GET /api/v1/products
// GET /api/v2/products

Method 2: Query String Versioning

builder.Services.AddApiVersioning(options =>
{
    options.ApiVersionReader = new QueryStringApiVersionReader("api-version");
});

[ApiController]
[Route("api/[controller]")]
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class ProductsController : ControllerBase
{
    [HttpGet]
    [MapToApiVersion("1.0")]
    public IActionResult GetV1() => Ok("Version 1.0");

    [HttpGet]
    [MapToApiVersion("2.0")]
    public IActionResult GetV2() => Ok("Version 2.0");
}

// Usage:
// GET /api/products?api-version=1.0
// GET /api/products?api-version=2.0

Method 3: Header Versioning

builder.Services.AddApiVersioning(options =>
{
    options.ApiVersionReader = new HeaderApiVersionReader("X-Api-Version");
});

// Usage:
// GET /api/products
// Headers: X-Api-Version: 1.0

Method 4: Media Type Versioning

builder.Services.AddApiVersioning(options =>
{
    options.ApiVersionReader = new MediaTypeApiVersionReader();
});

// Usage:
// GET /api/products
// Headers: Accept: application/json;v=1.0

Deprecating Old Versions:

[ApiVersion("1.0", Deprecated = true)]
[ApiVersion("2.0")]
[ApiController]
[Route("api/v{version:apiVersion}/[controller]")]
public class ProductsController : ControllerBase
{
    // Implementation
}

Multiple Versioning Strategies:

builder.Services.AddApiVersioning(options =>
{
    options.ApiVersionReader = ApiVersionReader.Combine(
        new QueryStringApiVersionReader("api-version"),
        new HeaderApiVersionReader("X-Api-Version"),
        new UrlSegmentApiVersionReader()
    );
});

Related Resources