访问DelegatingHandler中的ApiController类型

我正在使用Asp.Net WebAPI进行项目。 我目前正在进行身份validation和授权。

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

例如:

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

在身份validation消息处理程序中,我希望能够查看属性并根据所需内容从数据库中恢复声明。 为此,我需要知道我将根据路线命中的控制器和动作:

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

所以我可以做到。 但是现在我需要把它变成一个我可以反思的Type,但我所拥有的只是控制器名称(甚至不是完整的类名或命名空间)。 我怎样才能把它变成我可以反思的东西以获得属性等?

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

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

 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)); 

您可能希望对结果进行一些缓存(如控制器选择器那样)。 但这种方法应该有效。

您可能最好将此逻辑移动到位于控制器而不是委托处理程序的自定义授权filter中。 鉴于您需要知道控制器类型,您也可以让ControllerSelector正常工作。 也许,如果您将负载声明属性转换为授权操作filter属性,您只需加载作为参数传入的声明并在那里设置主体和声明?

如果你仍然在DelegatingHandler上设置,你可以获得Controller Selector实例本身,这将更有效:

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