Around a year ago I wrote this post about an MVC HTML helper that could render a link, taking the current authorization state into account (only rendering the link if the user was authorized to hit it).  It used an “IsAuthorized” extension method that was a bit of a hack, and was quickly replaced by something much cooler (that let the AuthorizeAttribute itself do the real work, but which I also forgot to re-publish)…  Here’s the improved version of IsAuthorize (for MVC 2.0):

public static class AuthorizationExtensions
{
    /// <summary>
    /// Determines whether the specified action is authorized by examining all <see cref="IAuthorizationFilter"/> attributes.
    /// </summary>
    /// <typeparam name="TController">The type of the controller.</typeparam>
    /// <param name="helper">The helper.</param>
    /// <param name="action">The action method to be called.</param>
    /// <returns>
    ///     <c>true</c> if the specified helper is authorized; otherwise, <c>false</c>.
    /// </returns>
    public static bool IsAuthorized<TController>( this HtmlHelper helper, Expression<Action<TController>> action )
    {
        var call = action.Body as MethodCallExpression;

        if ( call == null ) return false;

        var authorizeAttributes = call.GetAttributes<IAuthorizationFilter>();
        if ( authorizeAttributes.Length == 0 ) return true;

        var controllerContext = helper.ViewContext.Controller.ControllerContext;
        var controllerDescriptor = new ReflectedControllerDescriptor( typeof( TController ) );
        var actionDescriptor = new ReflectedActionDescriptor( call.Method, call.Method.Name, controllerDescriptor );

        return authorizeAttributes.All( a => IsAuthorized( a, controllerContext, actionDescriptor ) );
    }

    /// <summary>
    /// Determines whether the specified authorization filter is authorized.
    /// </summary>
    /// <param name="authorizationFilter">The authorization filter.</param>
    /// <param name="controllerContext">The controller context.</param>
    /// <param name="actionDescriptor">The action descriptor.</param>
    /// <returns>
    ///     <c>true</c> if the specified authorization filter is authorized; otherwise, <c>false</c>.
    /// </returns>
    private static bool IsAuthorized( IAuthorizationFilter authorizationFilter, ControllerContext controllerContext, ActionDescriptor actionDescriptor )
    {
        var authorizationContext = new AuthorizationContext( controllerContext, actionDescriptor );

        authorizationFilter.OnAuthorization( authorizationContext );

        return ( authorizationContext.Result == null );
    }
}

It uses a convenient extension method to pull the attributes from the MethodCallExpression.  Here it is, with a bunch of related helpers:

public static class FilterExtensions
{
    /// <summary>
    /// Returns specified attributes for an action descriptor.
    /// </summary>
    /// <param name="call">The call.</param>
    /// <returns>Returns specified attributes for an action method along with the action's controller.</returns>
    public static TAttribute[] GetAttributes<TAttribute>( this ControllerDescriptor controller )
    {
        return controller.GetCustomAttributes( typeof( TAttribute ), true )
            .Cast<TAttribute>()
            .ToArray();
    }

    /// <summary>
    /// Returns specified attributes for an action descriptor.
    /// </summary>
    /// <param name="call">The call.</param>
    /// <returns>Returns specified attributes for an action method along with the action's controller.</returns>
    public static TAttribute[] GetAttributes<TAttribute>( this ActionDescriptor action )
    {
        return action.GetCustomAttributes( typeof( TAttribute ), true )
            .Cast<TAttribute>()
            .ToArray();
    }

    /// <summary>
    /// Returns specified attributes for an action method along with the action's controller.
    /// </summary>
    /// <param name="call">The call.</param>
    /// <returns>Returns specified attributes for an action method along with the action's controller.</returns>
    public static TAttribute[] GetAttributes<TAttribute>( this MethodCallExpression call )
    {
        return call.Object.Type.GetCustomAttributes( typeof( TAttribute ), true )
            .Union( call.Method.GetCustomAttributes( typeof( TAttribute ), true ) )
            .Cast<TAttribute>()
            .ToArray();
    }
}

DotNetKicks Image
About these ads