访问DelegatingHandler中的ApiController类型

本文关键字:类型 ApiController 中的 DelegatingHandler 访问 | 更新日期: 2023-09-27 18:00:51

我正在使用Asp。Net WebAPI。我目前正在进行身份验证和授权。

我有一个messageHandler,它将检查请求的HTTP身份验证标头,并构建我的身份和用户配置文件。然而,我想用动作可能需要的声明来注释我的控制器动作(或者只是控制器((我们有很多用户可以拥有的声明,所以我不想全部加载(。

例如:

public class MyController : ApiController
{
    [LoadClaims("SomeClaim", "SomeOtherClaim", "etc")]
    public string Get()
    {
        if (HasClaim("SomeClaim"))
            return "Awesome";
        return "Bummer";
    }
}

在身份验证消息处理程序中,我希望能够查看属性,并仅根据需要从DB中带回声明。为此,我需要知道我将根据路线打击什么控制器和行动:

 protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request, CancellationToken cancellationToken)
        {
...
            var routeData = request.GetRouteData();
            object controllerName;
            object actionName;
            routeData.Values.TryGetValue("controller", out controllerName);
...

所以我可以得到。但现在我需要将其转换为一个可以反思的类型,但我所拥有的只是控制器名称(甚至不是完整的类名或命名空间(。我如何将其转化为我可以反思的东西,以获得属性等?

我正在研究DefaultHttpControllerSelector,看看WebAPI堆栈是如何做到这一点的,它似乎使用了HttpControllerTypeCache。这是一个内部类,所以我无法创建实例。获取目标控制器类型的正确方法是什么?

访问DelegatingHandler中的ApiController类型

您可以使用全局服务定位器自己访问类型解析器。

var controllerTypeResolver = GlobalConfiguration.Configuration.Services.GetHttpControllerTypeResolver();
var controllerTypes = controllerTypeResolver.GetControllerTypes(GlobalConfiguration.Configuration.Services.GetAssembliesResolver());
var controllerType = controllerTypes.SingleOrDefault(ct => ct.Name == string.Format("{0}Controller", controllerName));

您可能想要对结果进行一些缓存(就像控制器选择器所做的那样(。但这种方法应该奏效。

但是

您最好将此逻辑移动到位于控制器上的自定义授权过滤器中,而不是委托处理程序中。如果您需要了解控制器类型,您也可以让ControllerSelector正常工作。也许,如果您将加载声明属性转换为授权操作过滤器属性,您可以加载作为参数传入的声明,然后设置主体和声明?

如果您仍然在DelegatingHandler上设置,您可以获得控制器选择器实例本身,这将更加高效:

var controllerSelector = GlobalConfiguration.Configuration.Services.GetHttpControllerSelector();
var controllerDescriptor = controllerSelector.SelectController( request );