Search code examples
c#asp.netsimple-injector

Simple Injector - ApplicationSignInManager is registered as transient, but implements IDisposable


So I am trying to set up my application to use Simple Injector with Microsoft's default ASP.NET.Identity but I can't get it to work. I have looked into various sources such as here: https://simpleinjector.codeplex.com/discussions/564822

But I have hit yet another snap with the SignInManager. The full error message I receive is this:

The configuration is invalid. The following diagnostic warnings were reported:

-[Disposable Transient Component] ApplicationSignInManager is registered as transient, but implements IDisposable.

See the Error property for detailed information about the warnings. Please see https://simpleinjector.org/diagnostics how to fix problems and how to suppress individual warnings.

I looked around and I saw that I could add this line to DI the SignInManager:

RegisterPerWebRequest<SignInManager<ApplicationUser, string>, ApplicationSignInManager>();

However when I do this I receive many more errors which look like so:

The configuration is invalid. The following diagnostic warnings were reported:

-[Short Circuited Dependency] AccountController might incorrectly depend on unregistered type ApplicationSignInManager (Transient) instead of SignInManager (Web Request).

-[Short Circuited Dependency] ManageController might incorrectly depend on unregistered type ApplicationSignInManager (Transient) instead of SignInManager (Web Request).

-[Disposable Transient Component] ApplicationSignInManager is registered as transient, but implements IDisposable.

-[Ambiguous Lifestyles] The registration for ApplicationSignInManager (Transient) maps to the same implementation (ApplicationSignInManager) as the registration for SignInManager (Web Request) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.

-[Ambiguous Lifestyles] The registration for SignInManager (Web Request) maps to the same implementation (ApplicationSignInManager) as the registration for ApplicationSignInManager (Transient) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.

See the Error property for detailed information about the warnings. Please see https://simpleinjector.org/diagnostics how to fix problems and how to suppress individual warnings.

I'm not sure how to DI the SignInManager so I can get it to work with my application.

My Account controller looks like this:

public class AccountController : Controller
{
    private ApplicationSignInManager _signInManager;
    private ApplicationUserManager UserManager;

    public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
    {
        UserManager = userManager;
        SignInManager = signInManager;
    }

    public ApplicationSignInManager SignInManager
    {
        get
        {
            return _signInManager ?? HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
        }
        private set { _signInManager = value; }
    }
}

And my Inialiser for Simple Injector like this:

public static class SimpleInjectorInitializer
{
    public static Container Initialize(IAppBuilder app)
    {
        var container = GetInitializeContainer(app);

        container.Verify();

        DependencyResolver.SetResolver(
            new SimpleInjectorDependencyResolver(container));

        return container;
    }

    private static Container GetInitializeContainer(IAppBuilder app)
    {
        var container = new Container();

        container.RegisterSingleton(app);

        container.RegisterPerWebRequest<ApplicationUserManager>();

        container.RegisterPerWebRequest(() => new ApplicationDbContext(
            "connectionString"));

        container.RegisterPerWebRequest<IUserStore<ApplicationUser>>(() =>
            new UserStore<ApplicationUser>(
                container.GetInstance<ApplicationDbContext>()));

        container.RegisterInitializer<ApplicationUserManager>(
            manager => InitializeUserManager(manager, app));

        container.RegisterMvcControllers(Assembly.GetExecutingAssembly());

        container.Register<IAuthorisationManager, AuthorisationManager>(
            Lifestyle.Transient);
        container.Register<IAuthorisationRepository, AuthorisationRepository>(
            Lifestyle.Transient);

        container.RegisterPerWebRequest<SignInManager<ApplicationUser, string>, 
            ApplicationSignInManager>();

        container.RegisterPerWebRequest(() =>
            AdvancedExtensions.IsVerifying(container) 
                ? new OwinContext(new Dictionary<string, object>()).Authentication
                : HttpContext.Current.GetOwinContext().Authentication);

        return container;
    }

    private static void InitializeUserManager(ApplicationUserManager manager, IAppBuilder app)
    {
        manager.UserValidator = new UserValidator<ApplicationUser>(manager)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        //Configure validation logic for passwords
        manager.PasswordValidator = new PasswordValidator()
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = false,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };

        var dataProtectionProvider = app.GetDataProtectionProvider();

        if (dataProtectionProvider != null)
        {
            manager.UserTokenProvider =
               new DataProtectorTokenProvider<ApplicationUser>(
                  dataProtectionProvider.Create("ASP.NET Identity"));
        }
    }
}

Can anyone help me use Simple Injector to register my SignInManager?


Solution

  • I have not injected the correct sign in manager to my controllers:

     public class AccountController : Controller
        {
            private SignInManager<ApplicationUser, string> SignInManager;
            private ApplicationUserManager UserManager;
    
            public AccountController(ApplicationUserManager userManager, SignInManager<ApplicationUser, string> signInManager )
            {
                UserManager = userManager;
                SignInManager = signInManager;
            }
        }
    

    Although I now get a parameter count mismatch issue on start up which I am looking into