Search code examples
c#asp.net-mvcasp.net-identityasp.net-identity-2simple-injector

Register IAuthenticationManager with Simple Injector


I am having a configuration setup for Simple Injector where I have moved all of my registrations to OWIN pipeline.

Now the problem is I have a controller AccountController which actually takes parameters as

public AccountController(
    AngularAppUserManager userManager, 
    AngularAppSignInManager signinManager, 
    IAuthenticationManager authenticationManager)
{
    this._userManager = userManager;
    this._signInManager = signinManager;
    this._authenticationManager = authenticationManager;
}

Now my Owin Pipeline configurations looks something like this

public void Configure(IAppBuilder app)
{
    _container = new Container();
    ConfigureOwinSecurity(app);
    ConfigureWebApi(app);
    ConfigureSimpleinjector(_container);

    app.Use(async (context, next) =>
    {
        _container.Register<IOwinContext>(() => context);
        await next();
    });

    _container.Register<IAuthenticationManager>(
        () => _container.GetInstance<IOwinContext>().Authentication);

    _container.Register<SignInManager<Users, Guid>, AngularAppSignInManager>();
}

private static void ConfigureOwinSecurity(IAppBuilder app)
{
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        CookieName = "AppNgCookie",
        //LoginPath = new PathString("/Account/Login")
    });
}

private static void ConfigureWebApi(IAppBuilder app)
{
    HttpConfiguration config = new HttpConfiguration();
    WebApiConfig.Register(config);
    app.UseWebApi(config);
}

private static void ConfigureSimpleinjector(Container container)
{
    SimpleInjectorInitializer.Initialize(container);
}

And Simple Injector Initializer looks something like this

private static void InitializeContainer(Container container)
{
    container.Register<DbContext, AngularAppContext>();

    container.Register<IUserStore<Users, Guid>, AngularAppUserStore>();
    container.Register<IRoleStore<Roles, Guid>, AngularAppRoleStore>();

    container.Register<UserManager<Users, Guid>, AngularAppUserManager>();
    container.Register<RoleManager<Roles, Guid>, AngularAppRoleManager>();
    //container.RegisterPerWebRequest<SignInManager<Users, Guid>, AngularAppSignInManager>();

    container.Register<IdentityFactoryOptions<AngularAppUserManager>, IdentityFactoryOptions<AngularAppUserManager>>();
    //container.Register<IAuthenticationManager>(() => HttpContext.Current.GetOwinContext().Authentication);

    //container.Register<SignInManager<Users, Guid>, AngularAppSignInManager>();
    // For instance:
    // container.Register<IUserRepository, SqlUserRepository>();
}

Now the problem is The controller is not able to register IAuthenticationManager. I tried using

container.Register<IAuthenticationManager>(
    () => HttpContext.Current.GetOwinContext().Authentication);

But that Leaves me with Exception as:

System.InvalidOperationException: No owin.Environment item was found in the context.

In this line

container.Register<IAuthenticationManager>(
    () => HttpContext.Current.GetOwinContext().Authentication);

I also tried instead of using HttpContext.Current.GetOwinContext().Authentication with the configuration mentioned above in public void Configure(app) method to register using app.Use(). And then later resolve it via container to get the IAuthenticationManager. But every possibilities have left me failed.

What am I missing here? Why HttpContext.Current.GetOwinContext().Authentcation is failing to resolve authentcation from OwinContext?

And if thats not, why is the same configuration via app.Use also not working?


Solution

  • What you are doing with IAuthenticationManager registration worked for me with no issues. At some point I was getting the same exception as you were getting, but that was caused by line with

    container.Verify();
    

    just after the container configuration. It was trying to create all instances of registered objects, but there was no HttpContext.Current present, hence the exception.

    Are you not getting any instances out of container before any HTTP request is available? If you really need them, then the only way to work around this is use Factory, as suggested by NightOwl888. If you don't need container before the HTTP request, then refactor, so it is not use outwith HTTP request.