我需要一个自定义的 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.
然后简单地使 CustomControllerSelector
从 DefaultHttpControllerSelector
继承并检查该标志:
Then simply make the CustomControllerSelector
inherit from DefaultHttpControllerSelector
and inspect that flag:
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)
保存旧选择器作为类中的字段/属性
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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!