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

时间:2016-05-06 10:29:50

标签: c# asp.net-web-api2 asp.net-identity owin simple-injector

在我的项目中添加Simple Injector以创建我的UserAppManager的实例后,我将开始收到错误:

没有无参数构造函数的错误:

  

尝试创建类型为' AuthController'的控制器时发生错误。确保控制器具有无参数的公共构造函数。

无参数构造函数出错:

  

要使容器能够创建AuthController,它应该只有一个公共构造函数:它有2个。

我遵循指南(https://simpleinjector.codeplex.com/discussions/564822)以避免从Request.GetOwinContext()获取UserManager并使用构造函数执行它但没有运气。我做错了什么?

启动:

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 个答案:

答案 0 :(得分:4)

查看您的代码:

<强> Startup.cs

app.UseWebApi(httpConfig);

<强> DependencyConfig

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

对我来说,似乎没有对Web Api配置和SimpleInjector注册使用相同的HttpConfiguration实例。

请注意GlobalConfiguration.Configuration!= httpConfig(除非您手动分配了var httpConfig = GlobalConfiguration.Configuration)。

这样,您的Web API中间件不了解SimpleInjector,并将使用其默认实现。因此,控制器的创建将失败。

对于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);
        // ...
    }
}

此外,您需要为控制器提供一个构造函数,并在其中注入要注入的每个参数(删除无参数构造函数)。

关于app.CreatePerOwinContext

我会非常小心地使用这一行:

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

您在Owin中请求LifeStyle.Scoped类型的实例,但您将默认范围声明为WebApiRequestLifestyle。这种生活方式继承自ExecutionContextScopeLifestyle,但范围本身仅在Web Api请求开始时开始,因此我相信它不会出现在Web API之外执行的任何中间件中(也许Steven可以帮助我们澄清)这件事)。

您可以考虑使用WebRequestLifestylebut be aware of the possible issues with async/await