How to configure Ninject for MVC4 & custom Membership provide?
Asked Answered
B

3

3

According to this article description custom-membership-provider-with-repository-injection

I implement the custom Membership provide with inject.

Custom Membership provider

using Ninject;

public class CustomMembershipProvider : MembershipProvider
{
        [Inject]
        public IUserRepository UserRepository { get; set; }

[...]

Custom Role Provider

using Ninject;

public class CustomRoleProvider : RoleProvider
{
      [Inject]
      public IUserRoleRepository UserRoleRepository { get; set; }
[...]

within Web.Config

<membership defaultProvider="CustomsMembershipProvider">
      <providers>
        <clear/>
        <add name="CustomsMembershipProvider" type="namespace.CustomsMembershipProvider"/>
      </providers>
</membership>
<roleManager enabled="true" defaultProvider="customRoleProvider">
      <providers>
        <clear/>
        <add name="customRoleProvider" type="namespace.customRoleProvider"/>
      </providers>
</roleManager>

Now within NinjectWebCommon

private static IKernel CreateKernel()
{
      var kernel = new StandardKernel();
      kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
      kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

      RegisterServices(kernel);
      return kernel;
}

private static void RegisterServices(IKernel kernel)
{
  [...]

  kernel.Bind<IUserRepository>().To<UserRepository>();
  kernel.Bind<IUserRoleRepository>().To<UserRoleRepository>();

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

when I run application I got error

This method cannot be called during the application's pre-start initialization stage.

from kernel.Inject(Membership.Provider); this line

But If I Kernel setting put within Application_Start

I got bellow Error

Error activating IUserRepository No matching bindings are available, and the type is not self-bindable. Activation path: 2) Injection of dependency IUserRepository into property UserRepository of type CustomMembershipProvider 1) Request for CustomeMembershipProvider

How to solve that. ??

Beaudette answered 19/1, 2013 at 7:48 Comment(0)
P
2

I had a lot of trouble trying this and ended up adding a method that gets me a repository

using System.Web.Mvc;  //Used to access dependency resolver

    private IUserRepository GetUserRepository()
    {
        return DependencyResolver.Current.GetService<IUserRepository>();
    }

I then call this in the methods that require it

I was able to get the repository to become injected using constructor injection but as soon as I went to use the repository the object had been disposed. I found the above to be the simplest alternative.

However, I guess you could also use the Initialize() method

    IUserRepository userRepository;
    public override void Initialize(string name, NameValueCollection config)
    {
        base.Initialize(name, config);
        this.userRepository = DependencyResolver.Current.GetService<IUserRepository>();
    }

Or another way would be to use a property

public IUserRepository UserRepository
{
    get
    {
        return DependencyResolver.Current.GetService<IUserRepository>();
    }
}
Passport answered 19/1, 2013 at 7:51 Comment(11)
Where I put Initialize() method or IUserRepository UserRepository property. Now within controller (IUserRepository userRepository) , so any changes required to call from Controller ?Beaudette
No, all of the above can be put in your membership provider.Passport
So there is no set; for IUserRepository UserRepository property? only [inject]IUserRepository UserRepository {get;} within membership provider. Rest of the Kernel.Inject & kernel.bind<>` settings within NinjaWebCommmon and configuration in Web.Config remain same ?Beaudette
You need to remove the [Inject] attribute as we are no longer injecting it. Instead we are now getting it from ninject when we need it. NinjectWebCommon and Web.config can remain unchangedPassport
You can probably remove the bindings you are doing in CreateKernel()Passport
kernel.Inject(Membership.Provider); kernel.Inject(Roles.Provider);. So this is also not required within NinjectWebCommon ? But basic binding such as kernel.Bind<IUserRepository>().To<UserRepository>(); required ??Beaudette
Correct. You are not using ninject to inject your providers, only your repositoriesPassport
One stupid question, is DependencyResolver is a part of the Ninija?Beaudette
Not a stupid question. DependencyResolver is part of System.Web.Mvc so add a using to you membership providerPassport
Thanks, now let me try this.Beaudette
Will you please help me regarding this (#14425736)Beaudette
F
8

The result is always null. why? because asp.net has it's own static property for membership.

which is membership.provider. and this instance is not part of instance ninject management.

to workaround it , you need to use kernel.inject . but on the generate aspnetmvc.cs you would see that it's injection on PreApplicationStart event and won't let you.

here is the soloution by cipto that solve the problem for me. add this to your NinjectWebCommon

    [assembly: WebActivator.PreApplicationStartMethod(typeof(TopRankFantasy.App_Start.NinjectMVC3), "Start")]
    [assembly: WebActivator.PostApplicationStartMethod(typeof(TopRankFantasy.App_Start.NinjectMVC3), "RegisterMembership")]
    [assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(TopRankFantasy.App_Start.NinjectMVC3), "Stop")]

    public static void RegisterMembership()
    {
        bootstrapper.Kernel.Inject(Membership.Provider);
    } 

Link to article: Ninject and customMembership asp.net mvc 3

Flagging answered 20/4, 2013 at 14:48 Comment(1)
"Did you ever know that you're my hero, and everything I would like to be?" Thanks for saving my butt, this is the right way to do it with ninject and MVCCottonseed
P
2

I had a lot of trouble trying this and ended up adding a method that gets me a repository

using System.Web.Mvc;  //Used to access dependency resolver

    private IUserRepository GetUserRepository()
    {
        return DependencyResolver.Current.GetService<IUserRepository>();
    }

I then call this in the methods that require it

I was able to get the repository to become injected using constructor injection but as soon as I went to use the repository the object had been disposed. I found the above to be the simplest alternative.

However, I guess you could also use the Initialize() method

    IUserRepository userRepository;
    public override void Initialize(string name, NameValueCollection config)
    {
        base.Initialize(name, config);
        this.userRepository = DependencyResolver.Current.GetService<IUserRepository>();
    }

Or another way would be to use a property

public IUserRepository UserRepository
{
    get
    {
        return DependencyResolver.Current.GetService<IUserRepository>();
    }
}
Passport answered 19/1, 2013 at 7:51 Comment(11)
Where I put Initialize() method or IUserRepository UserRepository property. Now within controller (IUserRepository userRepository) , so any changes required to call from Controller ?Beaudette
No, all of the above can be put in your membership provider.Passport
So there is no set; for IUserRepository UserRepository property? only [inject]IUserRepository UserRepository {get;} within membership provider. Rest of the Kernel.Inject & kernel.bind<>` settings within NinjaWebCommmon and configuration in Web.Config remain same ?Beaudette
You need to remove the [Inject] attribute as we are no longer injecting it. Instead we are now getting it from ninject when we need it. NinjectWebCommon and Web.config can remain unchangedPassport
You can probably remove the bindings you are doing in CreateKernel()Passport
kernel.Inject(Membership.Provider); kernel.Inject(Roles.Provider);. So this is also not required within NinjectWebCommon ? But basic binding such as kernel.Bind<IUserRepository>().To<UserRepository>(); required ??Beaudette
Correct. You are not using ninject to inject your providers, only your repositoriesPassport
One stupid question, is DependencyResolver is a part of the Ninija?Beaudette
Not a stupid question. DependencyResolver is part of System.Web.Mvc so add a using to you membership providerPassport
Thanks, now let me try this.Beaudette
Will you please help me regarding this (#14425736)Beaudette
A
1

Since a custom RoleProvider often comes along with the custom MembershipProvider, in that case it is useful to add an injection for the Role Provider class. I used the ramon22's solution with an additional line.

[assembly: WebActivator.PreApplicationStartMethod(typeof(TopRankFantasy.App_Start.NinjectMVC3), "Start")]
[assembly: WebActivator.PostApplicationStartMethod(typeof(TopRankFantasy.App_Start.NinjectMVC3), "RegisterMembership")]
[assembly: WebActivator.ApplicationShutdownMethodAttribute(typeof(TopRankFantasy.App_Start.NinjectMVC3), "Stop")]

public static void RegisterMembership()
{
    bootstrapper.Kernel.Inject(Membership.Provider);
    bootstrapper.Kernel.Inject(Roles.Provider);
} 
Anglicanism answered 10/10, 2014 at 8:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.