Introduction
API versioning in .NET Core is essential for maintaining backward compatibility, enabling smooth feature evolution, and preventing breaking changes for existing clients. As APIs grow and new features are introduced, older consumers must continue functioning without disruption. Implementing a structured API versioning strategy in ASP.NET Core Web API ensures long-term maintainability, controlled releases, and enterprise-grade scalability.
Why API Versioning Is Important
In production environments, APIs are consumed by:
Web applications
Mobile applications
Third-party integrations
Microservices
If a response model changes, a route is modified, or a field is removed without versioning, existing consumers may fail. API versioning allows developers to introduce enhancements while preserving legacy behavior.
Common API Versioning Strategies
ASP.NET Core supports multiple API versioning approaches. Each has different trade-offs in terms of clarity, flexibility, and maintainability.
1. URL Path Versioning
Example:
/api/v1/products
/api/v2/products
This is the most commonly recommended and production-friendly approach.
Advantages:
This approach is widely adopted in RESTful API design because versioning becomes part of the route structure.
2. Query String Versioning
Example:
/api/products?api-version=1.0
Advantages:
However, it is less explicit and sometimes harder to manage in large systems.
3. Header Versioning
Example:
api-version: 1.0
Advantages:
Drawbacks:
4. Media Type (Accept Header) Versioning
Example:
Accept: application/json;version=1.0
This approach is more REST-purist but adds complexity and is less commonly used in practical enterprise applications.
Recommended Approach: URL Path Versioning with Microsoft API Versioning Package
The best way to handle API versioning in .NET Core is to use the official API versioning package and implement URL path versioning. It offers clarity, maintainability, and strong tooling support.
Install the NuGet package:
dotnet add package Microsoft.AspNetCore.Mvc.Versioning
Step 1: Configure API Versioning
Inside Program.cs:
builder.Services.AddApiVersioning(options =>
{
options.AssumeDefaultVersionWhenUnspecified = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.ReportApiVersions = true;
});
This configuration:
Step 2: Define Versioned Controllers
Example controller using URL versioning:
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products from V1");
}
}
Create a second version:
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class ProductsV2Controller : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return Ok("Products from V2 with enhanced response");
}
}
This ensures clean separation between versions while preserving older contracts.
Supporting Multiple Versions in One Controller
You can also map multiple versions within a single controller:
[ApiVersion("1.0")]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/[controller]")]
public class ProductsController : ControllerBase
{
[HttpGet]
[MapToApiVersion("1.0")]
public IActionResult GetV1()
{
return Ok("Version 1");
}
[HttpGet]
[MapToApiVersion("2.0")]
public IActionResult GetV2()
{
return Ok("Version 2");
}
}
This approach reduces duplication when differences between versions are minimal.
Versioning Best Practices in Enterprise Applications
Never modify an existing version after release
Deprecate versions gradually instead of immediate removal
Communicate version lifecycle clearly
Maintain documentation per version
Use semantic versioning (major.minor)
Log API usage per version for monitoring
Proper governance prevents version sprawl and technical debt accumulation.
Handling Breaking Changes Safely
When introducing breaking changes:
Create a new major version
Maintain old version for a transition period
Announce deprecation timeline
Monitor client migration progress
In microservices architecture, API gateways can route traffic based on version, simplifying traffic management during upgrades.
API Versioning and Swagger Integration
For better developer experience, integrate versioning with Swagger (OpenAPI). Configure Swagger to generate separate documentation per API version. This improves API discoverability and reduces consumer confusion.
When Not to Version
If changes are:
You may not need a new version. Over-versioning can increase maintenance overhead.
Summary
The best way to handle API versioning in .NET Core is to implement structured version control using the official API versioning package combined with URL path versioning for clarity and maintainability. By defining explicit versioned routes, preserving backward compatibility, managing breaking changes carefully, and integrating version awareness into documentation and monitoring workflows, teams can build scalable and enterprise-ready ASP.NET Core Web APIs that evolve safely without disrupting existing consumers.