Asp.net web api ASP.NETMVC:拦截路由并转发到不同的操作/路由

Asp.net web api ASP.NETMVC:拦截路由并转发到不同的操作/路由,asp.net-web-api,asp.net-mvc-routing,Asp.net Web Api,Asp.net Mvc Routing,我们的站点有一个RESTAPI。我们已经通过使用端点添加或更新的发布版本作为端点的前缀来对端点进行版本控制。比如说 /v1/service-a /v2/服务-b /v3/service-c 这种方法的问题是我们的客户端代码调用不同版本的端点。例如,页面可能会调用/v3/service-c和/v1/service-a 我想对其进行设置,这样我们的开发人员就可以通过在端点前面加上最新版本的端点来访问最新版本的API。使用上面的示例,页面将调用/v3/service-c和/v3/service-a

我们的站点有一个RESTAPI。我们已经通过使用端点添加或更新的发布版本作为端点的前缀来对端点进行版本控制。比如说

  • /v1/service-a
  • /v2/服务-b
  • /v3/service-c
这种方法的问题是我们的客户端代码调用不同版本的端点。例如,页面可能会调用/v3/service-c和/v1/service-a

我想对其进行设置,这样我们的开发人员就可以通过在端点前面加上最新版本的端点来访问最新版本的API。使用上面的示例,页面将调用/v3/service-c和/v3/service-a,对于service-a,请求将转发到绑定到/v1/service-a的操作,因为这是/v3之前的最新版本的服务

我知道我可以在代码中显式地手动添加路由,但如果管理不同版本的端点,这将变得很困难

我知道如何从路由表中枚举版本并解析它们;这一部分就解决了。但是,我不确定的是,我到底如何拦截路由,以便将对/v3/-service-a的调用转发到我为/v1/service-a设置的路由


有什么想法吗?

想象一下你这样宣布你的路线:

        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 });
现在,您可以使用特定的命名约定为不同的版本创建不同的控制器,例如:

public class FooController : ApiController {}

public class FooV2Controller : ApiController {}

public class FooV3Controller : ApiController {}
现在,因为版本是路由的一部分,所以您可以实现一个自定义控制器选择器,从路由中选择版本,并基于此选择相关的控制器

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)));
    }
}
此代码使用可以找到的
VersionFinder
helper类

然后您只需注册自定义选择器:

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

作为一个完整的示例,它是ASP.NET Web API 2菜谱手册的一部分。

想象一下,您这样声明您的路线:

        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 });
现在,您可以使用特定的命名约定为不同的版本创建不同的控制器,例如:

public class FooController : ApiController {}

public class FooV2Controller : ApiController {}

public class FooV3Controller : ApiController {}
现在,因为版本是路由的一部分,所以您可以实现一个自定义控制器选择器,从路由中选择版本,并基于此选择相关的控制器

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)));
    }
}
此代码使用可以找到的
VersionFinder
helper类

然后您只需注册自定义选择器:

  config.Services.Replace(typeof(IHttpControllerSelector), new VersionAwareControllerSelector(config));
作为一个完整的示例,它是ASP.NET Web API 2菜谱手册的一部分