用于单个路由的 ASP.NET Web API 自定义 IHttpControllerSelector [英] ASP.NET Web API custom IHttpControllerSelector for a single route

查看:12
本文介绍了用于单个路由的 ASP.NET Web API 自定义 IHttpControllerSelector的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要一个自定义的 IHttpControllerSelector,它应该只应用于特定的路由.所有其他 web api 路由应使用 IHttpControllerSelector 的默认实现.

I need a custom IHttpControllerSelector which should be applied to a specific route only. All other web api routes should use the default implementation of IHttpControllerSelector.

在研究时,我发现以下代码旨在在应用程序启动时替换 IHttpControllerSelector,但它完全替换了默认控制器选择器,这导致应用程序中的所有路由都使用我的自定义控制器选择器:

While researching I found the following code that is meant to replace the IHttpControllerSelector at application start, but it replaces the default controller selector completely, which causes that all routes in the application use my custom controller selector:

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

有没有办法为单个路由配置 IHttpControllerSelector?

Is there a way to configure the IHttpControllerSelector for a single route?

推荐答案

您可以将每个路由消息处理程序分配给需要使用不同控制器选择逻辑的路由.此处理程序将标记 HttpRequestMessage 与此请求需要区别对待的标志.

You can assign a per-route message handler to the route that needs to use a different controller selection logic. This handler would mark the HttpRequestMessage with a flag that this request needs to be treated differently.

然后简单地使 CustomControllerSelectorDefaultHttpControllerSelector 继承并检查该标志:

Then simply make the CustomControllerSelector inherit from DefaultHttpControllerSelector and inspect that flag:

  • 如果已设置,请继续使用您的自定义逻辑
  • 如果没有设置,返回base(DefaultHttpControllerSelector)

代码如下:

1) 消息处理程序,设置标志

1) message handler, setting the flag

public class RouteSpecificHandler : DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        request.Properties["UseCustomSelector"] = true;
        return base.SendAsync(request, cancellationToken);
    }
}

2) 仅将每个路由消息处理程序分配给特定路由(不要为其他路由运行)

2) assigning per route message handler to the specific route only (do not run for other routes)

        config.Routes.MapHttpRoute(
            name: "MyRoute",
            routeTemplate: "api/dummy/{id}",
            defaults: new {controller = "Dummy", id = RouteParameter.Optional},
            constraints: null,
            handler: new RouteSpecificHandler { InnerHandler = new HttpControllerDispatcher(config) }
            );

3) 尊重标志的自定义选择器:

3) custom selector respecting the flag:

public class CustomSelector : DefaultHttpControllerSelector
{
    public CustomSelector(HttpConfiguration configuration) : base(configuration)
    {
    }

    public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
    {
        if (request.Properties.ContainsKey("UseCustomSelector") &&
            request.Properties["UseCustomSelector"] as bool? == true)
        {
            //your logic goes here
        }

        return base.SelectController(request);
    }
}

4) 注册选择器:

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

编辑

如果您不希望从 DefaultHttpControllerSelector 继承 - 然后直接实现 IHttpControllerSelector,而不是调用 base.SelectController(request) 保存旧选择器作为类中的字段/属性

edit

If you wish to not inherit from DefaultHttpControllerSelector - then implement IHttpControllerSelector directly, and instead of calling the base.SelectController(request) save the old selector as a field/property in your class

public class CustomSelector : IHttpControllerSelector
{
    private HttpConfiguration _config;

    public IHttpControllerSelector PreviousSelector {get; set;}

    public CustomSelector(HttpConfiguration configuration)
    {
         _config = configuration;
    }

    public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
    {
        if (request.Properties.ContainsKey("UseCustomSelector") &&
            request.Properties["UseCustomSelector"] as bool? == true)
        {
            //your logic goes here
        }

        return PreviousSelector.SelectController(request);
    }
}

那就改注册吧:

  var previousSelector = config.Services.GetService(typeof(IHttpControllerSelector)) as IHttpControllerSelector;
 config.Services.Replace(typeof(IHttpControllerSelector), new CustomSelector(config) { PreviousSelector = previousSelector});  

这篇关于用于单个路由的 ASP.NET Web API 自定义 IHttpControllerSelector的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆