ASP.NET MVC3 + ActionFilterAttribute + Injection?

10

嗨,我已经成功地在我的FilterAttribute中使用了属性注入,但是我想知道是否可以将它移动到构造函数中?

我的当前代码:

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

提前致谢!

2个回答

8

不,这是不可能的,因为构造函数的参数 必须是简单类型

为了测试目的,您可以拥有另一个构造函数(因为您不应该在测试中使用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;
    }

    // ...
}

当您仅使用属性时,TheCloudlessSky是正确的。过滤器可以使用构造函数注入,但是您需要将属性绑定到过滤器...我在下面提供了一个答案;感谢Remo Gloor、B Z和其他人的帮助。 - one.beat.consumer

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容器将Attribute绑定到Filter:
// controller-level
kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller, 0).WhenControllerHas<RequireRolesAttribute>()
// action level
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0).WhenActionMethodHas<RequireRolesAttribute>();

参见:

使用Ninject和Filter属性进行ASP.NET MVC的依赖注入

使用构造函数参数将属性绑定到过滤器(Filter)

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

我想要克服的难点是如何将我的角色定义传递给过滤器...Ninject文档应该有所帮助,但我自己还没有到那里。

祝你好运。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接