Have you ever tried to use an [Authorize] attribute and assign roles for example with an Enum value in one of your ASP.NET MVC projects?
If so, you will get the following error message when compiling:
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
It is because you need to use static values and it makes impossible to use an Enum to set properties of an Attribute. It means that you can not set the property Roles of an [AuthorizeAttribute] with an Enum value.
That is frustrating, because I personally don't like having to hard code roles in an application. It makes the application dirty and more complicated to maintain.
Hopefully, ASP.NET MVC allows us to customize the [AuthorizeAttribute] easily without having to override the standard security process.
Creation
For our needs we will create the following Enum to declare roles:
namespace MvcApplication.HowTo.Enums { public enum Role { Administrator = 1, UserWithPrivileges = 2, User = 3, } }
Now we are going to create a custom [AuthorizeAttribute] that accepts Enum as parameters in the constructor. It will inherit from the standard System.Web.Mvc.AuthorizeAttribute:
using System; using System.Linq; using System.Web.Mvc; namespace MvcApplication.HowTo.Attributes { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] public class AuthorizeEnumAttribute : AuthorizeAttribute { public AuthorizeEnumAttribute(params object[] roles) { if (roles.Any(r => r.GetType().BaseType != typeof(Enum))) throw new ArgumentException("roles"); this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r))); } } }
As you can see we have to pay attention to several things here:
Example of use
Let's say we want to authorize only users with roles Administrator or UserWithPrivileges on the HomeController action named ThePrivilegeZone. ThePrivilegeZone action will be decorated with our custom authorize attribute like bellow:
using System.Web.Mvc; using MvcApplication.HowTo.Attributes; using MvcApplication.HowTo.Enums; namespace MvcApplication.HowTo.Controllers { public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Welcome to ASP.NET MVC!"; return View(); } public ActionResult About() { return View(); } [AuthorizeEnum(Role.Administrator, Role.UserWithPrivileges)] public ActionResult ThePrivilegeZone() { return View(); } } }
Our code is clean like that, isn't it?
To go further
If you take a look with a tool like Reflector, it is interesting to understand how the action ThePrivilegeZone is decorated when compiled. Here is a screenshot:
We understand that once compiled, Role Enum values are used and not names. Here 1 (Administrator) and 2 (UserWithPrivileges).
Note that if you use an Enum for your roles without setting values like we did here, Enum values will be 0, 1, 2, etc. to the number of your roles less 1.
Summary
We have seen how to create and use a custom AuthorizeAttribute that accepts parameters of type enum. Here we are only setting roles, but depending on your needs, you can do the same with users. I personally use this custom attribute in my framework so that I am able to reuse it in all my ASP.NET MVC projects.
You can download the example solution here:
Download the Authorize Enum Solution
(Note that the project uses ASP.NET MVC 3)
Please feel free to comment or contact me if you have any question about this article.
Thats Great!
Is it possible to use a [Flags] Enum ?
This is exactly where I was looking for, thanks a lot!
hi
thank you for this article
how to save roles in database,and dynamic parameter Authorize?
thanks
Good Information.
Also exactly what I was looking for too! Thanks!
this is the ONLY place on the entire web that talks about passing parms.
Can you please expand this to show the MVC web page - so that we can dynamically assign the roles http://bit.ly/2iyt146