Using Ninject with a Custom Role provider in an MVC3 app
Asked Answered
K

2

9

I'm trying to use a custom role provider in an MVC3 app. I've already got the membership provider working ok using Ninject but can't seem to get the role provider working. The Membership provider doesn't require a parameterless constructor but role provider does. Here's some code snippets:

Web.config

<membership>
  <providers>
    <clear/>
    <add name="MyMembershipProvider" type="MyApp.Models.NHibernateMembershipProvider" 
         applicationName="myApp" />
  </providers>
</membership>

<roleManager enabled="true">
  <providers>
    <add name="MyRolesProvider" type="MyApp.Models.NHibernateRoleProvider"
         applicationName="myApp" />
  </providers>
</roleManager>

I have a Ninject module.

public class MyNinjectModule : NinjectModule
{
    public override void Load()
    {
        this.Bind<ISession>().ToMethod(
            x => MyApp.MvcApplication.SessionFactoryData.GetCurrentSession());

        // Respository
        this.Bind<IUserRepository>().To<UserRepository>();
        this.Bind<MembershipProvider>().To<NHibernateMembershipProvider>();
        this.Bind<RoleProvider>().To<NHibernateRoleProvider>();
    }
}

The custom Membership provider

public class NHibernateMembershipProvider : MembershipProvider
{
    private IUserRepository _repo;

    public NHibernateMembershipProvider(IUserRepository repository)
    {
        _repo = repository;
    }
    ...

The role provider

public class NHibernateRoleProvider : RoleProvider
{

    private IUserRepository _repo;

    public NHibernateRoleProvider(IUserRepository repository)
    {
        _repo = repository;
    }
    ...

I then configure my controller to require an authorize

    [Authorize(Roles="Admin")]
    public ActionResult Edit(int? id)
    {
       ...

I get this error when starting the app.

Parser Error Message: No parameterless constructor defined for this object.

Source Error: 


Line 49:     <roleManager enabled="true">
Line 50:       <providers>
Line 51:         <add name="MyRolesProvider" type="MyApp.Models.NHibernateRoleProvider"
Line 52:              applicationName="myApp" />
Line 53:       </providers>

I can access the users through the membership provider, so the repository is being injected ok, but the roles provider seems to be different. Why does the role provider require a constructor-less parameter? Is there a simple way to get the role provider to work with Ninject. Any help appreciated.

Kloster answered 29/6, 2011 at 11:14 Comment(2)
I now have the role provider working most of the time, but if I try to authenticate the user, the role provider loaded doesn't have a reference to the repository (it's null). Not sure why this is happening.Kloster
The reason that the repository is null is that Ninject is not creating the role provider. It is created by the ASP.NET framework, which in turn not very DI-friendly. That's why it requires a parameterless constructor.Piton
P
18

Since the role provider, in this case the NHibernateRoleProvider is instantiated by the ASP.NET framework the best solution is to use the service locator pattern. The service locator pattern is normally considered to be an anti-pattern but sometimes you have to be pragmatic and accepted the limitation on the framework that is being used (in this case the ASP.NET framework).

Assuming you are using an implementation of the IDependencyResolver interface for Ninject. The following code should work.

public class NHibernateMembershipProvider : MembershipProvider
{
    private IUserRepository _repo;

    public NHibernateMembershipProvider()
    {
        _repo = DependencyResolver.Current.GetService<IUserRepository>();
    }

    // ...
}
Piton answered 30/6, 2011 at 4:31 Comment(3)
What is the advantage of using the IDependencyResolver interface?Kloster
There is really no advantage. I used it in this example as it provided me with a well-known abstraction of the Service Locator pattern.Piton
An alternative is to Inject the repository into a property of the custom membership provider as demonstrated here - danharman.net/2011/06/23/…Farci
C
3

Alternatively, if you're using the Ninject.Web.Mvc nuget package you can always use property injection on your role provider as illustrated here:

ASP.NET MVC 3 Ninject Custom Membership and Role Provider

Chromatic answered 10/4, 2013 at 3:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.