Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
374 views
in Technique[技术] by (71.8m points)

asp.net mvc 3 - Ninject Binding Attribute to Filter with Constructor Arguments

I read as many answers as I could for this, but they seem to fall short of one detail.

The trouble is when binding an action filter (with a service injected by controller) to a corresponding attribute, I've been unable to figure out how to pass parameter/property values from the attribute to its bound filter. Below is the code, and below that my intended fake-code:

Filter & Attribute

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

Filter/Attribute Bindings

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

This should make sure any controller/action decorated with [RolesRequired] is bound to the filter. So far so good. Now I want to declare via the attribute the roles (much like the stock AuthorizeAttribute) and pass those values onto the filter that actually does the authorization.

Intended/Fake Code:

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

Specifically,

What does it take to inform the AuthorizationFilter of the roles? Can the filter/ninject access the arguments passed to the attribute's constructor? Can the filter/ninject pull them from the attributes public property?

For reference, these articles were a huge help, but don't answer this one thing:

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

Custom Authorization MVC 3 and Ninject IoC

B Z, Remo Gloor, others... how can I accomplish this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I have figured it out (thanks to Remo's directions and documentation).

Use the appropriate .WithConstructorArgument extension whether you are binding to a Controller or Action filter. For example binding my action filter looks like this:

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

Once I understood the Func<> signature, it all became clear. The best way I found to handle this was to

  1. make the extension type-specific for my attribute

    .WithConstructorArgumentFromActionAttribute<TAttribute>()
    
  2. fetch the value from the callback object (your attribute) via lambda:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...