您可以将每个路由消息处理程序分配给需要使用不同控制器选择逻辑的路由。该处理程序将标记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});