8

I'm following a ninject filter attribute setup on this page.

For them, they have:

.WithConstructorArgumentFromControllerAttribute<LogAttribute>(
      "logLevel", attribute => attribute.LogLevel);

The second parameter is expecting a Func<LogAttribute, object> callback. Their actual param list is setup as follows:

Log(LogLevel = Level.Debug)

But my filter attribute is setup as follows:

public class AuthAttribute : FilterAttribute { }

public class AuthFilter : IAuthorizationFilter
{

    private readonly IUserService userService;
    private string[] roles;

    //Stuck on the constructor also. How do I accept params?
    public AuthFilter(IUserService userService, params string[] roles)
    {
        this.userService = userService;
        this.roles = roles;
    }
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        throw new NotImplementedException();
    }
}

Somehow this is wrong. Because I want my filter to look like:

[Auth("Admin", "Contrib")]

My bindings:

 kernel.BindFilter<AuthFilter>(FilterScope.Controller, 0)
            .WhenControllerHas<AuthAttribute>()
            .WithConstructorArgumentFromControllerAttribute<AuthAttribute>("roles", /*Stuck here*/)
Shawn Mclean
  • 56,733
  • 95
  • 279
  • 406

1 Answers1

18

You need to make roles into a property in your attribute.

Attribute:

public class AuthAttribute : FilterAttribute 
{ 
  public string[] Roles { get; set; }

  public AuthAttribute(params string[] roles)
  {
      this.Roles = roles;
  }
}

Filter:

public class AuthFilter : IAuthorizationFilter
{

  private readonly IUserService userService;
  private readonly string[] roles;

  public AuthFilter(IUserService userService, string[] roles)
  {
    this.userService = userService;
    this.roles = roles;
  }

  public void OnAuthorization(AuthorizationContext filterContext)
  {
    //do stuff
  }
}

Controller

   [AuthAttribute("a", "b")]
   public class YourController : Controller 
   {

   }

Binding:

kernel.BindFilter<AuthFilter>(FilterScope.Controller, 0)
            .WhenControllerHas<AuthAttribute>()
            .WithConstructorArgumentFromControllerAttribute<AuthAttribute>("roles", attribute => attribute.Roles);
B Z
  • 9,363
  • 16
  • 67
  • 91
  • So I remove this from the constructor? – Shawn Mclean Jun 01 '11 at 18:04
  • And how do I access it in the `OnAuthorization` method? – Shawn Mclean Jun 01 '11 at 18:05
  • Thanks this works. How do I setup the binding for both controller and action? When I have another binding for actions, it says multiple bindings found. – Shawn Mclean Jun 01 '11 at 18:27
  • @Lol coder...hmm, not sure what the issue could be, the ninject documentation has good examples on how to setup both. Maybe try posting a different question, someone may be able to help more. – B Z Jun 01 '11 at 18:56
  • 1
    See http://groups.google.com/group/ninject/browse_thread/thread/2547e261a7201333 and https://github.com/ninject/ninject.web.mvc/commit/686b1ad3c169b06ef053a1219629625759343880 – Remo Gloor Jun 01 '11 at 21:35
  • @Remo Gloor, So I need to download the nightly build? – Shawn Mclean Jun 02 '11 at 21:24
  • Yes. And you have to use Ninject.Web.Common. See the sample app of MVC about how to setup. – Remo Gloor Jun 03 '11 at 00:34
  • [+1] I was having the same problem, and had a mirror question up: http://stackoverflow.com/questions/8305476/ninject-binding-attribute-to-filter-with-constructor-arguments/8306795#8306795 - solved it the same way with Remo's pointer to documentation and a little trial/error with the Func<> signature callback. Thanks BZ and Remo. – one.beat.consumer Nov 30 '11 at 18:54
  • Remo - i'm a bit nervous to use the nightly builds in a production application. you have any guess/rumor when the next stable version will be available to allow dual constructor and action binding? I pulled the package off NuGet and looks like it is 2.2 – one.beat.consumer Nov 30 '11 at 18:56
  • Is there a way to do this by inheriting from the `AuthorizeAttribute` rather than from the `FilterAttribute` because it seems to me like I would need to duplicate the majority of the `AuthorizeAttribute` from here: https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/AuthorizeAttribute.cs considering that I just need a way to access the `Roles` property of the Attribute, in the Filter .. while injecting a user service into the Filter too – Pricey Feb 25 '14 at 20:13