ASP.Net MVC: intercepting routing and redirecting to different actions / routes

We have a REST API for our site. We limited endpoints to versions by adding or updating an endpoint with an endpoint. for instance

  • / v1 / service-a
  • / v2 / service-b
  • / v3 / service s

The problem with this approach is that our client code invokes different versions of endpoints. For example, a page might call / v 3 / service-c and / v1 / service-a.

I would like to configure it so that our developers can access the latest version of the API, just the endpoint prefix with the latest version of the endpoints. Using the above example, the page will instead refer to / v 3 / service-c and / v3 / service-a, and for service-a the request will be redirected to the action associated with / v 1 / service-a, since this was the latest version service before / v 3.

I know that I can simply manually add routes explicitly to the code, but that would make it difficult to manage different versions of the endpoints.

I know how to list versions from a route table and analyze them; so the part is resolved. However, I'm not sure exactly how I intercept routing so that calls to / v 3 / -service-a can be redirected to the route that I set for / v 1 / service-a.

Any ideas?

0
source share
1 answer

Imagine you are declaring your routes as follows:

config.Routes.MapHttpRoute("defaultVersioned", "v{version}/{controller}/{id}", new { id = RouteParameter.Optional }, new { version = @"\d+" }); config.Routes.MapHttpRoute("default", "{controller}/{id}", new { id = RouteParameter.Optional }); 

Now you can create separate controllers for individual versions using a specific naming convention, for example:

 public class FooController : ApiController {} public class FooV2Controller : ApiController {} public class FooV3Controller : ApiController {} 

Now, since the version is part of your route, you can implement a specialized controller selector where you get the version from the route and select the appropriate controller based on this.

 public class VersionAwareControllerSelector : DefaultHttpControllerSelector { public VersionAwareControllerSelector(HttpConfiguration configuration) : base(configuration) { } public override string GetControllerName(HttpRequestMessage request) { var controllerName = base.GetControllerName(request); var versionFinder = new VersionFinder(); var version = versionFinder.GetVersionFromRequest(request); if (version > 0) { return GetVersionedControllerName(request, controllerName, version); } return controllerName; } private string GetVersionedControllerName(HttpRequestMessage request, string baseControllerName, int version) { var versionControllerName = string.Format("{0}v{1}", baseControllerName, version); HttpControllerDescriptor descriptor; if (GetControllerMapping().TryGetValue(versionControllerName, out descriptor)) { return versionControllerName; } throw new HttpResponseException(request.CreateErrorResponse( HttpStatusCode.NotFound, String.Format("No HTTP resource was found that matches the URI {0} and version number {1}", request.RequestUri, version))); } } 

This code uses the helper class VersionFinder , which can be found here .

Then you just need to register a custom selector:

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

For a complete example, take a look here on Github , this is part of the ASP.NET Web API 2 Recipes book.

+10
source

Source: https://habr.com/ru/post/982648/


All Articles