Property Injection in ASP.NET MVC with Ninject
August 29, 2008
I got a design challenge with asp.net mvc. I want to keep track of the currently logged in user in the session because I don’t want to hit the database every time I need to get the username or id for a query. And I have all my controllers inherit from a base controller named BaseController. So, I added a CurrentUser property to the BaseController and I want it to automagically work without the derived controllers having to do anything. Here is a class diagram to help clarify:
The CurrentUser Property needs to look something like this:
public User CurrentUser { get { var key = "currentuser"; if (Session[key] == null) { Session[key] = /*get user from database some how*/; } return (User) Session[key] ; } }
This looks simple enough but it is not. The reason it is not simple is because to get the current user I have to call Membership.Provider.GetUser from the BaseController. The problem with that is that it creates a dependency on the MembershipProvider class which I don’t want to have, because it will make testing very hard.
One obvious solution was to add the MembershipProvider (which is an abstract class) to the BaseController’s construct and then pass a mocked instance during testing… The problem with this design is that now my BaseController will be forced to have a parameterized constructor which means that I have to change the code in all the derived controllers to handle that and pass the appropriate instance of MembershipProvider. Sounds like a code smell.
My solution was to create the MembershipProvider class using my IoC container - in this case, my Ninject Kernel. This allows me to inject a SqlMembershipProvider in development and runtime and inject a mocked provider in testing. So the final CurrentUser property looks like this:
public User CurrentUser { get { var key = "currentuser"; if (Session[key] == null) { var Provider = (MembershipProvider) Kernel.Get(typeof(MembershipProvider)); Session[key] = AppHelper.CreateUserFromMembershipUser (Provider.GetUser(User.Identity.Name, true)); } return (User) Session[key] ; } }
If you have been paying attention, you are probably wondering what is this “Kernel” thing. Well Kernel is an instance of the Ninject Kernel which itself was injected into the BaseController class like this:
[Inject]
public IKernel Kernel { get; set; }
I could have done this differently. For example, I could have injected the provider itself using property injection like this:
[Inject]
public MembershipProvider Provider { get; set; }
The only problem is that the provider isn’t needed by all the derived classed and I didn’t want to have a public property in the base class that would hardly be used anywhere else. On the other hand Kernel could be globally used to instantiate an object.
What do you think? Is this the way to do it? Is there a better way?
Posted in

content rss

Add New Comment
Viewing 9 Comments
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Add New Comment
Trackbacks