Custom RoleProvider is not so scary after all

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 framwork 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 requires 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 it’s 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:

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 resuls looks like this:

public override void Initialize(string name, NameValueCollection config)
{
	base.Initialize(name, config);

	IUnityContainer container = new UnityContainerFactory().Create();
	accountRepository = container.Resolve();
}

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 efectively 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. 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s