ASP.NET Core API Versioning
There are several versioning strategies that can be used to version ASP.NET Core APIs. In this post we will have a look at the various versioning strategies, how to implement them, and configure Swagger.
There are several versioning strategies that can be used to version ASP.NET Core APIs. In this post we will have a look at the various versioning strategies, how to implement them, and how to configure Swagger UI.
Why do we need version APIs in the first place? Simply, because things change and when they change we want to handle it in the best possible way. For example, we may want to introduce a change to the request or make a change to the response. And, when we change it, we don't want to force all the consumers of our API to upgrade - we want to give our consumers the freedom to upgrade when they are ready. We also have to remain backwards compatible for as long as possible. If we do introduce a breaking change, how do we communicate it to our consumers?
Through an effective versioning strategy we can introduce changes and give our consumers the freedom to upgrade when they are ready. We can also introduce a breaking change and have our consumers accept and change to accommodate the breaking change over time.
Versioning Strategies
In the table below there are several versioning strategies that can be used by APIs to introduce change. My personal preference is to use the query string parameter as it is explicit about the version we use and we can easily specify the default API version to use if it's not specified.
Versioning Strategy | Example |
---|---|
Query String | https://example.com/api/weather/za?api-version=2.1 |
URL Segment | https://example.com/api/v2/weather/za |
Header | api-version: 2.0 |
Media Type | Content-Type: application/json;v=2.0 |
How do we decide what the version number should be? We can use Semantic Versioning (MAJOR.MINOR) to decide whether it should be v3.0 or v3.24 by using the following criteria:
- MAJOR version when you make incompatible API changes,
- MINOR version when you add functionality in a backward compatible manner.
Alternatively, we can use version numbers like 1.1 (Beta) by using version format strings.
Installation
To add versioning to your API, add the following NuGet packages to your API project:
Configuration
To configure versioning for the API, add the following to the Program.cs file.
In the options, set ReportApiVersions to true to return the available API versions to the caller in the response headers, for example:
Set the ApiVersionReader to one of the following to tell the API where to find the version specification:
- QueryStringApiVersionReader
- UrlSegmentApiVersionReader
- HeaderApiVersionReader
- MediaTypeVersionReader
The GroupNameFormat is the version format string to use for the API, for example: v'VVV
.
DefaultApiVersion specifies the API version to assume when an API version is not given. The default value is derived from DefaultApiVersion.
Usage
Add the ApiVersion attribute to the controller specifying the API versions that are supported by the controller, for example:
MapToApiVersion maps the controller action method to a particular group or several groups, where a group is a "version".
Setting Deprecated to true will advertise the API version as deprecated and disable it in Swagger UI (it can still be tried out in Swagger), for example:
Note: When using the URL segment version reader you need to update the Controller route to [Route("v{version:apiVersion}/[controller]")]`
.
Configuring Swagger UI
To get the API definitions in Swagger UI to display the different API versions we need to update the Swagger endpoint with the group names.
Version 1 of the WeatherForecast API:
Version 2 of the WeatherForecast API:
The example application in GitHub includes an OperationFilter to automatically set the version number in the operation to the selected version. It also includes a DocumentFilter to change the operations to lowercase.
Conclusion
In this post we showed the different ways in which a version can be applied to an API and how to configure Swagger so that the different versions of the API can be selected.
An example repository is available on GitHub.