API versioning is a critical aspect of building and maintaining robust and scalable web services, especially in environments where continuous improvement and frequent updates are key. In ASP.NET Core, handling multiple versions of an API can be straightforward, yet it requires a clear understanding of the tools and techniques available to manage changes effectively. Whether you're adding new features, fixing bugs, or making breaking changes, proper API versioning ensures that your users can continue to interact with your service seamlessly.
In this blog post, we'll explore the various strategies for implementing API versioning in ASP.NET Core. We'll cover the basics, delve into practical examples, and discuss best practices to help you maintain backward compatibility while rolling out new versions of your API. Whether you're a beginner or an experienced developer, this guide will equip you with the knowledge to handle API versioning with confidence in your ASP.NET Core applications.
Why do we need API versioning ?
Backward Compatibility: As APIs evolve, older clients may still rely on previous versions. Versioning ensures that these clients can continue to function without breaking when new updates or features are introduced.
Safe Introduction of Breaking Changes: Over time, APIs may need significant changes that are not backward-compatible. Versioning allows these changes to be introduced without disrupting existing users.
Clear Evolution Path: Versioning provides a structured approach to evolving an API, allowing developers to introduce new features, deprecate old ones, and communicate these changes effectively to users.
Reduced Technical Debt: By managing versions systematically, you can phase out outdated features and code, reducing technical debt while maintaining service continuity.
Support for Multiple Client Types: Different clients (e.g., mobile apps, web apps) might need different versions of the API. Versioning enables support for these diverse needs without forcing a one-size-fits-all approach.
Improved Testing and Documentation: With versioning, each API version can have its own set of tests and documentation, ensuring that changes are well-understood and thoroughly tested before being released.
Better User Experience: By carefully managing how and when changes are introduced, you can maintain a smooth user experience, minimizing disruptions for end-users as the API evolves.
Compliance and Governance: In regulated industries, maintaining different versions of an API may be necessary to comply with legal or contractual obligations, ensuring that specific functionalities remain available or unchanged over time.
API Versioning in ASP .NET Core
You will need to start by installing two NuGet packages that we'll need to implement API versioning:
dotnet add package Asp.Versioning.Http
dotnet add package Asp.Versioning.Mvc.ApiExplorer
builder.Services.AddApiVersioning(options =>
{
options.DefaultApiVersion = new ApiVersion(1.0);
options.ReportApiVersions = true;
options.AssumeDefaultVersionWhenUnspecified = true;
options.ApiVersionReader = ApiVersionReader.Combine(
new UrlSegmentApiVersionReader());
}).AddApiExplorer(options =>
{
options.GroupNameFormat = "v";
options.SubstituteApiVersionInUrl = true;
});
DefaultApiVersion
- Sets the default API version. Typically, this will bev1.0
.ReportApiVersions
- Reports the supported API versions in theapi-supported-versions
response header.AssumeDefaultVersionWhenUnspecified
- Uses theDefaultApiVersion
when the client didn't provide an explicit version.ApiVersionReader
- Configures how to read the API version specified by the client. The default value isQueryStringApiVersionReader
The AddApiExplorer
method is helpful if you are using Swagger. It will fix the endpoint routes and substitute the API version route parameter.
Versioning on API Controllers:
[ApiController]
[Route("api/chat")]
[ApiVersion(version: 1)]
[ApiVersion(version: 2)]
public class ChatController : ControllerBase
{
private readonly IConversationService _conversationService;
public ChatController(IConversationService conversationService)
{
_conversationService = conversationService;
}
[HttpPost]
[Route("send")]
[MapToApiVersion(1)]
public async Task<IActionResult> Get([FromBody] ChatRequest chatRequest)
{
var response = await _conversationService.SendChatRequest(chatRequest.Message);
return Ok(response.Select(x => x.Text));
}
[HttpPost]
[Route("send")]
[MapToApiVersion(2)]
public async Task<IActionResult> GetV2([FromBody] ChatRequest chatRequest)
{
var streamingContentList = new StringBuilder();
var response = _conversationService.StreamChatRequest(chatRequest.Message);
await foreach (var stream in response)
{
streamingContentList.Append(stream.ContentUpdate);
}
return Ok(streamingContentList);
}
}
How to deprecate any API ?
[Route("api/chat")]
[ApiController]
[ApiVersion(version: 1, Deprecated = true)]
[ApiVersion(version: 2)]
public class ChatController : ControllerBase
{
public ChatController(IConversationService conversationService)
{
}
}
If you want to deprecate an old API version, you can set the Deprecated
property on the ApiVersion
attribute. The deprecated API versions will be reported using the api-deprecated-versions
response header.
Conclusion
In conclusion, implementing API versioning using the Asp.Versioning.Http
package in ASP.NET Core is a powerful way to manage the evolution of your APIs while maintaining backward compatibility. This package offers a flexible and straightforward approach to versioning, allowing you to cater to various client needs and introduce new features without disrupting existing users.
By leveraging the different versioning strategies provided—such as URL path, query string, header, and media type versioning—you can ensure that your API remains scalable, maintainable, and user-friendly. The Asp.Versioning.Http
package not only simplifies the setup process but also integrates seamlessly with ASP.NET Core, making it easier to enforce versioning policies and manage the lifecycle of your API.