Versioning is key when developing APIs, especially if they're exposed outside of your team or organization. What would you do if an API your application consumed suddenly changed input parameters or changed its output? Let me guess: Probably scream out loud in frustration..
So please dont be that guy who break applications in other organizations. Version your APIs! This is how.
Lets start with the basics. A version number consist, normally, of four numbers
Major.Minor.Patch.Revision. I´ve rarly or never seen
Patch being used as part of an API version, probably because they refer to internal changes and not the contract being exposed to the consumers. Lets cover all four anyway.
You should bump the
Major version if you have any breaking changes in the contract between your application and consumers of your API. An example would be that you deprecated a method or changed mandatory input parameters to a method that would affect the consuming part.
Minor changes to your application which does not break the integration between your system and consuming applications. This might be bug fixes or that you´ve added extra data in the response back to the consuming application.
Internal bugfixes in your application.
Usually a number added by the build server to differentiate release across the versions.
Microsoft have released a NuGet package solely for the purpose of API versioning. You can install it to your project from the command line
dotnet add package Microsoft.AspNetCore.Mvc.Versioning --version 5.0.0
Once the download is complete, find the method
Startup.cs and add the following statement
services.AddApiVersioning();. The next step is to find your controller and map that specific controller to an api version. Attribute the controller with
[ApiVersion("1.0")]in order to do so.
Now you can navigate to your endpoint and make sure that you specify which version of the api to use by adding
?api-version=1.0 at the end of your url.
Change versioning schemas
If you don´t like the default syntax of adding a query parameter to specify the api-version, you can just change it.
You got several options to change the versioning schema, implement it yourself or including a pre-defined class from the NuGet-package.
This is done by adding an implementation of
IApiVersionReader in the
AddApiVersioning method. You can also choose to implement this yourself if the specific use case isn´t covered by the implementations provided by Microsoft.
If you want to use the version as a segment of the url, you can add an instance of
UrlSegmentApiVersionReader in the example above. If you choose this implementation you'll have to change the route for all of your controllers to support this. This version reader uses string interpolation to inject the variable to your route. The route for the example below would be
If your consumers navigate to the api without specifying the api-version, they'll get an error message telling them to specify it. You can, however, assume that they want to consume the default version of the api by specifying so in the
What about swagger, is it supported?
Yes, you document your version with swagger, but it's way more of hazzle than first expected. These are the steps:
1. Install Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer
dotnet add package Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer --version 5.0.0
2. Implement the method
3. Update the
AddSwaggerGen method to list Api title and version
4. Update method
UseSwaggerUI in the
When you run the application, you should see that the swagger definition shows up in your browser.
Deprecate versions of your API.
You probably want to deprecate your old APIs as new ones are created. It would also be nice to report back to the consumer which of the versions that are deprecated. This can be achieved by setting the property
Then mark the controller as deprecated like this:
If we have several API controllers with the same route, but different versions, the http header in the response will report back the supported and deprecated versions.
Version is key when designing APIs. The NuGet package has alot more functionality than demonstrated above. I encourage you to try it out and play around with the different schemas and functionality in this library.
You can find the complete source code here: https://github.com/Thorstensen/api-versioning