JsonApiDotNetCore
JsonApiDotNetCore copied to clipboard
How to handle API versioning
SUMMARY
I'm looking for some guidance on how to handle API versioning using the JsonApiDotNetCore library. As an example, let's say I have a Book entity and I currently have a series of endpoints defined for CRUD operations on Books (i.e. /api/v1/books). Now let's say I'd like to make some changes to the Book entity and would like to reflect this in a new endpoint (i.e. /api/v1.1/books) while retaining the existing v1 endpoint as much as possible. I could create a new BookV1p1 resource class and a new controller, but now I have two model classes that would be mapped to two different tables via EF Core. What I would like to achieve is to be able to make the desired changes to the EF Core model and create two different controllers for interacting with this model (/api/v1.1/books and /api/v1/books). /api/v1.1/books would use the new Book EF Core model directly, whereas /api/v1/books would perform some conversions from the old Book definition to the new one. I was reading through the Extensibility section of the documentation but was struggling to identify what the appropriate layer to handle this case is. Any help pointing me in the right direction here would be greatly appreciated.
VERSIONS USED
- JsonApiDotNetCore version: 5
- ASP.NET Core version: 6
- Entity Framework Core version: 6
- Database provider: MySQL (Pomelo EF Core Provider)
Hi @rsmith8917,
As far as I'm aware, API versioning was never really thought through for JsonApiDotNetCore. Over the years, we've seen comments from users in issues and the chat about their approaches, but it really depends on the use case and what kinds of changes in versions are to be expected.
Stripe's approach to API versioning is described at https://stripe.com/blog/api-versioning. I like the idea of migrations, which could be added to JsonApiReader/Writer. They would transform the incoming JSON body to the latest version and vise-versa. I'd recommend using a HTTP header or query string to pass the version, so you won't need to adapt routing. This leaves the controllers, resources and DB mappings unchanged.
Another solution would be to run the transforms in a reverse proxy such as YAST.
It would be interesting to gather a list of versioning changes and think about a universal solution in JsonApiDotNetCore. Things that come to mind:
- Attributes
- Adding new attributes
- Merging/splitting of attributes
- Changing the data type or requiredness of attributes
- Renaming attributes
- Relationships...?
- Resources...?
- Endpoints...?
Atomic operations is a separate concern: it codifies requests in a different way. If routes are involved, LinkBuilder probably requires changes to accommodate the version in the URLs. If new endpoints or relationships must be blocked from older versions, JsonApiMiddleware likely needs to handle that.
Then there's query strings, such as filters and sorting. What should happen when trying to filter or sort on an attribute that was split-up in the latest version? There's no generic mechanism to produce a WHERE clause for that.
All in all, this is hard to design without a clear scope with good use cases.
@rsmith8917 Any thoughts about the above?
Closing due to inactivity.