Tutorials ASP.NET Core Web API
API Versioning Strategies
On this page
API Versioning Strategies
When you change your API's JSON response structure, you break every mobile app currently installed on users' phones. To prevent this, APIs must be versioned. You leave the old API (v1) running for legacy clients, and build the new features in a separate API structure (v2).
1. Installing the Framework
ASP.NET Core supports enterprise-grade versioning via the Asp.Versioning.Mvc package.
dotnet add package Asp.Versioning.Mvc
Configuration in Program.cs
builder.Services.AddApiVersioning(options =>
{
// If client doesn't specify a version, assume they want v1.0
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
// Returns headers showing which versions are supported/deprecated
options.ReportApiVersions = true;
});
2. Applying Versions to Controllers
You define multiple controller classes and tag them with their specific version. Both controllers can exist simultaneously without causing an AmbiguousMatchException.
// OLD CONTROLLER
[ApiController]
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/users")]
public class UsersV1Controller : ControllerBase
{
[HttpGet] // URL: GET /api/v1/users
public IActionResult GetUsers() {
return Ok(new[] { new { Name = "John" } }); // Returns flat JSON
}
}
// NEW CONTROLLER (Breaking Change!)
[ApiController]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/users")]
public class UsersV2Controller : ControllerBase
{
[HttpGet] // URL: GET /api/v2/users
public IActionResult GetUsers() {
// We added a data wrapper and pagination metadata! (Breaking change!)
return Ok(new { data = new[] { new { FirstName = "John" } }, totalCount = 1 });
}
}
3. The Three Types of Versioning
URL Versioning (shown above) is just one way to communicate the requested version. The framework supports three distinct strategies.
1. URL Segment
GET /api/v2/users
The most common and explicitly readable method. Best for public REST APIs used by third-party developers.
2. Query String
GET /api/users?api-version=2.0
Keeps the main URL clean, but often gets lost or stripped by aggressive caching proxies.
3. HTTP Header
Header: x-api-version: 2.0
The most "RESTful" approach (URLs shouldn't change just because data shape changes), but difficult to test directly in a browser without Postman.
4. Interview Mastery
Q: "When is a change considered a 'Breaking Change' requiring an entirely new API Version, versus a safe change that can just be updated silently on v1?"
Architect Answer: "The rule of thumb relies on Postel's Law (The Robustness Principle). A 'Safe' change is an additive change. If I add a new `Age` property to the JSON response, older clients will simply ignore the new JSON field because they weren't programmed to look for it. No version required. A 'Breaking' change is a reductive or mutating change. If I rename `FirstName` to `Name`, delete a property entirely, change a property's type from a string to an integer, or require a brand new mandatory HTTP Header that wasn't previously required, the mobile app will immediately crash when attempting to parse the JSON. That requires a brand new v2 API endpoint."