38

I use a custom AuthorizationFilter like the followings:

public class ActionAuthorizeAttribute : AuthorizeAttribute {

protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext) {

        if(!httpContext.User.Identity.IsAuthenticated)
            return false;

        if(IsUserExcluded())
            return false;
        else
            return IsRoleAuthorize(httpContext);
    }
}

I use this filter at the top of each action I have, and for check Is Authorized, need Action Name, Controller Name, And Area Name. So is there any way to get this names in AuthorizeCore() method like use System.Web.HttpContextBase? if answer is No then how can I get this names and pass it to attribute, obviously I don't want to add each name by hand, actually something likeViewContext.RouteData.Values["Controller"] in controllers:

[ActionAuthorize(actionName=Action, controller=ControllerName, area=AreaName)]
public ActionResult Index() {
    return View();
}

Does any one have any idea about it?

Saeid
  • 13,224
  • 32
  • 107
  • 173

5 Answers5

91

You could fetch them from the RouteData:

protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
{
    var rd = httpContext.Request.RequestContext.RouteData;
    string currentAction = rd.GetRequiredString("action");
    string currentController = rd.GetRequiredString("controller");
    string currentArea = rd.Values["area"] as string;

    ...

}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 1
    "You could fetch them from the RouteData" Isn't a good answer. **Now** it was edited, I'll revert. – gdoron Apr 02 '12 at 12:52
  • 11
    This could be just in ASP.NET MVC 4, but the area is found in rd.DataTokens["area"]. – Peter Hedberg Feb 11 '13 at 08:56
  • You should change the line var rd = httpContext.Request.RequestContext.RouteData; to var rd = HttpContext.Current.Request.RequestContext.RouteData; better to use the standard one than a parameter :) – Anders M. Mar 13 '14 at 14:40
  • 6
    @AndersM., I would rather not do that. That would render my code extremely unit-test unfriendly. I always prefer working with abstractions. Can't remember when I last used `HttpContext.Current` in my career. – Darin Dimitrov Mar 17 '14 at 08:14
  • The area name will not be contained in the Values RouteValueDictionary. Rather, it will be contained in the DataTokens property, so to get the area you would want rd.DataTokens["area"] as string – MissingLinq Jun 04 '14 at 19:16
1

Face the same issue just a moment ago and my solution is:

  1. Define 2 attributes in your ActionAuthorizeAttribute class e.g.

    public string ControllerName {get;set;}
    public string ActionName {get;set;}
    
  2. While annotating your action of the controller specify them e.g.

    [ActionAuthorize(Roles="Admin", ContollerName="ControllerName",ActionName="ActionName")]**
    public ActionResult Disable(int id)
    {
     ...
    }
    
Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101
0

Getting the area will not work if you are on a custom filter the next will work to get an area

filterContext.RouteData.DataTokens["area"]
0
> namespace dene.kontroller {
>     public class daAttribute: AuthorizeAttribute
>     {
>         private Entities db = new Entities();
>         private readonly string[] allowedroles;
>         public daAttribute(params string[] roles)
>         {
>             this.allowedroles = roles;
>         }
> 
> 
>         protected override bool AuthorizeCore(HttpContextBase httpContext)
>         {
>             bool authorize = false;
>             foreach (var role in allowedroles)
>             {
>                 if (role == HttpContext.Current.User.Identity.Name)
>                 {
>                      
>                     if (role!= null)
>                     {
>                         authorize = true;
>                     }
>                 }
>                 
> 
>             }
>             return authorize;
>         }
> 
> 
>         protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
>         {
> 
>             FormsAuthentication.SignOut();
>             filterContext.Result = new HttpUnauthorizedResult();
>         }
> 
>     } }
change
  • 1
  • 1
0

If getting the area did not work, you can fetch are from the RouteData in this way:

 string currentArea = string.Empty;
 if (rd.DataTokens.TryGetValue("area", out object area))
 {
     currentArea = area.ToString();
 }
Mehran Mazhar
  • 63
  • 3
  • 13