ASP.NET MVC3 + ActionFilterAttribute + Injection?

Hey there, I’ve succesfull been able to use property injection in my FilterAttribute, however I’m wondering whether its possible to move it into the constructor instead?

My current code:

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

Thanks in advance!

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

No, this isn’t possible as the parameters for the constructors must be simple types.

For testing purposes, you could have another constructor (since you shouldn’t be using an IoC container with testing):

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

    // ...
}

Method 2

Constructor injection is possible in this scenario, but you need to use an Attribute/Filter combo.

Your Filter (ex. : IAuthorizationFilter) implementation will use Constructor Injection and do all the work…

Your Attribute (ex. : FilterAttribute) will be thin, mainly used to decorate your controllers or actions.

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

Then your Ninject container binds the Attribute to the Filter:
// controller-level
kernel.BindFilter<AuthorizationFilter>(FilterScope.Controller, 0).WhenControllerHas<RequireRolesAttribute>()
// action level
kernel.BindFilter<AuthorizationFilter>(FilterScope.Action, 0).WhenActionMethodHas<RequireRolesAttribute>();

See:

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

The trick I’m looking to overcome is how get my Roles defined on the attribute to the Filter… the ninject documentation should help but I’m not there yet myself.

Good luck.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x