How to retrieve attributes of requested Action Method

asp.net-mvc-3, c#, html-helper, reflection

Solution

EDIT: Updated the method to include insights from this page. This final version peeks the `AuthorizationFilters` for the requested action method and checks whether the user is authorized to perform the action.

So I dug around in `System.Web.Mvc.ControllerActionInvoker` and found the methods and constructors I needed. `ControllerDescriptor.FindAction()` ended up being the key. Below, I've copied the method I wrote that will retrieve all the attributes:

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();
        
        var controller = (ControllerBase)factory.CreateController(
            htmlHelper.ViewContext.RequestContext, controllerName);
            
        controllerContext = new ControllerContext(
            htmlHelper.ViewContext.RequestContext, controller);
    }
    
    var controllerType = controllerContext.Controller.GetType();
    var controllerDescriptor = new ReflectedControllerDescriptor(controllerType);
    var actionDescriptor = controllerDescriptor.FindAction(
        controllerContext, actionName);
    
    if (actionDescriptor == null)
    {
        return false;
    }
    
    var filters = new FilterInfo(
        FilterProviders.Providers.GetFilters(controllerContext, actionDescriptor)
    );
    
    var authContext = new AuthorizationContext(controllerContext, actionDescriptor);
    foreach (IAuthorizationFilter authFilter in filters.AuthorizationFilters)
    {
        authFilter.OnAuthorization(authContext);
        if (authContext.Result != null)
        {
            return false;
        }
    }
    
    return true;
}

Problem

I'm trying to peek at any authentication attributes which may be decorating action methods in my controllers in an MVC 3 application. I'm doing this in my own HtmlHelper extension methods which are basically wrappers to ActionLink (to give you the context of what information I have available at runtime). I have a basic solution in place, but overloaded methods have just made it explode. I know that the framework is internally resolving urls to action methods, but after looking through the code for System.Web.Mvc.LinkExtensions, I still haven't found precisely how that is happening, so I'm a bit stuck as to how to tackle this issue. Here's the code I have so far for resolving the relevant method: ``` 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 } ``` So my current problem is that when a method is overridden, I get "ambiguous match found" exceptions. I'm guessing I need to process the RouteValues to resolve any parameters to the method so I can unambiguously identify the right one. Does anyone have some pointers on how to do this? Alternately, does the framework already provide a means of resolving the exact method needed? Thanks so much!

Original source