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


5 comments
Comments feed for this article
July 17, 2010 at 10:00 am
MVC IsAuthorized and AuthorizedActionLink « Chris Cavanagh’s Blog
[...] Contact ← MVC IsAuthorized and AuthorizedActionLink revisited [...]
July 18, 2010 at 8:09 am
MVC IsAuthorized and AuthorizedActionLink « Chris Cavanagh’s Blog
[...] June 11, 2009 · 9 Comments UPDATE 2: Improved IsAuthenticated helper method can be found here. [...]
July 19, 2010 at 8:28 am
alex
great code.. thank you!
May 23, 2012 at 8:51 am
MVC Strongly-Typed Action Helpers « Chris Cavanagh's Blog
[...] if user is authorized for an action (automatically hide or disable [...]
May 23, 2012 at 8:51 am
MVC Strongly-Typed Action Helpers « Chris Cavanagh's Blog
[...] if user is authorized for an action (automatically hide or disable [...]