Asp.net 访问在DelegatingHandler中执行的当前控制器

Asp.net 访问在DelegatingHandler中执行的当前控制器,asp.net,asp.net-web-api,Asp.net,Asp.net Web Api,我想知道是否可以在DelegatingHandler的SendAsync方法中访问正在执行(或即将执行)的控制器?我似乎不知道如何访问它,我想这是因为它在控制器执行之外执行 是否可以引用它?否,因为消息处理程序对原始HttpRequestMessage或原始HttpResponseMessage进行操作(在继续的情况下)。因此,实际上没有使用delegatinghandler执行“当前控制器”的概念,因为消息处理程序将在将请求分派给控制器之前调用,或者(在继续的情况下)在控制器返回响应之后调用

我想知道是否可以在DelegatingHandler的SendAsync方法中访问正在执行(或即将执行)的控制器?我似乎不知道如何访问它,我想这是因为它在控制器执行之外执行


是否可以引用它?

否,因为消息处理程序对原始
HttpRequestMessage
或原始
HttpResponseMessage
进行操作(在继续的情况下)。因此,实际上没有使用
delegatinghandler
执行“当前控制器”的概念,因为消息处理程序将在将请求分派给控制器之前调用,或者(在继续的情况下)在控制器返回响应之后调用

然而,这实际上取决于你想做什么

如果您想知道请求最终将路由到哪个控制器,可以手动调用内部选择控制器的机制

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);
    }
}
公共类MyHandler:DelegatingHandler
{
受保护的重写System.Threading.Tasks.Task SendAsync(HttpRequestMessage请求,System.Threading.CancellationToken CancellationToken)
{
var config=GlobalConfiguration.Configuration;
var controllerSelector=新的默认HttpControllerSelector(配置);
//此处的描述符将包含有关请求将路由到的控制器的信息。如果为null(即未找到控制器),则会引发异常
变量描述符=控制器选择器。选择控制器(请求);
//继续
返回base.sendaync(请求、取消令牌);
}
}

扩展@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);
    }
}
公共类MyHandler:DelegatingHandler
{
专用静态IHttpControllerSelector _controllerSelector=null;
受保护的重写System.Threading.Tasks.Task SendAsync(HttpRequestMessage请求,System.Threading.CancellationToken CancellationToken)
{
if(_controllerSelector==null)
{
var config=request.GetConfiguration();
_controllerSelector=config.Services.GetService(typeof(IHttpControllerSelector))作为IHttpControllerSelector;
}
尝试
{
//此处的描述符将包含有关请求将路由到的控制器的信息。如果为null(即未找到控制器),则会引发异常
变量描述符=_controllerSelector.SelectController(请求);
}
抓住
{
//找不到控制器
}
//继续
返回base.sendaync(请求、取消令牌);
}
}

根据您对信息的处理方式,您可以在请求执行后获取信息。例如,记录执行的控制器/操作

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);
        }
    }
}
使用系统;
使用System.Net.Http;
使用系统线程;
使用System.Threading.Tasks;
使用System.Web;
名称空间示例
{
公共类SampleHandler:DelegatingHandler
{
受保护的覆盖任务SendAsync(HttpRequestMessage请求,CancellationToken CancellationToken)
{
return base.sendaync(请求、取消令牌)
.ContinueWith(任务=>
{
HttpResponseMessage response=task.Result;
string actionName=request.GetActionDescriptor().actionName;
字符串controllerName=request.GetActionDescriptor().ControllerDescriptor.controllerName;
//记录操作/控制器或执行其他操作
返回响应;
},取消令牌);
}
}
}

谢谢,我有一个验证例程,如果能够检查控制器类型,看看它是否定义了自定义属性,那就太好了,这样我就可以避免这个验证例程。这应该使这成为可能。太好了。是的,一旦你抓住了一个HttpControllerDescriptor@FilipW有没有一种“好”的方法可以做到这一点而不引发异常?在源代码中,对
SelectController
的调用最终调用了
this.\u controllerInfoCache.Value.TryGetValue(controllerName,out controllerDescriptor)
但是
\u controllerInfoCache
在Web API 2中不能以任何方式公开访问,最好使用
请求.GetConfiguration()
扩展方法,而不是
全局配置。配置
参考。如何在此处获取操作名称