Routing in ASP NET Web API - for different API versions

I am reading about Attribute Routing in Web API 2 from here

The article says:

 Here are some other patterns that attribute routing makes easy. API versioning In this example, "/api/v1/products" would be routed to a different controller than "/api/v2/products". /api/v1/products /api/v2/products 

How did it happen?

EDIT: I would do this in normal routing:

 public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/v2/products", defaults: new { controller = V2_Products } ); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/v1/products", defaults: new { controller = V1_Products } ); } } 

Can someone explain to me how to do this in Attribute Routing ? And how is it that using Attribute Routing simpler and more convenient for this example (according to the article)?

+5
c # asp.net-web-api asp.net-mvc-5 routing
source share
3 answers

There are many ways to implement attribute routing versions; In fact, the main way is to use the RoutePrefix attribute for each version of your ApiController

 [RoutePrefix("v1")] public class V1_ProductsController : ApiController { [Route("products")] public IEnumerable<string> Get() { return new string[] { "v1-product1", "v1-product2" }; } //.... } [RoutePrefix("v2")] public class V2_ProductsController : ApiController { [Route("products")] public IEnumerable<string> Get() { return new string[] { "v2-product1", "v2-product2" }; } //.... } 

/v1/products goes to the first version /v2/products goes to the second.

+7
source share

You can do this by overriding DefaultHttpControllerSelector

there you override the selectcontroller method

 public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { HttpControllerDescriptor controllerDescriptor = null; IDictionary<string, HttpControllerDescriptor> controllers = GetControllerMapping(); IHttpRouteData routeData = request.GetRouteData(); if (routeData == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } object apiVersion; if (!routeData.Values.TryGetValue("Version", out apiVersion)) { apiVersion = "1"; } object controllerName; if (!routeData.Values.TryGetValue("controller", out controllerName)) { controllerName = string.Empty; } if (controllerName == null) { throw new HttpResponseException(HttpStatusCode.NotFound); } string newControllerName = String.Concat(controllerName.ToString(), "V", apiVersion); if (controllers.TryGetValue(newControllerName, out controllerDescriptor)) { return controllerDescriptor; } if (controllers.TryGetValue(controllerName.ToString(), out controllerDescriptor)) { return controllerDescriptor; } throw new HttpResponseException(HttpStatusCode.NotFound); } 

Then you add webapiconfig routes

  config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{version}/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); 

and register controller selector in webapiconfig

 config.Services.Replace(typeof(IHttpControllerSelector), new ApiVersioningSelector(config)); 

So now, if you select the ProductsV1Controller controller, it will be reffer / api / v1 / products. Also note that my example also supports routes without version, so if v1 is not found, it will try to check if ProductsController exists

PS. The code updates one error :(

+8
source share

Another simple way is to configure your route as api / {folder} / {controller} / {action}, where you can specify a name in the folder as V1 or V2.

A good way would be to implement your own controller selector. You can use this link for more information.

The interface used by the web API to select the controller is IHttpControllerSelector . An important method of this interface is the SelectController, which selects the controller for this HttpRequestMessage.

+3
source share

All Articles