Question

I'm trying to write an attribute class that can be used on all my "admin" actions which then effectively applies all relevant action/auth filters to that action. For instance, I always apply the AuthoriseAttribute and a custom AdminLayoutAttribute, so my intention is to just have an AdminAttribute which somehow implies both the above. That way I can make changes to the entire Admin section in one handy place.

However I don't see how I can do this. Can any one point me in the right direction?

Much appreciated.

Was it helpful?

Solution

You could consider moving them from the actions to a controller class or a base controller class for the Admin actions. That way you would just set both the Authorize and AdminLayout attributes in the controller class instead of each individual action method.

[Authorize]
[AdminLayout]
public AdminController: Controller
{
    //action methods
}

Having an attribute combining the authorization and some custom layout logic could be seen as a break of the Single Responsibility Principle, but if you have no other choice then you could try these approaches:

If you want to replace your existing AdminLayoutAttribute by a new AdminAttribute, you could then create the AdminAttribute so it inherits from the standard AuthorizeAttribute and also implements IActionFilter\IResultFilter as in your custom AdminLayoutAttribute.

public class AdminLayoutAttribute: AuthorizeAttribute, IActionFilter, IResultFilter
{
    //Logic as in existing AdminLayoutAttribute to be replaced
}

Otherwise if you want to keep your existing AdminLayoutAttribute and add a new AdminAttribute that combines it with the AuthorizeAttribute, you could then inherit from your custom attribute and implement IAuthorizationFilter by calling an internal instance of type AuthorizationFilter

public class AdminLayoutAttribute: AdminLayoutAttribute, IAuthorizationFilter
{
    //Implement IAuthorizationFilter by delegating to an internal AuthorizeFilter instance
    private _authorizeFilter = new AuthorizeAttribute();

    public override object TypeId 
    { 
        //override from base Attribute class as in AuthorizeAttribute class
        get { return _authorizeFilter.TypeId ; }
    }

    public string Roles 
    {
        get { return _authorizeFilter.Roles; }
        set { _authorizeFilter.Roles = value; }
    }

    public string Users 
    {
        get { return _authorizeFilter.Users; }
        set { _authorizeFilter.Users = value; }
    }

    public void OnAuthorization(AuthorizationContext filterContext) 
    {
        _authorizeFilter.OnAuthorization(filterContext);
    }

}

The key in both options is to not having the new AdminAttribute class inheriting from 2 concrete classes, as multiple inheritance is not supported by C#.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top