I have an ASP.NET MVC 4 app. I want to use the new Web API feature for learning purposes. I want to learn how to expose the same endpoint, but provide different versions of it. In other words, I want to expose endpoints like the following:
http://mysite/1.0/Products/1
http://mysite/2.0/Products/1
In an attempt to do this, I added an "Api" directory within the default "Controllers" directory. Within the "Api" directory, I have two other directories: "Version1-0" and "Version2-0". Each of those directories has an ApiController named "ProductsController".
I tried to expose the endpoints by adding the following route definition in my WebApiConfig.cs file:
config.Routes.MapHttpRoute(
name: "1-0Api",
routeTemplate: "api/1.0/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
Unfortunately, I can't figure out how to expose actions via the URLs I listed above. What am I doing wrong? Thank you!
Summary. As the application grows and business need increase, Versioning of the API is one of the difficult and important part of the API as it makes the API backward compatible. We can do Versioning in ASP.NET Web API with URI, QueryString, Custom Headers and Accept Header parameters, etc.
ASP.NET MVC 4 projects now include Entity Framework 5. One of the great features in Entity Framework 5 is support for database migrations. This feature enables you to easily evolve your database schema using a code-focused migration while preserving the data in the database.
You're probably running into issues because the controllers have the same name. The controller namespace or the folder it's in doesn't matter at all to WebAPI, only the name does. The simplest thing I can think of is to rename your controllers ProductsV1Controller and ProductsV2Controller and set up two routes to point to your controllers:
config.Routes.MapHttpRoute(
name: "1-0Api",
routeTemplate: "api/1.0/Products/{id}",
defaults: new { controller = "ProductsV1", id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "2-0Api",
routeTemplate: "api/2.0/Products/{id}",
defaults: new { controller = "ProductsV2", id = RouteParameter.Optional }
);
Of course, this gets messy if you have multiple controllers you want to expose in this way. Let me see if I can't think of something better for you.
Sebastiaan Dammann has, on his blog, described how he did Web API versioning by writing his own implementation of IHttpControllerSelector
and supporting interfaces.
http://damsteen.nl/blog/implementing-versioning-in-asp.net-web-api
He's also put the code on github
https://github.com/Sebazzz/SDammann.WebApi.Versioning
And packaged it in NuGet for us! :)
https://nuget.org/packages/SDammann.WebApi.Versioning
While implementing IHttpControllerSelector
is certainly (imho) the Right Way to do Web API versioning, I think it would be ideal if he included the ability to version based on the HTTP (see http://barelyenough.org/blog/2008/05/versioning-rest-web-services/).Accept
header
Unfortunately my client side is unable to work with the Accept
header, so his RouteVersionedControllerSelector
is ideal for me.
Edit: Not sure how I missed it, but there is indeed an AcceptHeaderVersionedControllerSelector
that can be used to do versioning the ideal way. I'm currently using it on a new project, but it still has some drawbacks
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With