ASP.Net MVC:拦截路由和转发至不同的动作/路线(ASP.Net MVC: Intercep

2019-10-21 00:32发布

我们对我们网站的REST API。 我们已经通过前缀与端点加入或更新的发行版的端点版本的端点。 例如

  • / V1 /服务一个
  • / V2 /服务-B
  • / V3 /服务-C

这种方法的问题是,我们有我们的客户端代码呼唤着不同版本的端点。 例如,一个页面可以叫出/ V3 /服务-C和/ V1 /服务的一个。

我想设定,让我们的开发人员可以通过只是端点的最新版本前缀端点访问最新版本的API。 使用上面的示例,该网页将代替调出/ V3 /服务-c和/ V3 /服务一个,以及用于服务一个,该请求将被转发到绑定到/ V1 /服务所涉及的动作,因为这是前/ v3的服务的最新版本。

我知道我可以只手动明确添加代码中的路线,但会得到难以管理不同版本的端点。

我知道如何从路由表中列举的版本,并解析他们。 所以这部分就解决了。 然而,是什么我不知道的是我究竟是如何去拦截路由因此调用/ V3 / - 维修 - 一个可以转发到我已经安装了/ V1 /服务的一个途径。

有任何想法吗?

Answer 1:

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

        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辅助类,它可以找到这里 。

然后你只需要注册自定义选择:

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

对于一个完整的例子- 看看这里Github上 ,它的的ASP.NET Web API 2食谱书的一部分。



文章来源: ASP.Net MVC: Intercepting routing and forwarding to different actions/routes