10

Hola, he podido usar la inyección de propiedades en mi FilterAttribute, pero me pregunto si es posible moverlo al constructor.ASP.NET MVC3 + ActionFilterAttribute + Injection?

Mi código actual:

// AuthAttribute.cs 

public class AuthAttribute : ActionFilterAttribute 
{ 
    public Roles _authRoles { get; private set; } 

    [Inject] 
    private readonly IAuthorizationService _service; 

    public AuthAttribute(Roles roles) 
    { 
     _authRoles = roles; 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (!filterContext.HttpContext.User.Identity.IsAuthenticated) 
     { 
      string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath; 
      string redirectUrl = string.Format("?returnUrl={0}", redirectOnSuccess); 
      string loginUrl = FormsAuthentication.LoginUrl + redirectUrl; 

      filterContext.HttpContext.Response.Redirect(loginUrl, true); 
     } 
     else 
     { 
      bool isAuthorized = _service.Authorize(GetUserSession.Id, _authRoles.ToString()); 

      if (!isAuthorized) 
      { 
       // TODO: Make custom "Not Authorized" error page. 
       throw new UnauthorizedAccessException("No access"); 
      } 
     } 
    } 
} 

 

// TestController.cs 

[Auth(Roles.Developer)] 
public ActionResult Index() 
{ 
    // Some smart logic 
} 

Gracias de antemano!

Respuesta

8

No, esto no es posible ya que los parámetros para los constructores must be simple types.

Para propósitos de prueba, usted podría tener otro constructor (ya que no se debe utilizar un contenedor IoC con las pruebas):

public class AuthAttribute : ActionFilterAttribute 
{ 
    public Roles _authRoles { get; private set; } 

    [Inject] 
    private readonly IAuthorizationService _service; 

    public AuthAttribute(Roles roles) 
    { 
     _authRoles = roles; 
    } 

    public AuthAttribute(Roles roles, IAuthorizationService authSvc) 
     : this(roles) 
    { 
     this.service = authSvc; 
    } 

    // ... 
} 
+0

TheCloudlessSky es correcto cuando usa solo un atributo. Los filtros pueden usar inyección de constructor, pero luego debe vincular un atributo a un filtro ... He ofrecido una respuesta a continuación; Gracias a Remo Gloor, B Z y otros por ayudar. –

7

inyección de constructor es posible en este escenario, pero hay que usar un combo de atributo/filtro.

su filtro (por ejemplo:. IAuthorizationFilter) aplicación utilizará Constructor de inyección y hacer todo el trabajo ...

Su atributo (por ejemplo:. FilterAttribute) será delgada, utiliza principalmente para decorar sus controladores o acciones.

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

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

    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     // do work, or HandleUnauthorizedRequest() 
    } 

    protected void HandleUnauthorizedRequest(AuthorizationContext filterContext) 
    { 
     // do work 
    } 

} 

public class RequireRolesAttribute : FilterAttribute 
{ 
    public readonly UserRoles RequiredRoles; 

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

Entonces su contenedor Ninject une el atributo al Filtro:

// controller-level 
kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller, 0).WhenControllerHas<RequireRolesAttribute>() 
// action level 
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0).WhenActionMethodHas<RequireRolesAttribute>(); 

Ver:

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

Ninject Binding Attribute to Filter with Constructor Arguments

https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations

El truco que estoy tratando de superar es cómo definir mis Roles en el atributo para el Filtro ... la documentación del ninject debería ayudar, pero todavía no estoy allí.

Buena suerte.