14

He leído tantas respuestas como pude para esto, pero parecen no dar ningún detalle.Atributo de enlace de ninject para filtrar con argumentos de constructor

El problema es que al vincular un filtro de acción (con un servicio inyectado por el controlador) a un atributo correspondiente, no he podido averiguar cómo pasar los valores de parámetro/propiedad del atributo a su filtro vinculado. A continuación se muestra el código, y por debajo que mi intención falso-código:

Filtro & Atributo

public class AuthorizationFilter : IAuthorizationFilter 
{ 
    private readonly IAuthorizationService _authorizationService; 
    private readonly UserRoles _requiredRoles; // Enum 

    public AuthorizationFilter(IAuthorizationService authorizationService, UserRoles requiredRoles) 
    { 
     _authorizationService = authorizationService; 
     _requiredRoles = requiredRoles; 
    } 

    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext.HttpContext.Session == null) 
      HandleUnauthorizedRequest(filterContext); 
     else { 
      var authorized = _authorizationService.IsUserInRole((UserSessionInfoViewModel) filterContext.HttpContext.Session["user"], _requiredRoles); 
      if (!authorized) 
       HandleUnauthorizedRequest(filterContext); 
      // else TODO: deal with cache... 
     } 
    } 
} 

public class RequireRolesAttribute : FilterAttribute 
{ 
    public readonly UserRoles RequiredRoles; 

    public RequireRolesAttribute(UserRoles requiredRoles) 
    { 
     RequiredRoles = requiredRoles; 
    }   
} 

Filtro/Atributo enlaces

kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller, 0) 
     .WhenControllerHas<RequireRolesAttribute>(); 
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0) 
     .WhenActionMethodHas<RequireRolesAttribute>(); 

Esto debe asegurarse de que cualquier controlador/la acción decorada con [RolesRequired] está ligada al filtro. Hasta aquí todo bien. Ahora quiero declarar a través del atributo los roles (al igual que el stock AuthorizeAttribute) y pasar esos valores al filtro que realmente hace la autorización.

Destinado/Código falso:

[RequireRoles(UserRoles.Author)] 
public ActionResult Index() 
{ 
    // blah 
} 

Específicamente,

¿Qué se necesita para informar al AuthorizationFilter de los papeles? ¿Puede el filtro/ninject acceder a los argumentos pasados ​​al constructor del atributo? ¿Puede el filtro/ninject sacarlos de la propiedad pública de atributos?

Como referencia, estos artículos eran una gran ayuda, pero no responden a una sola cosa:

Dependency Injection with Ninject and Filter attribute for asp.net mvc

Custom Authorization MVC 3 and Ninject IoC

BZ, Remo Gloor, otros ... ¿Cómo puedo lograr ¿esta?

Respuesta

19

Lo he descubierto (gracias a las instrucciones y documentación de Remo).

Utilice la extensión .WithConstructorArgument adecuada, ya sea que esté vinculando a un controlador o filtro de acción. Para la unión de mi filtro de acción de ejemplo se parece a esto:

kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0) 
     .WhenActionMethodHas<RequireRolesAttribute>() 
     .WithConstructorArgumentFromActionAttribute<RequireRolesAttribute>("requiredRoles", o => o.RequiredRoles); 

Una vez que entendí el Func <> firma, todo quedó claro.La mejor manera que he encontrado para manejar esto era

  1. hacen específica del tipo de la extensión para mi atributo

    .WithConstructorArgumentFromActionAttribute<TAttribute>() 
    
  2. buscar el valor del objeto de devolución de llamada (el atributo) a través de lambda:

    ("argumentName", o => o.PropertyName) 
    
+1

sólo el billete, aplausos – redsquare

+0

alguna idea de lo que hay que hacer si la clase derivada de 'FilterAttribute' tiene constructor con múltiples parámetros (es decir RequireRoles clase en el ejemplo anterior que tiene constructor con múltiples parametes), entonces ¿cómo puede los parámetros se asignan en '.WithConstructorArgumentFromActionAttribute ()' ?? – Vipresh

+1

Para que el método 'BindFilter <>()' esté disponible, puede agregar una referencia a 'Ninject.Web.Mvc.FilterBindingSyntax'. – bump

8

y para llevar el método BindFilter de extensión en el alcance no se olvide de agregar;

using Ninject.Web.Mvc.FilterBindingSyntax; 
+15

Esto no es una respuesta, debe publicarse como un comentario a la respuesta de la solución. – angularsen

+0

Si bien este enlace puede responder a la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace de referencia. Las respuestas de solo enlace pueden dejar de ser válidas si la página vinculada cambia. - [De la opinión] (/ reseña/mensajes de baja calidad/18739473) – diceler

Cuestiones relacionadas