2012-04-30 18 views
7

Estoy tratando de ver los atributos de autenticación que pueden estar decorando los métodos de acción en mis controladores en una aplicación MVC 3. Estoy haciendo esto en mis propios métodos de extensión HtmlHelper que son básicamente envoltorios para ActionLink (para darle el contexto de la información que tengo disponible en tiempo de ejecución). Tengo una solución básica en su lugar, pero los métodos sobrecargados la han hecho explotar. Sé que el marco interno está resolviendo urls a métodos de acción, pero después de mirar el código de System.Web.Mvc.LinkExtensions, todavía no he encontrado exactamente cómo está sucediendo eso, así que estoy un poco atascado en cuanto a cómo para enfrentar este problemaCómo recuperar los atributos del método de acción solicitado

Aquí está el código que tengo hasta ahora para resolver el método correspondiente:

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 
} 

Así que mi problema actual es que cuando se anula un método, consigo "concordancia ambigua encontrado" excepciones. Supongo que necesito procesar los RouteValues ​​para resolver los parámetros del método, de modo que pueda identificar inequívocamente el correcto. ¿Alguien tiene algunos consejos sobre cómo hacer esto? Alternativamente, ¿el marco ya proporciona un medio para resolver el método exacto que se necesita?

Gracias tanto!

+0

OK, así que me he mantenido la excavación en el código fuente MVC3 y parece que necesito para obtener una instancia ControllerDescriptor y el uso eso para obtener un ActionDescriptor para el método de acción apropiado. Entonces, si ese es el caso, ¿cómo obtengo el ControllerContext del controlador apropiado cuando el método de acción solicitado no es el controlador en HtmlHelper.ViewContext.Controller? –

+0

Obtener un ControllerContext resulta ser bastante sencillo. Obteniendo un ControllerDescriptor, no tanto. ¿Alguna idea? –

+0

Se encontró el código [aquí] (http://weblogs.asp.net/jeffreyzhao/archive/2009/01/30/extend-asp-net-mvc-for-asynchronous-action.aspx) para obtener ControllerDescriptor y ActionDescriptor. Cada vez más cerca ... –

Respuesta

2

EDITAR: Se actualizó el método para incluir estadísticas del this page. Esta versión final muestra los AuthorizationFilters para el método de acción solicitado y verifica si el usuario está autorizado para realizar la acción.

Así que busqué en System.Web.Mvc.ControllerActionInvoker y encontré los métodos y constructores que necesitaba. ControllerDescriptor.FindAction() terminó siendo la clave. A continuación, he copiado el método escribí que se recuperar todos los atributos

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; 
} 
0

La forma normal de agregar el código de autorización es usando Authorization Filter.

IAuthorizationFilter.OnAuthorization proporciona un objeto AuthorizationContext que tiene una propiedad ActionDescriptor.

+0

Ya utilizamos filtros de autorización, pero a menos que me falta, el marco no le proporciona un medio para inspeccionar esa autorización antes de invocar una acción. Intento ocultar enlaces de usuarios que no tienen acceso para realizar las acciones a las que se vinculan, por lo que debo inspeccionar los atributos de autorización antes de representar html. El manejo de la Autorización de Autorización será demasiado tarde para la funcionalidad que necesito. –

Cuestiones relacionadas