简体   繁体   English

使用Owin和Simple Injector进行UserManager依赖项注入

[英]UserManager dependency injection with Owin and Simple Injector

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: 在将Simple Injector添加到我的项目中以创建UserAppManager的实例之后,该实例将在会话的整个生命周期中都存在,我开始收到错误消息:

Error with no parameterless constructor: 没有无参数构造函数时出错:

An error occurred when trying to create a controller of type 'AuthController'. 尝试创建“ 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. 为了使容器能够创建AuthController,它应该只有一个公共构造函数:它有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. 我遵循了指南( https://simpleinjector.codeplex.com/discussions/564822 )以避免从Request.GetOwinContext()获取UserManager并使用构造函数来执行它,但是没有运气。 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: AuthController:

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

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

DependencyConfig: 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>());
    }
}

Looking at your code: 查看您的代码:

Startup.cs Startup.cs

app.UseWebApi(httpConfig);

DependencyConfig 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. 对我来说似乎很清楚,Web Api配置和SimpleInjector注册都没有使用相同的HttpConfiguration实例。

Please note that GlobalConfiguration.Configuration != httpConfig (except if you have manually assigned var httpConfig = GlobalConfiguration.Configuration ). 请注意, GlobalConfiguration.Configuration != httpConfig (除非您手动分配了var httpConfig = GlobalConfiguration.Configuration )。

This way your Web API middleware has no knowledge of SimpleInjector, and will use its default implementation. 这样,您的Web API中间件将不了解SimpleInjector,并将使用其默认实现。 Because of this the creation of your controller will fail. 因此,创建控制器将失败。

Please use the same HttpConfiguration for both Web Api and SimpleInjector registration: 对于Web Api和SimpleInjector注册,请使用相同的HttpConfiguration

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 关于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 . 您正在Owin内部请求一个LifeStyle.Scoped类型的实例,但是您将默认范围声明为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). 这种生活方式继承自ExecutionContextScopeLifestyle但是范围本身仅在Web Api请求开始时才开始,因此,我相信它不会出现在Web API之外执行的任何中间件中(也许Steven可以帮助我们阐明这一点)。

You may consider using WebRequestLifestyle , but be aware of the possible issues with async/await . 您可以考虑使用WebRequestLifestyle但要注意async / await可能存在的问题

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM