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.
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 we are going your 1st approach then it helps to route and allow us to get the data for V1, V2.... but now we have taken an example of v1 and v2 for one controller so routing code will be as below:
config.Routes.MapHttpRoute(
name: "1-0Api",
routeTemplate: "tables/v1/Products",
defaults: new { controller = "ProductsV1", id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "2-0Api",
routeTemplate: "tables/v2/Products",
defaults: new { controller = "ProductsV2", id = RouteParameter.Optional }
);
But we have more than 20 controllers and multiple versions then how to make it generic.
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.
Any chance you still have the default Web API route defined and it's before your custom route? That would cause your scenario to fail. The following route definitions (note the order) worked for me.
public static void Register(HttpConfiguration config) {
config.Routes.MapHttpRoute(
name: "1-0Api",
routeTemplate: "api/1.0/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
Using HttpControllerSelctor Implementation Controller Versioning in Web Api 2 using URL
for more information you can check and Here