c# - 使用 Owin 和简单注入(inject)器进行 UserManager 依赖注入(inject)

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

将简单注入(inject)器添加到我的项目以创建将在 session 的整个生命周期中存在的 UserAppManager 实例后,我开始收到错误:

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

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

无参数构造函数错误:

For the container to be able to create AuthController it should have only one public constructor: it has 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;
    }
}

依赖配置:

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

最佳答案

查看您的代码:

Startup.cs

app.UseWebApi(httpConfig);

依赖配置

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

在我看来,你显然没有使用相同的 HttpConfiguration Web Api 配置和 SimpleInjector 注册的实例。

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

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

请使用相同的HttpConfiguration对于 Web Api 和 SimpleInjector 注册:

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

此外,您只需为 Controller 提供一个构造函数,以及要注入(inject)其中的每个参数(删除无参数构造函数)。


关于app.CreatePerOwinContext

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

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

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

您可以考虑使用WebRequestLifestyle , but be aware of the possible issues with async/await .

关于c# - 使用 Owin 和简单注入(inject)器进行 UserManager 依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37070107/

相关文章:

C# Blazor 错误 BL0005 - 正确设置组件属性

c# - 删除没有子节点的父节点

c# - Webapi 2 属性路由

azure - Web API 2 - CORS - 在调试中工作,但不在 IIS Express 中工作

asp.net-identity - 'ClaimsPrincipal' 不包含 'GetUserId' 的定义

cookies - 如何在应用程序中检查.AspNet.ApplicationCookie

c# - UtcNow 和 Now 是相同的日期时间吗?他们知道他们不一样吗?

c# - 从求和中忽略 NaN

.net - HttpClient.ReadAsAsync<T> 在使用 [Serializable] 时返回空对象

asp.net - 将 ASP.NET 身份存储移动到 EF Sql 数据库