Question

I have created a custom membership provider for my MVC4 solution. The problem is I can't get it injected through Unity.

I have tried using constructor injection, but then I get the parameterless constructor error. If I try using InjectionProperty its does not change any of my properties. I have tried use the DependencyResolver.Current.GetService(); it returns null.

I have first attached the provider through the web.config:

  <membership defaultProvider="ExtendedServiceMembershipProvider" userIsOnlineTimeWindow="15">
  <providers>
    <clear />
    <add name="ExtendedServiceMembershipProvider" type="Foo.Providers.Security.BoxMembershipProvider, Foo" />
  </providers>
</membership>
<roleManager defaultProvider="ExtendedServiceRoleProvider">
  <providers>
    <clear />
    <add name="ExtendedServiceRoleProvider" type="Foo.Providers.Security.BoxRoleProvider, Foo" />
  </providers>
</roleManager>

Is this the right approach? Hope some of you have a solution to my problem.

Thanks.

Était-ce utile?

La solution

What you should do is create an empty membership provider that does nothing more than call into the MVC Dependency Resolver to fetch the real Membership Provider. By doing this you achieve three things:

  • This implementation has a default constructor and can be configured in the web.config.
  • The implementation is a MVC infrastructure component and is decoupled from the actual membership provider that contains the implementation (that you probably want to test).
  • This infrastructure component has no dependency on Unity (or any other container), but just on MVC3 which lowers the coupling of the container itself.

The implementation might look like this:

public class DependencyResolverMembershipProvider : MembershipProvider
{
    private static MembershipProvider Provider
    {
        get
        {
            var provider = DependencyResolver.Current.GetService<MembershipProvider>();

            if (provider == null)
            {
                throw new InvalidOperationException(
                    "Make sure the MembershipProvider is registered.");
            }

            return provider;
        }
    }

    public override string ApplicationName
    {
        get { return Provider.ApplicationName; }
        set { Provider.ApplicationName = value; }
    }

    public override bool ChangePassword(string username, 
        string oldPassword, string newPassword)
    {
        return Provider.ChangePassword(username, oldPassword, newPassword);
    }

    public override bool ChangePasswordQuestionAndAnswer(string username, 
        string password, string newPasswordQuestion, string newPasswordAnswer)
    {
        return Provider.ChangePasswordQuestionAndAnswer(username,
            password, newPasswordQuestion, newPasswordAnswer);
    }

    public override MembershipUser CreateUser(string username, 
        string password, string email, string passwordQuestion, 
        string passwordAnswer, bool isApproved, object providerUserKey, 
        out MembershipCreateStatus status)
    {
        return Provider.CreateUser(username, password, email,
            passwordQuestion, passwordAnswer, isApproved, providerUserKey,
            out status);
    }

    // Implement all other methods here
}

This is still a lot of work, since the MembershipProvider has a lot of methods. There are two ways you can make this easier:

  • Use a framework such as Griffin.MvcContrib, which already do such a thing for you and do it even in a more pleasant way, since it separates the responsibilities that are inside these classes and expose a few new interfaces that you can implement for this functionality.
  • Prevent any part of the system of depending on the static Membership class, but always inject a MembershipProvider into those classes or even better: don't use the MembershipProvider but simply inject the interfaces that are probably behind that MembershipProvider (such as IUserRepository and IPasswordManager).
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top