如何检索所请求的Action Method的属性

时间:2012-04-30 20:23:57

标签: c# asp.net-mvc-3 reflection html-helper

我正在试图查看任何可能在MVC 3应用程序中的控制器中修饰操作方法的身份验证属性。我在我自己的HtmlHelper扩展方法中执行此操作,这些方法基本上是ActionLink的包装器(为您提供我在运行时可用的信息的上下文)。我有一个基本的解决方案,但重载方法刚刚爆炸。我知道框架在内部解析了动作方法的URL,但在查看了System.Web.Mvc.LinkExtensions的代码之后,我仍然没有准确地发现它是如何发生的,所以我有点陷入困境解决这个问题。

以下是我目前解决相关方法的代码:

private static bool _IsUserAuthorized(HtmlHelper html,
  string controllerName, string actionName)
{
  controllerName = controllerName ??
    html.ViewContext.RouteData.GetRequiredString("controller");

  var factory = ControllerBuilder.Current.GetControllerFactory();
  var controller = factory.CreateController(
    html.ViewContext.RequestContext, controllerName);

  Type controllerType = controller.GetType();
  var methodInfo = controllerType.GetMethod(actionName,
    BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

  ... check authentication
}

所以我当前的问题是,当一个方法被覆盖时,我会得到“模糊匹配”异常。我猜我需要处理RouteValues来解析方法的任何参数,这样我才能明确地识别正确的参数。有没有人对如何做到这一点有一些指示?或者,框架是否已经提供了解决所需方法的手段?

非常感谢!

2 个答案:

答案 0 :(得分:2)

编辑:更新了方法以包含来自this page的见解。最终版本查看AuthorizationFilters以获取所请求的操作方法,并检查用户是否有权执行操作。

所以我在System.Web.Mvc.ControllerActionInvoker中挖掘并找到了我需要的方法和构造函数。 ControllerDescriptor.FindAction()最终成为关键。下面,我复制了我写的方法检索所有属性

private static bool _IsUserAuthorized(HtmlHelper htmlHelper,
  string controllerName, string actionName)
{
  ControllerContext controllerContext = null;
  //if controllerName is null or empty, we'll use the 
  // current controller in HtmlHelper.ViewContext.
  if (string.IsNullOrEmpty(controllerName))
  {
    controllerContext = htmlHelper.ViewContext.Controller.ControllerContext;
  }
  else //use the controller factory to get the requested controller
  {
    var factory = ControllerBuilder.Current.GetControllerFactory();
    ControllerBase controller = (ControllerBase)factory.CreateController(
      htmlHelper.ViewContext.RequestContext, controllerName);
    controllerContext = new ControllerContext(
      htmlHelper.ViewContext.RequestContext, controller);
  }

  Type controllerType = controllerContext.Controller.GetType();
  ControllerDescriptor controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
  ActionDescriptor actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName);
  if (actionDescriptor == null)
    return false;

  FilterInfo filters = new FilterInfo(FilterProviders.Providers.GetFilters(
    controllerContext, actionDescriptor));

  AuthorizationContext authContext = new AuthorizationContext(controllerContext, actionDescriptor);
  foreach (IAuthorizationFilter authFilter in filters.AuthorizationFilters)
  {
    authFilter.OnAuthorization(authContext);
    if (authContext.Result != null)
      return false;
  }
  return true;
}

答案 1 :(得分:0)

添加授权码的常用方法是使用Authorization Filter

IAuthorizationFilter.OnAuthorization提供AuthorizationContext对象,该对象具有ActionDescriptor属性。