問題描述
我需要一個自定義的 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:
- 如果已設置,請繼續使用您的自定義邏輯
- 如果沒有設置,返回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的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!