ASP.NET Web API为单个路由定制IHttpControllerSelector

时间:2014-09-18 13:59:33

标签: asp.net asp.net-web-api routes

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

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

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

有没有办法为单条路线配置IHttpControllerSelector

1 个答案:

答案 0 :(得分:11)

您可以为需要使用不同控制器选择逻辑的路由分配每路由消息处理程序。此处理程序将标记HttpRequestMessage,并标记该请求需要以不同方式处理。

然后只需从CustomControllerSelector继承DefaultHttpControllerSelector并检查该标志:

  • 如果已设置,请继续使用自定义逻辑
  • 如果未设置,请返回基地(DefaultHttpControllerSelector

以下是代码:

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

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

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

        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)尊重旗帜的自定义选择器:

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)将旧选择器保存为您班级中的字段/属性

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});