Once an API is deployed and starts to be used, it should be reliable and should not break for any reason. On the other hand, as requirements change, we need to update the API code base. This should be done without breaking the current API, so both the new and old versions of the API will be active. This is where API versioning approaches come into play, to handle different versions of APIs.
Assuming that you are familiar with ASP.NET Core API development, we are going to discuss the different ways to version APIs in ASP.NET Core.
Note: If you are not familiar with building ASP.NET Core APIs, please read this blog: How to Build CRUD REST APIs with ASP.NET Core 3.1 and Entity Framework Core, Create JWT Tokens, and Secure APIs.
Prerequisites
Including versioning package and service
Microsoft provides an out-of-the-box library for ASP.NET Core API Versioning. We can install the versioning library by either using the NuGet package manager or using the following command in the package manager console:
Install-Package Microsoft.AspNetCore.Mvc.Versioning |
Now, let’s add the versioning service in the application. To do this, go to the Startup class and register the versioning service.
Refer to the following code example.
public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddApiVersioning(); }
After including the service, your API will return the ApiVersionUnspecified error.
This happens because we didn’t specify the version, which is mandatory for calling an API. To resolve this, add the default version and configure the versioning service to consider the default version if none is provided.
Refer to the following code example.
services.AddApiVersioning(config => { config.DefaultApiVersion = new ApiVersion(1, 0); config.AssumeDefaultVersionWhenUnspecified = true; });
Now the error will be resolved, and the default version will be considered for all API calls without version details.
Another useful configuration in the versioning service is to know the supported versions of an API in response to an API call. Refer to the following code example.
services.AddApiVersioning(config => { config.DefaultApiVersion = new ApiVersion(1, 0); config.AssumeDefaultVersionWhenUnspecified = true; config.ReportApiVersions = true; });
By setting the ReportApiVersions configuration as true, we can see all the supported versions of the API in the response.
We have successfully included the versioning service in the application, so now let’s see some approaches to versioning.
Versioning approaches
We need to do the following two steps to implement API versioning:
- Map the controller or action with the supported version.
- Configure the versioning service to read and identify the version the client calls.
In the sections that follow, I explain the different approaches for both of these steps. Each approach has its pros and cons- you have to choose the one that suits you.
Versioning controller
We can specify which API versions can access a controller action by using the ApiVersion attribute in the controller. Then, only those specified versions will be allowed to access the controller actions. All other versions will return the UnsupportedApiVersion error.
Refer to the following code example.
[ApiVersion("1.0")] [ApiVersion("2.0")] [Route("[controller]")] [ApiController] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering" }; [HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } }
Versioning action
We can also specify an action to support only the specified API versions with the MapToApiVersion attribute. Then, only those mapped API versions will have access to the API. Other versions will return the UnsupportedApiVersion error.
Refer to the following code example.
[HttpGet("{weather}")] [MapToApiVersion("2.0")] public WeatherForecast Get(string weather) { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToList().Where(weatherList => weatherList.Summary == weather).FirstOrDefault(); }
Using a URI to pass the version details
A URI is an easy way to pass version details to the versioning service. We can use a query string or a URI absolute path to state the version in an API call.
Using the query string
By default, the versioning service reads the query string named api-version. If the query string is present in the URI, then the service will consider the query string value as the API version.
We can override this default behavior and configure a different query string to mention the API version. To do so, we need to configure the versioning service to look for a specific query string value in the URI to get the value of the calling API version.
Refer to the following code example.
services.AddApiVersioning(config => { config.DefaultApiVersion = new ApiVersion(1, 0); config.AssumeDefaultVersionWhenUnspecified = true; config.ReportApiVersions = true; config.ApiVersionReader = new QueryStringApiVersionReader("version"); });
Demo URI
https://localhost:44335/weatherforecast/cool?version=2.0
Using URI absolute path
By using the UrlSegmentApiVersionReader, we can use part of the URI segment to specify the API version. There are no inputs needed to use the segment reader while configuring the service. It will assume that the version will be present in the URI segment. To make this work, we have to configure the controller and the versioning service. Refer to the following code.
Startup service
services.AddApiVersioning(config => { config.DefaultApiVersion = new ApiVersion(1, 0); config.AssumeDefaultVersionWhenUnspecified = true; config.ReportApiVersions = true; config.ApiVersionReader = new UrlSegmentApiVersionReader(); });
Controller
[Route("v{version:apiVersion}/[controller]")] [ApiVersion("1.0")] [ApiVersion("2.0")] [ApiController] public class WeatherForecastController : ControllerBase { private static readonly string[] Summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" }; [HttpGet] public IEnumerable<WeatherForecast> Get() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } }
Demo URI
https://localhost:44335/v2/weatherforecast
https://localhost:44335/v1/weatherforecast
Using headers to pass the version details
By configuring the versioning service, we can use the HTTP request header values to pass the API version. To get the version from the header, we need to configure the versioning service using the HeaderApiVersionReader and mention the header that we are going to use in our application.
Refer to the following code example.
Startup Service
services.AddApiVersioning(config => { config.DefaultApiVersion = new ApiVersion(1, 0); config.AssumeDefaultVersionWhenUnspecified = true; config.ReportApiVersions = true; config.ApiVersionReader = new HeaderApiVersionReader("x-version"); });
Demo URI and header
Other versioning approaches
There are also other versioning approaches available in the ASP.NET Core API versioning library.
You can apply a specific version in the namespace and pass the version details in the content type. Also, you can write your own version reader for the versioning library and use that in the service. Writing your own reader will let you read the version by your app logic, so it will be completely based on your needs.
Conclusion
In this article, we have learned how to apply API versioning in ASP.NET Core and some of the common versioning approaches. I hope you found this article useful. Try out the methods listed in this blog post and leave your feedback in the comments section.
The Syncfusion ASP.NET Core UI controls library, powered by Essential JS 2, is the only suite you will ever need to build an application. It contains over 70 high-performance, lightweight, modular, and responsive UI controls in a single package. Use them to enhance your productivity!
For existing customers, the new version is available for download from the License and Downloads page. If you are not yet a Syncfusion customer, you can try our 30-day free trial to check out our available features. Also, we encourage you to try our samples on GitHub.
You can also contact us through our support forum, Direct-Trac, or feedback portal. We are always happy to assist you!
Comments (3)
Nice Dhinesh,
Is Swagger (swashbuckle) have support of rednering the api as per it?
Hi Kamran,
Thanks for your feedback,
Yes, swagger has support for aspnet core API versioning. Please refer to the below documentation to enable and customize swagger to generate doc based on API version.
https://github.com/domaindrivendev/Swashbuckle.AspNetCore#generate-multiple-swagger-documents
https://github.com/domaindrivendev/Swashbuckle.AspNetCore#customize-the-action-selection-process
Thanks,
Dhinesh V.
Consider extending this post by adding Swagger.
API versioning is great, but we need an easy way to show that via UI and Swagger is great for that.
Comments are closed.