UserManager dependency injection with Owin and Simple Injector

隐身守侯 提交于 2019-12-10 10:58:42

问题


After adding Simple Injector to my project to create an instance of my UserAppManager that will exist through the whole lifetime of a session I started to recieve errors:

Error with no parameterless constructor:

An error occurred when trying to create a controller of type 'AuthController'. Make sure that the controller has a parameterless public constructor.

Error with a parameterless constructor:

For the container to be able to create AuthController it should have only one public constructor: it has 2.

I followed a guide (https://simpleinjector.codeplex.com/discussions/564822) to avoid getting the UserManager from the Request.GetOwinContext() and doing it using the constructor but without luck. What am I doing wrong?

Startup:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ...
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(httpConfig);

        DependencyConfig.InjectDependencies(app);
    }
 }

AuthController:

[RoutePrefix("api/auth")]
public class AuthController : ApiController
{
    readonly private AppUserManager _appUserManager;

    public AuthController(AppUserManager appUserManager)
    {
        _appUserManager = appUserManager;
    }
}

DependencyConfig:

public class DependencyConfig
{
    public static void InjectDependencies(IAppBuilder app)
    {
        var container = new Container();
        container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

        container.Register<AppDbContext>(Lifestyle.Scoped);
        container.Register<IUserStore<AppUser>>(() => new UserStore<AppUser>(container.GetInstance<AppDbContext>()), Lifestyle.Scoped);
        container.Register<AppUserManager>(Lifestyle.Scoped);

        // other service injections

        container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
        container.Verify();
        GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

        app.CreatePerOwinContext(() => container.GetInstance<AppUserManager>());
    }
}

回答1:


Looking at your code:

Startup.cs

app.UseWebApi(httpConfig);

DependencyConfig

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);
container.Verify();
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

Seems clear to me that you are not using the same HttpConfiguration instance for both the Web Api configuration and SimpleInjector registration.

Please note that GlobalConfiguration.Configuration != httpConfig (except if you have manually assigned var httpConfig = GlobalConfiguration.Configuration).

This way your Web API middleware has no knowledge of SimpleInjector, and will use its default implementation. Because of this the creation of your controller will fail.

Please use the same HttpConfiguration for both Web Api and SimpleInjector registration:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        //...
        app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
        app.UseWebApi(httpConfig);

        DependencyConfig.InjectDependencies(app, httpConfig);
    }
 }

public class DependencyConfig
{
    public static void InjectDependencies(IAppBuilder app, HttpConfiguration config)
    {
        // ...
        container.RegisterWebApiControllers(config);
        container.Verify();
        config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
        // ...
    }
}

Also, you need to provide just a single constructor for your controller, with every parameter you want to be injected inside it (remove the parameterless constructor).


Regarding app.CreatePerOwinContext

I would be very careful in using this line:

app.CreatePerOwinContext(() => container.GetInstance<AppUserManager>());

You are requesting an instance of a LifeStyle.Scoped type inside Owin, but you declared the default scope as WebApiRequestLifestyle. This life-style inherits from ExecutionContextScopeLifestyle but the scope itself begins only on the start of a Web Api request, and thus I believe it will not be present in any middleware executed outside of Web API (maybe Steven could help us clarify this matter).

You may consider using WebRequestLifestyle, but be aware of the possible issues with async/await.



来源:https://stackoverflow.com/questions/37070107/usermanager-dependency-injection-with-owin-and-simple-injector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!