我想知道是否可以在 DelegatingHandler 的 SendAsync 方法中访问正在执行(或即将执行)的控制器?我似乎无法弄清楚如何访问它,我认为这是因为它在控制器执行之外执行......
可以参考吗?
我想知道是否可以在 DelegatingHandler 的 SendAsync 方法中访问正在执行(或即将执行)的控制器?我似乎无法弄清楚如何访问它,我认为这是因为它在控制器执行之外执行......
可以参考吗?
不,因为消息处理程序在 rawHttpRequestMessage
或 raw上运行HttpResponseMessage
(在延续的情况下)。所以实际上,没有“当前控制器执行”的概念,DelegatingHandlers
因为消息处理程序将在将请求分派给控制器之前或(再次,在继续的情况下)在控制器返回响应之后被调用。
但是,这实际上取决于您要做什么。
如果您想知道请求最终将路由到哪个控制器,您可以手动调用将在内部选择控制器的机制。
public class MyHandler : DelegatingHandler
{
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
var config = GlobalConfiguration.Configuration;
var controllerSelector = new DefaultHttpControllerSelector(config);
// descriptor here will contain information about the controller to which the request will be routed. If it's null (i.e. controller not found), it will throw an exception
var descriptor = controllerSelector.SelectController(request);
// continue
return base.SendAsync(request, cancellationToken);
}
}
扩展@GalacticBoy解决方案,使用起来会更好
public class MyHandler : DelegatingHandler
{
private static IHttpControllerSelector _controllerSelector = null;
protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
if (_controllerSelector == null)
{
var config = request.GetConfiguration();
_controllerSelector = config.Services.GetService(typeof(IHttpControllerSelector)) as IHttpControllerSelector;
}
try
{
// descriptor here will contain information about the controller to which the request will be routed. If it's null (i.e. controller not found), it will throw an exception
var descriptor = _controllerSelector.SelectController(request);
}
catch
{
// controller not found
}
// continue
return base.SendAsync(request, cancellationToken);
}
}
根据您对信息的处理方式,在执行请求后获取信息可能会很好。例如记录执行的控制器/动作。
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
namespace Example
{
public class SampleHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken)
.ContinueWith(task =>
{
HttpResponseMessage response = task.Result;
string actionName = request.GetActionDescriptor().ActionName;
string controllerName = request.GetActionDescriptor().ControllerDescriptor.ControllerName;
// log action/controller or do something else
return response;
}, cancellationToken);
}
}
}