ASP.Net MVC 3 Custom Membership Provider with Repository Injection

In most serious ASP.NET MVC, or even legacy ASP.Net web sites, you are unlikely to want to use the default membership provider of ASP.Net. Its dependency on SQLServer and unhealthy predilection for littering databases with hundreds tables, just to support features you don’t care about, make it distinctly unattractive.

What we really want is to integrate our web site’s security with the project’s schema and bind directly to a table or repository encapsulating the users model for the site. The way to do this is through the implementation of a custom MembershipProvider.

This may seem a little daunting, but in practise is fairly simple. In fact, all we need do is override a pair of methods, on a couple of abstract classes, and all authentication and role checking will be routed to our code. Even better, by leveraging the well-tested and robust ASP.NET security facilities, we can still utilise the convenience and security of ASP.Net’s attribute based security to protect your controllers and controller methods. If you aren’t familiar with these, it’s as simple as attaching an Authorise tag, and optionally specifying a role the user must have to gain access e.g.

public class MemberController : Controller
{
	IAccountRepository repo;

	public MemberController(IAccountRepository accountRepository)
	{
		repo = accountRepository;
	}

	[Authorize]
	public ActionResult Index()
	{
...
	}

	[Authorize(Roles = "Admin")]
	public ActionResult Delete(int accountId)
	{
...
	}
}

Just being authorised means the user has been authenticated i.e. logged in. The role is supplementary to this and allows you finer grained access control. Easy huh?

So, firstly authentication. To take control of this, we have to create a class derived from the abstract class MembershipProvider.

Unfortunately, being a hangover from old-school ASP.net, wiring this in is a little more clumsy than one might expect. It predates the pluggable design pattern applied throughout the MVC platform. The upshot being, that if you want to use the repository pattern with it, you can’t pass a repository into the constructor as ASP.Net instantiates the class for you, and only knows how to do this through a default constructor.

One way to work around this is to make your repository a property on the class and update it after the framework has constructed it. In this example I’m going to use ninject as my DI framework, but you could use a different one, or in fact just set the property without using DI at all.

First lets start with an example membership provider. I’ve only bothered to override ValidateUser() as the other methods aren’t required to leverage ASP.NET’s integrated security features.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using Ninject;

namespace MyProj.Web.Infrastructure
{
	public class AccountMembershipProvider : MembershipProvider
	{
		[Inject]
		public IAccountRepository AccountRepository { get; set; }

		public override string ApplicationName
		{
			get
			{
				throw new NotImplementedException();
			}
			set
			{
				throw new NotImplementedException();
			}
		}

... lots of unimplemented overrides...

		public override void UpdateUser(MembershipUser user)
		{
			throw new NotImplementedException();
		}

		public override bool ValidateUser(string username, string password)
		{
			return AccountRepository.IsValidLogin(username, password);
		}
	}
}

You’ll notice there is an AccountRepository being used here to validate the user login. This is where your custom authorisation logic goes – as such I’m not going to provide an implementation here as it will depend on the specifics of your site.

Next, we need to ensure that the AccountRepository is injected into our MembershipProvider, and the place to do this is Application_Start() in Gloabl.asax.

	internal class MyNinjectModules : NinjectModule
	{
		public override void Load()
		{
			Bind<IAccountRepository>()
				.To<AccountRepository>();
		}
	}

	public class MvcApplication : System.Web.HttpApplication
	{
		private IKernel _kernel = new StandardKernel(new MyNinjectModules());

...code deleted....

		protected void Application_Start()
		{
			AreaRegistration.RegisterAllAreas();

			RegisterGlobalFilters(GlobalFilters.Filters);
			RegisterRoutes(RouteTable.Routes);

			// Inject account repository into our custom membership provider.
			_kernel.Inject(Membership.Provider);
		}
	}

You’ll notice that I’m grabbing the framework instantiated instance of our membership provider, and using ninject to set the repository property on our custom membership provider.

I’m also setting up a ninject controller factory which is a great class when you want to inject repositories into your controller’s constructors. This is based on code found in one of the best programming books I’ve ever read Pro ASP.NET MVC 2 Framework by Steven Sanderson. This book covers so much more than ASP.NET MVC, it teaches you how to design and build applications for testability, and is the most digestable explanation of modern test driven design I’ve ever come across. It’s worth a read even if you aren’t an MVC programmer! n.b. I believe a revised MVC3 edition is to be released shortly.

public class NinjectControllerFactory : DefaultControllerFactory
	{
		private IKernel _kernel;

		public NinjectControllerFactory(IKernel kernel)
		{
			_kernel = kernel;
		}

		protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
		{
			if (controllerType == null)
				return null;
		 
			return (IController)_kernel.Get(controllerType);
		}
	}

Now… what if we want to create a custom role provider too? Well that’s easy. Here is an exampe RoleProvider:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using Ninject;

namespace MyProj.Web.Infrastructure
{
	public class AccountRoleProvider : RoleProvider
	{
		[Inject]
		public IAccountRepository AccountRepository { get; set; }

		public override void AddUsersToRoles(string[] usernames, string[] roleNames)
		{
			throw new NotImplementedException();
		}

... lots of unimplemented overrides...

		public override string[] GetRolesForUser(string id)
		{
			return AccountRepository.GetRoles(id);
		}

... lots of unimplemented overrides...

		public override bool RoleExists(string roleName)
		{
			throw new NotImplementedException();
		}
	}
}

Again, you really don’t need to override much of the RoleProvider abstract class, simply implementing GetRolesForUser() and ensuring it returns a string array of the given users roles will suffice.

To inject the membership provider juat change the previous code version of Application_Start() to:

	public class MvcApplication : System.Web.HttpApplication
	{
		private IKernel _kernel = new StandardKernel(new MyNinjectModules());

...code deleted....

		protected void Application_Start()
		{
			AreaRegistration.RegisterAllAreas();

			RegisterGlobalFilters(GlobalFilters.Filters);
			RegisterRoutes(RouteTable.Routes);

			// Inject account repository into our custom membership & role providers.
			_kernel.Inject(Membership.Provider);
			_kernel.Inject(Roles.Provider);
		}
	}

Finally we need to register our providers in web.config:

<configuration>
...
  <system.web>
...
    <membership defaultProvider="AccountMembershipProvider">
      <providers>
        <clear/>
        <add name="AccountMembershipProvider"
             type="MyProj.Web.Infrastructure.AccountMembershipProvider" />
      </providers>
    </membership>

    <roleManager enabled="true" defaultProvider="AccountRoleProvider">
      <providers>
        <clear/>
        <add name="AccountRoleProvider"
             type="MyProj.Web.Infrastructure.AccountRoleProvider" />
      </providers>
    </roleManager>
...
  </system.web>
...  
</configuration>

It really us as simple as that!

One other note, if you are implementing your own password storage, make sure you hash them! (and I recommend you look at bcrypt for that).

65 thoughts on “ASP.Net MVC 3 Custom Membership Provider with Repository Injection

  1. Tyrone Michael Avnit

    Brilliantly written article! Helped me so much, especially with ninject and dependancy injection with regards to the membership provider. Saw this article in response to your post on stack overflow. Exactly what I was looking for.

    Thanks again,

    Tyrone

    Reply
  2. Thomas

    I did the exact same thing but keep getting the error that The Role Manager feature has not been enabled. I get this error when running my application start code.

    Though, I’m sure it has been enabled as this is in my webconfig:

    Any ideas?

    Reply
  3. Dan Harman Post author

    Not come across that one as it works fine in my code. Your webconfig got removed by wordpress comments I think. I would be inclined to double check the config against mine as that works in an MVC3 app. Also have you got the account membership provider working as a first step?

    Reply
  4. Thomas

    Seems it was my fault. My application had two web config files which conflicted with eachother…

    Great tutorial, the most clear one that I found so far. Thumbs up!

    Reply
  5. Pingback: Storing Custom Data in Forms Authentication Tickets | | Dan HarmanDan Harman

  6. Renan

    Great article! I was searching for some solution like this about two months ago and I’ve found nothing. What a surprise to see this article made in the end of june! Thank you for your solution and keep sharing ideas and code! :)

    Reply
  7. Renan

    Hey, it’s me again! Testing this solution proposed by you, I found an annoying issue (btw, I’m using the Repository Pattern with NHibernate): when I try to use the injected repositories in the provider, the nhibernate session is “misteriously” closed! Debugging this behavior I have found that the session is disposed at some point between the application_start() and the construction of the controller.

    In the application_start() the provider contains a valid (opened) session and transaction, but just after the controller initialization seems that Ninject “recreate” the instances at request level and reinject them in the provider. I’m trying to figure out a solution to this problem. I’ve changed the scopes of binding (singleton, thread, etc) and nothing. If I find an easy (and possibly elegant) solution, I will post here. If you run into the same problem and get a solution first, I would be very pleased if you share it too!

    Reply
    1. Dan Harman Post author

      Hmm that sounds odd to me as the injection happens 1 time during start up. I think something else must be at work here. Have you tried putting a break point on the repositories properties to see if something else is accessing them?

      I’ve not used nhibernate for a very long time, but IIRC sessions are cheap and the unit of work pattern dictates you wouldn’t want to keep one for the lifetime of the app. So perhaps you should create them on demand in the repository or membership provider rather than trying to use just a single instance.

      Reply
      1. Renan

        I’m using the Unity of Work Pattern too as an separate object do control commits/rollbacks. But that’s not the problem. After debugging for a while I think that the problem is in the life management of the provider objects by the ASP.NET.

        I’ve found another solution that creates a wrapper class that calls and manage my custom providers using a IoC container (Windsor). Its very simple, elegant and works (despite being not the “right” manner of doing such customization of ASP.NET). I’ve adapted it to use Ninject and it’s working fine! All the sessions and transactions are open/initiated when the repositories are injected in the providers.

        You should check it out! :)
        http://bugsquash.blogspot.com/2010/11/windsor-managed-membershipproviders.html

        Thanks for the reply!

        Reply
        1. Dan Harman Post author

          Hi Renan,

          I suspect there is something else at work here. The Membership provider lifetime should be the same as the app domains and when it ends, a new one would be created and spun up including re-invocation of Application_Start().

          Have you tried breakpointing the constructor of your custom membership provider and seeing if its being recreated? Failing that I have seen people complain about connection loss in nhib sessions etc so maybe something to look at on that front.

          If your app domain is cycling improperly without calling app start you probably want to have a look at why that is happening as its not good. There is more info on app domain lifetime here:

          http://stackoverflow.com/questions/3772969/how-to-determine-asp-net-application-domain-lifetime

          I’m not a fan of the service locator pattern, so would prefer to understand what going on that resort to that!

          Reply
          1. Mauricio Scheffer

            Service Locator is only “bad” in application-level code. Limited use of it in framework-level code is ok. For example, all ASP.NET MVC controller factories are in fact using the container as a service locator.

            BTW: using the BuildUp / Inject feature of IoC containers prevents many important things, such as proxyability and immutability, because you don’t have control over the instantiation.

          2. Dan Harman Post author

            BTW: using the BuildUp / Inject feature of IoC containers prevents many important things, such as proxyability and immutability, because you don’t have control over the instantiation.

            Right but given we are interfacing with a non-pluggable bit of legacy framework where we don’t have control of instantiation anyway, so there isn’t much choice and to me it is preferable to bringing service location into a project.

        2. Murilo

          Renam check if there are some code that use your Membership class.

          I’m working with a custom role provider. I’ve noticed that the method GetRolesForUser was called twice: the first one by the framework and the second by one controller in my application. I don’t know why in the second call the Session was closed. I removed this code and the application runs fine now.

          Reply
  8. Johan

    Thanks for the great post. Easy to follow and understand and much appreciated.

    However, there’s one thing I do not understand:

    “ModelBinders.Binders.Add(typeof(ObjectId), new ObjectIdModelBinder());”

    What are ObjectId and ObjectIdModelBinder and which namespace or class do they come from?

    Reply
    1. Dan Harman Post author

      Hi Johan,

      You can ignore that, I accidently left it in. Its actually a model binder for a MongoDb ObjectId and isn’t really relevant to the example. I’ve now edited it out.

      Reply
  9. Marko

    Nice article…everything works well for just one provider. What about if I have more providers than one, defined in web.config? What I want to do is dynamically inject one or the other provider based on my ninject module…do you have ideas how I can accomplish this? Thank you :)

    Marko

    Reply
    1. Dan Harman Post author

      Well if you are using MVC3 then you could always use the built in resource locator (which is not a recommended pattern, but needs must) and have the provider do its own injection through this, rather than through property injection. If I get time I’ll post how to use this, but in short this will do the lookup:
      DependencyResolver.Current.GetService

      And you need to implement IDependencyResolver and register it first.

      Reply
  10. Finn Vilsbæk

    Interesting technique – but I have had some trouble making it work correctly. I’ve tried some different variations of binding etc. as suggested by various threads on stackoverflow, and I consistently end up with an ‘object not set to an instance..’ error when i call ninjectKernel.Inject(Membership.Provider) in global.asax as described. The standard Membership.Provider object is the culprit here, and it stumps me why it’s not instantiated at that point. Everything else seems to work ok – though I’m just using Ninject 2.2, as described in Sanderson’s book on MVC3 and not the Ninject.MVC NuGet package.

    What version of Ninject are you running?

    Best regards, Finn Vilsbæk

    Reply
  11. Dan Harman Post author

    Have used various versions of ninject, I tend to get it from nuget and keep it updated.

    If your Membership Provider is not instantiated by the time you get to application_start something is not right. If you’ve written your own provider, have you break pointed the constructor to see when its being initialised if at all? Maybe double check your config is right too etc?

    You could also try the technique I mention in a post above using MVC3s dependency resolver to implement the service locator pattern in the provider itself. Not a huge fan of the pattern but these providers don’t give too many choices.

    Reply
  12. Federico

    Hi, I’ve tried to run yout implementation with ninject. I can get the custom authentication and roles working. However, I can’t get the Authorize attribute to work out. I have
    [Authorize]
    public virtual ActionResult Panel()
    {
    return View();
    }
    And I’m able to view this in the browser even when I’m not logged in. I can even check User.Identity.IsAuthenticated inside the view and it gives me true/false depending if I’m logged in or not.
    Any idea on where does this problem might originate?

    Reply
  13. Trey

    Nice article. It got me going and helped me find what I was looking for. FYI, we can use constructor injection with Ninject… not on the Attribute for the reason you mentioned, but we can bind a Filter (constructor injection of our service/repository) to a decorative Attribute via the IoC container. Check it out here:

    Reply
  14. schaibaa

    Hello,

    I have some questions here if you don’t mind :)

    What if your repository has dependencies that you want to manage with NInject that has request scope — perhaps an NHibernate ISession or possibly an EF4/Linq DataContext…

    I guess what I’m asking is … have you tested this in a real production system? It’s likely to work in low volume systems – but I’m don’t know that it works how the article implies. If any of your repositories dependencies are scoped anything shorter than application, I’m pretty sure at some point your repository will get disposed (assuming it implements IDisposable) – or at the very least, it will need to be thread safe.

    Cheers

    Reply
    1. Dan Harman Post author

      Hi,

      The article wasn’t really focusing on the details of the repository abstraction. Where I’ve actually used this code, my repositories are all built around mongo db, whose sessions benefit from being:

      - thread safe.
      - able to be long lived.
      - not dependent on some kind of other unreferenced scoping of resources (which I think is what you are describing, but seems like a bad idea in a GC env, I think we all smashed ourselves up enough on this type of thing back in the C++/win32 days?)

      So none of your issues apply where I’ve used it.

      However, I know that nhib doesn’t like long lived sessions, and whilst I can’t remember if the sessions are thread safe, given it builds an in memory object map I suspect it isn’t. So in that case I’d probably just resort to the mvc3 baked in service locator pattern and just create a fresh session each time the provider gets a request. If I get some free time I’ll put up a little article on this.

      You do make a good point though – the approach I’ve outlined implies a repository scoped to the lifetime of the app (i.e. same scope as the providers) so if you are using a framework that doesn’t work like this, you need to modify the approach.

      Reply
  15. Stephen

    Great article. Thanks for taking the time to post it. You saved me a lot of time. I must buy the updated Steve Sanderson book. I loved the original. If it has more nuggets like this in it it’ll be money well spent.

    Reply
    1. Dan Harman Post author

      I recently read the 3rd edition, and now somewhat torn on the recommendation. I preferred the 2nd edition, but obviously that is now out of date and doesn’t cover razor. The 3rd edition has been streamlined and is easier to read, but in doing so they’ve dropped a few of the interesting little things that help you think like an mvc developer like the multi-stage sign up form etc. Also dropped discussions of some of the caching info, which again whilst outdated in 2nd ed, at least raised the topic.

      Reply
  16. Pawel

    Hello, Thanks for great article…

    I do not know to much about DI but i can see the point in using it for the above reason (and probably many more) where you could inject any kind of repository that uses sql, xml or whatever you may need to use without touching your membership provider. I plan adding DI to my project just for that reason :)

    Now, How come that everything works form me without DI? I just created an instance of the repository within my Membership provider and use it to validate user… it all works fine? how come? I must be missing something here.

    Can anyone please tell me if buying MVC2 book mentioned above woulb be better than buying MVC3 or even MVC4? What i mean here is, MVC2 has much more better reviews and may be written in a better way to comprehend the subject. Downside is, could be quite outdated as it not covers all the new stuff with MVC3, 4. Any Ideas?

    Once again, Thanks for the post :)

    Reply
  17. John Bubriski

    Since when does the SQL Membership Provider have an “unhealthy predilection for littering databases with hundreds tables”? In my current database it only made 11 and I think that I am using every feature.

    Are you registering the SQL Membership Provider in multiple databases?

    Reply
  18. Brady Kelly

    Very nice article. I’m just curious though; you only override ValidateUser(), so I can’t help wondering what you do for e.g. CreateUser() and ChangePassword(), the only other methods in the slightly aged MembershipProvider abstract that I am interested in. I have already implemented these in my MemberProvider class, which I access directly in my AccountController. Would you recommend I go the extra mile and override these in my CustomMembershipProvider as well, or just continue to use the repository directly?

    Reply
    1. Dan Harman Post author

      You can override the other methods if that is useful to you. This depends if you are going to use in the built in IIS management console (which tends not to be recommended for production useage). If not using that, then its easier to just manage the admin etc with some bespoke code and pages. The problem with the MS implementation is that it is a massive case of YAGNI. As the chap above mentions, it creates 11 tables, when I’ve not yet had to create a site where I’ve needed more than 2 tables for user permissioning.

      Reply
  19. Gary

    Thank you for this article. It helped me a lot but I am still facing difficulties to make my custom membership provider working.

    I installed ninjectMVC3 (V.2.2.2.0 with Ninject v.2.2.1.4) and it created a class called NinjectMVC3 in a the App_Start folder. This static class has a private method called CreateKernel which instanciate a kernel and call the method RegisterServices(kernel) where I made the binding between all my repositories and there interfaces.

    So I’m wondering if I still need to use the internal NinjectModule class you gave inside Global.asax or if I can use this NinjectMVC3 static class to inject my AccountRepository into my MembershipProvider ? And how could I use it?

    Reply
    1. Dan Harman Post author

      If using ninject MVC you don’t need to write some of the code I’ve given, but I don’t have an example to hand of how to do it, so you’ll have to do a little research.

      Reply
        1. Dan Harman Post author

          I haven’t looked at the ninject mvc stuff for a while and don’t have time to dig at the moment, but if I remember correctly it was doing some setup and startup stuff for you. Maybe even doing application_Start().

          All you need to do is track down where it’s keeping its kernel and do as per my example. Have a flick through the ninject mvc code there isn’t much to it from what I remember.

          To be honest I’d probably revise how I did this stuff now, and just cave in and use the MVC3 service locator pattern, which can be wired into ninject. Solves peoples issues with lifetime of object being passed into the membership repository.

          Reply
  20. Dave

    I don’t understand why you’d even use and override the asp.net membership and role provider at all if you’re rolling your own interfaces and classes. It just doesn’t make sense then if you don’t like the ASP.NET Membership provider that you’d have anything to do with it (overriding it or whatever else) in your custom provider implementation that you in my opinion should just do from scratch.

    Reply
    1. Christian James

      I partially agree with you Dave, the memberShipProvider does note make much sense since you will be calling FormsAuthentication.SetAuthCookie in your controller to login the user. So you might as well just call your AccountRepository diretcly to validate a user instead of doing the same job through a customMembershipProvider wrapper.
      With that said, if you want to use the AuthorizeAttribute with Role authorization i.e [Authorize(Roles = "someRole")] you must provide a RoleProvider since the MVC framework will hook into the roleProviders GetRolesForUser method to evaluate the users authority(roles).

      Reply
      1. Dan Harman Post author

        Right, that’s the whole point, you get to leverage a lot of robust well production tested authentication + authorisation code. What’s the point in rewriting that and opening yourself up when someone has already done it and its been field tested to the nth degree?

        Having said that I need to update this article for people who need repositories scoped to session lifetime not app domain lifetime!

        Reply
  21. David B. Bitton

    I just implemented this using Unity in lieu of ninject. I used the Unity.Mvc3 NuGet package. In my custom provider, I have:

    [Dependency]
    public IMembershipService MembershipService { get; set; }

    and then in my Bootstrapper.cs

    private static IUnityContainer BuildUnityContainer()
    {
    var container = new UnityContainer();

    // register all your components with the container here
    // e.g. container.RegisterType();
    container.RegisterType();
    container.BuildUp(typeof (CustomMembershipProvider), Membership.Provider);
    container.RegisterControllers();

    return container;
    }

    And then the usual complement in the web.config file. Worked like a charm. Thanks man!

    Reply
  22. Pingback: ASP.NET MVC Authentication - Customizing Authentication and Authorization The Right Way - Jon Galloway

  23. Pingback: ASP.NET MVC Authentication – Customizing Authentication and Authorization The Right Way | Code to Preload

  24. Matt

    Thank you for your posting. Just let me go on and try to put it into practice and see. Because since two weeks I am tinking about customs membership, role and profile. But only confusion and nothing clear. I really like this and the way you explain. Is it also possible to use another base class for the User class? Taking from here how a custom prifile can be include?

    Reply
  25. wok

    Question: What do you do if you don’t want to change the behavior of one of the abstract methods. For example, Membership.ValidateUser.

    public override bool ValidateUser(string username, string password)
    {

    //behave the same way,
    }

    Reply
  26. Bala

    Hi,

    I am implementing Repository Pattern in one of my project based on ASP.NET MVC4 and N-Tier Architecture. I am little confused as how to implement Custom Membership with Repository Pattern. Here are how I have implemented my classes so far.

    Generic Repository

    public interface IRepository where T : class
    {
    void Add(T entity);
    void Delete(T entity);
    void Update(T entity);
    IQueryable GetAll();
    T FindBy(Expression<Func> expression);
    IQueryable FilterBy(Expression<Func> expression);
    }

    Repository Base Class

    public abstract class Repository : IRepository where T : class
    {
    private STNDataContext _stnDataContext;
    private readonly IDbSet _dbSet;

    protected Repository(IDatabaseFactory databaseFactory)
    {
    DatabaseFactory = databaseFactory;
    _dbSet = StnDataContext.Set();
    }

    protected IDatabaseFactory DatabaseFactory { get; private set; }
    public STNDataContext StnDataContext
    {
    get { return _stnDataContext ?? (_stnDataContext = new STNDataContext()); }
    }
    public void Add(T entity)
    {
    _dbSet.Add(entity);
    _stnDataContext.Commit();
    }

    public void Delete(T entity)
    {
    _dbSet.Remove(entity);
    }

    public void Update(T entity)
    {
    _dbSet.Attach(entity);
    _stnDataContext.Entry(entity).State = EntityState.Modified;
    _stnDataContext.Commit();
    }

    public IQueryable GetAll()
    {
    return _dbSet.ToList().AsQueryable();
    }

    public T FindBy(Expression<Func> expression)
    {
    return FilterBy(expression).SingleOrDefault();
    }

    public IQueryable FilterBy(Expression<Func> expression)
    {
    return GetAll().Where(expression).AsQueryable();
    }

    User Repository Interface

    public interface IUserRepository : IRepository
    {
    }

    User Repository

    public class UserRepository : Repository, IUserRepository
    {
    public UserRepository(IDatabaseFactory databaseFactory)
    : base(databaseFactory)
    {
    }
    }

    Heres my Business Logic Layer

    Generic Service Interface

    public interface IService
    {
    void Add(T entity);
    void Delete(T entity);
    void Update(T entity);
    IEnumerable GetAll();
    T FindBy(Expression<Func> expression);
    IEnumerable FilterBy(Expression<Func> expression);
    }

    Service Base

    public class Service : IService where T : class
    {
    public void Add(T entity)
    {
    throw new NotImplementedException();
    }

    public void Delete(T entity)
    {
    throw new NotImplementedException();
    }

    public void Update(T entity)
    {
    throw new NotImplementedException();
    }

    public IEnumerable GetAll()
    {
    throw new NotImplementedException();
    }

    public T FindBy(Expression<Func> expression)
    {
    throw new NotImplementedException();
    }

    public IEnumerable FilterBy(Expression<Func> expression)
    {
    throw new NotImplementedException();
    }
    }

    User Service Interface

    public interface IUserService : IService
    {
    }

    User Service Implementation

    public class UserService : Service, IUserService
    {
    private readonly IUserRepository _userRepository;
    private readonly IRoleRepository _roleRepository;

    public UserService(IUserRepository userRepository, IRoleRepository roleRepository)
    {
    _userRepository = userRepository;
    _roleRepository = roleRepository;
    }

    public IList GetAllUsers()
    {
    return _userRepository.GetAll().ToList();
    }

    public User GetUser(int id)
    {
    return _userRepository.FindBy(x => x.UserId == id);
    }

    public User GetUser(string userName)
    {
    return _userRepository.FindBy(x => x.Username.Equals(userName));
    }

    public void CreatUser(User user)
    {
    _userRepository.Add(user);
    }

    public IList GetUsersForRole(string roleName)
    {
    return _userRepository.FilterBy(x => x.Role.RoleName.Equals(roleName)).ToList();
    }

    public IList GetUsersForRole(int roleId)
    {
    return _userRepository.FilterBy(x => x.Role.RoleId == roleId).ToList();
    }

    public IList GetUsersForRole(Role role)
    {
    return GetUsersForRole(role.RoleId);
    }

    }
    Hi Bob,
    I am developing one application using ASP.NET MVC4, N-Tier Architecture and Repository Pattern. I want to implement Custom Membership functionality and refering your gpsnerd application as reference. I am little confused implementing the same. Can you help?

    I am not very sure on Am I going the right way? If yes how do i implement my UserService class. 

    If no, what changes do i need to implement.

    Any help on this is highly appreciable. Thanks in advance

    Reply
  27. Kevin Shum

    Hi there, great article. However, there is one part I cannot follow…

    When you inject Membership.Provider and Roles.Provider what are these in reference to? I am not familiar with Ninject and I use Castle Windsor so I am not sure what should be passed into your kernel but I cannot find any reference to the providers. I thought you would be telling your kernel to inject an implementation of an interface when an interface is used. I cannot see the repository being injected anywhere, but can see you injecting a provider??

    Thanks :)

    Reply
    1. Dan Harman Post author

      They are global singletons… Asp.net has a lot of legacy and that’s one of the design issues in this version. I think it may have changed in the newer versions and I’ve been playing with some oauth providers based on the new templates in vs2012. Nothing to share yet though.

      Here are the lines where the asp singleton references are registered:

      // Inject account repository into our custom membership & role providers.
      _kernel.Inject(Membership.Provider);
      _kernel.Inject(Roles.Provider);

      Reply
      1. Kevin Shum

        Many thanks for taking the time to reply.

        Ok, so they are global singletons of a membership provider and a role provider. So it looks like you are injecting a membership provider and a role provider but not the repository.

        Also I would expect you to only need to inject the repository once and not twice.

        I think its quite obvious that I have misunderstood something somewhere so thanks for taking the time to explain.

        Reply
  28. Dan Harman Post author

    The repo is property injected as we don’t get to instantiate the membership provider as the framework does that. I.e. we can’t do create it via the repo to constructor inject.

    The other option is just to service locate the repo in the provider. More recent asp mvc has a service locator in the framework so I’d probably just use that these days. Service location is an anti pattern, but given ms have baked in a global singleton sometimes you just have to play the hand your are dealt…

    Reply
  29. Brett

    Great article! I’m hoping to adopt an approach demonstrated here.

    However, just wondering if there is a way to inject a different repository after application_start, for example I wanted to use a different repository when in a different area of the application?

    Thanks,
    Brett.

    Reply
  30. Jeff Hojnacki

    Hi Dan,

    Your article for a custom membership provider is exactly what I need. I downloaded and installed Ninject. I created a custom Membership Provider. Cut and pasted your sample code right into Global.asax, but it won’t compile because StandardKernel is expecting an Array.

    private IKernel _kernel = new StandardKernel(new MyNinjectModules());

    MyNinjectModules looks like below right now. Note: The Load function is commented because I have not implemented it yet.

    internal class MyNinjectModules : MyCustomMembershipProvider // NinjectModule
    {
    //public override void Load()
    //{
    //Bind()
    // .To();
    //}
    }

    I have searched for a few hours for other code samples, and tried a whole bunch of things, but unsuccessful. This has got to be something really simple. Please advise.

    Thanks,

    Jeff

    Reply

Leave a Reply