10

嘿,我已经succesfull能够在我的FilterAttribute中使用属性注入,但我想知道是否有可能将其移入构造函数呢?ASP.NET MVC3 + ActionFilterAttribute + Injection?

我当前的代码:

// 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 
} 

在此先感谢!

回答

8

不,这不可能作为构造函数must be simple types的参数。

出于测试目的,你可以有另一个构造函数(因为你不应该使用与测试IoC容器):

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是正确的,当你只使用一个属性。过滤器可以使用构造函数注入,但是你需要将一个属性绑定到过滤器上......我在下面提供了一个答案;感谢Remo Gloor,B Z和其他人的帮助。 –

7

构造方法注入在这种情况下可能的,但你需要使用属性/过滤器组合。

你的过滤器(例如:个IAuthorizationFilter)实现将使用构造函数注入和做所有的工作...

你的属性(例如:FilterAttribute)会瘦,主要是用来装饰你的控制器或动作。

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

然后你Ninject容器绑定属性的过滤器:

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

参见:

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

我期望克服的诀窍是如何让我的角色在过滤器的属性上定义... ninject文档应该有所帮助,但我并不是自己。

祝你好运。