Click here to Skip to main content
15,868,053 members
Articles / Web Development / ASP.NET

Custom RoleProvider is Not So Scary After All

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
29 Aug 2010CPOL3 min read 21.1K   5   1
Implementing a custom RoleProvider using Unity IoC library to support custom roles in ASP.NET MVC

I'm developing a little project to learn a few tools including ASP.NET MVC 2, NHibernate and Unity. The project is a simple web page to upload and search through documents of many different formats. One of the requirements I've made out for the system is having three different roles for users: “Uploader”, “Manager” and “Administrator”.

Now, ASP.NET MVC framework offers a very handy attribute called AuthorizeAttribute. Using it, you can allow some parts of the webpage to be viewable only for users in a specific role. All is well, but it uses ASP.NET role management under the hood. It requires a few additional tables in your database to be created and the actual data to be inserted to configure the roles. I was already using ASP.NET Membership to create secure logins for accounts, but it was only used to store passwords, nothing more. All the account information is stored in my own table called “Accounts”. That’s where I wanted my role to be kept too. ASP.NET Roles require you to store the roles in a specific table though. To avoid needless complexity, I chose to create my own custom RoleProvider class, so I could modify the default behaviour to suit my needs.

RoleProvider is an abstract class, whose derivatives are used to manage roles in an application. Checking if a user is in a role belongs to that class also. I've considered implementing my own RoleProvider a few times before, but I was overwhelmed by the number of methods we need to implement, so I went with the default behavior every time. That’s 11 methods and one property to implement.

Additionally, since I’m trying to use the best practices to develop this application and have been using Dependency Injection all over the place, implementing custom RoleProvider brought in another problem: there’s no way I can pass dependencies to RoleProvider implementation through a constructor, since that class is instantiated by ASP.NET implicitly, using settings in Web.Config.

Happily, both of these problems only seem tricky to solve. For the first one, implementing all the methods, it turned out that if I want to use AuthorizeAttribute, I only need to implement one single method. That method is GetRolesForUser(..) and it does what its name tells. Now, to get the list of roles for an account in my system, I need that repository that can retrieve them from database. Since an account can be in one role at a time in my case, it simply needs to use an interface I have, IAccountRepository, to retrieve account by username:

C#
public override string[] GetRolesForUser(string username)
{
	Account account = accountRepository.GetByUsername(username);
 
	if(account != null)
		return new string[]{ account.Role };
 
	return new string[] { };
}

All is well, but we need to actually get an instance of some implementation of IAccountRepository interface, since the project doesn’t reference any of them directly.

I’m using Unity IoC Container to create implementations of interfaces and fill any dependencies they might have in their constructors. Usually, the container is only used at the highest levels of your applications, like Global.asax in case of ASP.NET. But since there’s no way to inject anything into RoleProvider classes, I decided to directly interfere with the container in my custom implementation’s Initialize method. I created a UnityContainerFactory class to get the container, so that no singletons are needed (I was convinced by some blogs that singleton should be considered an anti-pattern). The result looks like this:

C#
public override void Initialize(string name, NameValueCollection config)
{
	base.Initialize(name, config);
 
	IUnityContainer container = new UnityContainerFactory().Create();
	accountRepository = container.Resolve<IAccountRepository>();
}

The UnityContainerFactory class actually returns the same instance of IUnityContainer that is being used by the custom IControllerFactory to create ASP.NET MVC controllers. It is effectively a Singleton, as in having one instance of a class per application, but not a singleton as in having a static property that we use in every part of our application all over.

All in all, it turned out to be easier than I thought. All the other methods in my custom RoleProvider implementation were left throwing NotImplementedExceptions, but I don’t care about it yet, since these methods are not even used. The problem with inability to use the traditional Dependency Injection was solved quite easily too. Even though I don’t like the idea of directly calling the container, I had no other choice I believe. :)

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Lithuania Lithuania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionSingle role for single account, you get 5! Pin
EsseyG6-Mar-14 21:32
professionalEsseyG6-Mar-14 21:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.