How does API versioning work
I wanted to ask for API versioning works and how to properly implement it into ASP.NET
because to me api/v1 and api/v2 just seem like 2 controllers that basically have the same controllers just handled differently
Is there a proper way to set this up and if yes, what's the best approach for it and how to handle a version like V1 going out if support if for example V5 rolls around
4 Replies
What you mean by "api versioning" is actually what's known as RESTful, the ful in the REST means it's written according to convention.
Read more on: https://restfulapi.net/versioning/
REST API Tutorial
What is REST API Versioning and How to Create Versions?
REST API versioning helps to iterate faster when the required, breaking or non-breaking, changes are identified. Learn to devise a strategy for API versioning.
api versioning and REST are completely orthogonal @SpReeD
We do two separate controllers at work, but that's probably not the greatest way.
I found this article https://weblogs.asp.net/ricardoperes/asp-net-core-api-versioning.
A bit late to the party, but in case it helps or for future readers, all of the code, documentation, and examples are available in the source repo. There are numerous posts, videos, and training provided that reference things as well.
https://github.com/dotnet/aspnet-api-versioning
GitHub
GitHub - dotnet/aspnet-api-versioning: Provides a set of libraries ...
Provides a set of libraries which add service API versioning to ASP.NET Web API, OData with ASP.NET Web API, and ASP.NET Core. - dotnet/aspnet-api-versioning
Contrary to what the referenced post claims, REST does describe how versioning is to be done. Fielding himself has called it out many times. The entire point of REST, which is merely Chapter 5 of the dissertation, is to be able to evolve networking protocols. It has been used to guide HTTP, but it wasn't only created for that. Fielding's assertion was that human are really good at creating things that can last 3 years, but not so much when it has to last 30+ years (which is about where HTTP is now).
The only accept way to version an API, according to Fielding, is by media type and content negotiation. That makes complete sense. The media type says what it is and it can of different versions. Despite it's popularity, the method of API versioning that is not RESTful is versioning by URL segment. That method violates the Uniform Interface constraint. For example,
v1/order/123
and v2/order/123
are almost certainly not different orders, but they have different data formats or shapes (e.g. media type). Media types are expressed by way of accept
and content-type
. The Uniform Interface states that the URL path is the identifier of the resource. Most devs see the identifier here as 123
, but that is simply not so. It might happen to be the value in a database behind the scenes, but that's an implementation detail. The /
in a URL path also has no meaning by spec, even though many people try to apply meaning to it or liken it to a file path. The constraint is, therefore, violated because v1
and v2
change the identifier. While it's true that a resource can have alternate identifiers, that is not the intent. This is just the tip of the iceberg, there are a number of other problems with this approach, such as if you try to implement HATEOAS. If v1/order/123
has a related Customer, how does the service know which version to use if there are multiple? Assume v1
? What if the client wants v2
?
An example of RESTful content is a web page. HTML has a version, but you almost certainly do not serve pages as v1/home.html
or v2/home.html
. The browser has to understand how to do with it. The same concept can be easily be applied to an API. With nothing but media types, you might have application/vnd.acme.order+1
, application/order+json; v=1
, or any other variant. Another example of this for APIs is with Problem Details (RFC 7807). The response can be application/problem+json
or application/problem+xml
. They are both problems with the same data elements, but different representations.
Alternate forms of API versioning are also possible without violating REST constraints. A media type is already a header, but a custom header could be used as well. It's not really necessary, but it's not necessarily wrong either. By not using a standard header, you force the client understand your custom header. The query string is also acceptable. It doesn't change the identifier for the resource. If you support HATEOAS, you should not return the API version query string value (IMHO). It's up to the client to decide. There are some ways you can return the full URL, query parameters or media types in all. If you return multiple links for different versions, the client may be able to select the most appropriate option (ex: RFC 8288: Web Linking).
The one way you can version using a URL is via the host. https://v1.api.com/order/123
doesn't change the identifier, it only changes the host. This tells the client where to find a particular resource. https://v1.api.com/order/123
, therefore, has the same identifier, but is located in a different place. This behavior can also come into play when returning location
or content-location
when resources are created or updated.