0

I have created a custom membership provider that takes an instance of IUsersRepository in it's constructor.

private IUsersRepository usersRepository;
public CustomMembershipProvider(IUsersRepository usersRepository)
{
     this.usersRepository = usersRepository;
}

This dependency is bound using Ninject

Bind<IUsersRepository>().To<SqlUsersRepository>().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString);
Bind<MembershipProvider>().To<CustomMembershipProvider>();

and used in my AccountController like so

CustomMembershipProvider provider;

public AccountController(MembershipProvider membershipProvider)
{
     this.provider = (CustomMembershipProvider)membershipProvider;
}

[HttpPost]
public ActionResult Register(User user)
{
    MembershipCreateStatus status = new MembershipCreateStatus();
    provider.CreateUser(user.FirstName, user.LastName, user.Email, user.Password, out status);

    return View(user);
}

The problem with this is that when CustomMembershipProvider is instantiated the Initialize method is not called and thus my modified Web.Config is not read.

As a side to this, I've noticed that CustomMembershipProvider is being instantiated twice - the first time as I explained above, and then again when my [HttpPost] action method is called. The second time it's instantiated using a parameterless constructor and it calls the Initialize method. I don't know what happens to the second CustomMembershipProvider as provider.CreateUser() uses my un-Initialized CustomMembershipProvider.

I hope I've explained this well enough, any help would be appreciated.

Stephen Dryden
  • 561
  • 4
  • 12
  • see http://stackoverflow.com/questions/1003587/how-to-integrate-ioc-membership-provider-with-asp-net-mvc http://stackoverflow.com/questions/4193484/how-do-i-control-membershipprovider-instance-creation-lifetime – Mauricio Scheffer Jun 14 '11 at 15:15
  • Thanks for your comment but forgive me if I'm being naive - I don't see how these links help with my issue as I'm not using Windsor. – Stephen Dryden Jun 14 '11 at 15:31
  • there's hardly any difference, the same concepts apply to Ninject or any other IoC container, and even a lot of the code. – Mauricio Scheffer Jun 14 '11 at 15:52
  • @Mauricio If I'm honest I don't really understand what to do - it just seems like a lot of code and messing around to solve the issue. I'm tempted to just remove the dependency between IUsersRepository and MembershipProvider, and just put my Repository code inside the provider as that's the only place I'll use it. I do realise this will make it difficult to test. – Stephen Dryden Jun 15 '11 at 09:28

3 Answers3

0

I can't tell if you're using the Ninject.Mvc3 extension (which you probably should), but that will allow you to have a single instance of your MembershipProvider per web request. You'll have to do the binding like so:

Bind<MembershipProvider>().To<CustomMembershipProvider>().InRequestScope();

If you want to return the same instance every time you can use InSingletonScope.

Accessing web.config is not possible at the time bindings tend to be done in Mvc apps, but I usually get around that by having a custom configuration section and binding that to a method. By doing that the method will not get evaluated until the kernel is asked for a configuration section, and at that time web.config can be accessed. Something similar might work for your connection string.

Bind<MyConfigurationSection>().ToMethod(context => (MyConfigurationSection)ConfigurationManager.GetSection("mysection")).InSingletonScope();
  • thanks for your response. I'm not using the Mvc3 extension as this is a Mvc2 app (I'm relatively new to ASP.net Mvc). I tried adding InRequestScope() to my project and it seemed to create my custom membership provider a third time - I'm guessing this works different because I'm using Mvc2. – Stephen Dryden Jun 15 '11 at 08:11
  • Forgive me for sound dumb but could you elaborate on your answer for accessing web.config? Could I achieve the same thing by reading in my config values from a method called by my CustomMembershipProvider's constructor (the one that takes IUsersRepository) - this would meant that base.Initialize doesn't get called - does that matter? – Stephen Dryden Jun 15 '11 at 08:19
0
Public Class SomeRolProvider
    Inherits RoleProvider
    Implements IProvider

    'this service needs to get initialized
    <Inject()>
    Public Property _memberhip As IMemberschipService


    Sub New()
        'only this constructor is called
    End Sub



Protected Overrides Function CreateKernel() As Ninject.IKernel
            Dim modules = New NinjectModule() {New Anipmodule()}

            Dim kernel = New StandardKernel(modules)
            kernel.Inject(Roles.Provider)
            kernel.Inject(Membership.Provider)
            Return kernel
        End Function

This will force the kernel to bind properties of the memberschip provider

David
  • 4,185
  • 2
  • 27
  • 46
0

Thanks for everybody's help on this question. I was unable to find a solution that would work well for this applications situation without the need for masses of code.

To get around the issue I looked at the default MVC 2 project and copied some of Microsoft's code. My project is probably not very testable but I needed a quick solution. I've set it up so that if I do have time to find a solution in the future, I'll be able to replace it with the current code.

Stephen Dryden
  • 561
  • 4
  • 12