【问题标题】:Configure Unity DI for ASP.NET Identity为 ASP.NET 标识配置 Unity DI
【发布时间】:2014-03-22 13:48:31
【问题描述】:

我成功地将 Unity 用于所有常规构造函数注入,例如存储库等,但我无法让它与 ASP.NET Identity 类一起使用。设置是这样的:

public class AccountController : ApiController
{
    private UserManager<ApplicationUser> _userManager { get; set; }

    public AccountController(UserManager<ApplicationUser> userManager)
    {
        if (userManager == null) { throw new ArgumentNullException("userManager"); }
        _userManager = userManager;
    }

    // ...
}

使用 Unity 的这些配置:

unity.RegisterType<AccountController>();
unity.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
unity.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager());

这与 Autofac 的其他帖子相同,例如 Ninject,但在我的情况下它不起作用。错误信息是:

尝试创建“AccountController”类型的控制器时出错。确保控制器有一个无参数的公共构造函数。 当然是手工创作作品:

public AccountController()
    : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>("Mongo")))
{
}

怎么了?

更新

正如@emodendroket 所建议的,将代码缩短到这个就可以了。不需要 Unity.Mvc 包。

unity.RegisterType<IUserStore<IdentityUser>, 
  MyCustomUserStore>(new HierarchicalLifetimeManager());

public AccountController(UserManager<IdentityUser> _userManager,
  IAccountRepository _account)
{
    // ...

【问题讨论】:

  • Mvc 和 web api 对 DI 使用不同的接口。 Nuget 来自 Microsoft P&P 的最新 Unity WebApi 包
  • 确定吗?我只能看到“引导程序”包和 3rd 方库的差异,而不是 Unity 包本身。
  • 你没有得到内部异常吗?
  • 安装 Unity.Mvc 包。此外,您不需要注册控制器。该消息似乎表明您仍在使用默认控制器工厂,Unity.Mvc 应该提供帮助。
  • 如果您刚刚安装了 Unity MVC 包并且在使用 ASP.NET 身份帐户控制器时遇到了问题,请参阅此处:stackoverflow.com/questions/20023065/…

标签: c# asp.net dependency-injection unity-container asp.net-identity


【解决方案1】:

替换AccountController中的这个属性

public ApplicationUserManager UserManager
{
    get
    { 
        _userManager = new ApplicationUserManager(
                          new UserStore<ApplicationUser>(new ApplicationDbContext()));
        return _userManager ??
               Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
    }
    private set
    {
        _userManager = value;
    }
}

【讨论】:

  • 请考虑添加一些解释,说明为什么这个答案是正确的,并且比其他答案更好。
【解决方案2】:

正如blog post from enterpriseframework.com 所说:

首先,添加 Unity Bootstrapper for ASP.NET MVC Nuget 包。

  1. 在 Visual Studio“解决方案资源管理器”中 > 右键单击​​ Web 项目的“参考”节点 > 单击“管理 NuGet 包”。

  2. 从左侧菜单中,选择在线 > 全部

  3. 在右上角的搜索框中 > 在线搜索 (Ctrl + E) > 键入“Unity bootstrapper for ASP.NET MVC”。
  4. 选择“Unity Bootstrapper for ASP.NET MVC”并选择安装。
  5. 安装完成后点击关闭

然后修改your-Web-project/App_Start/UnityConfig.cs文件,更新using语句如下:

    using System;
    using System.Data.Entity;
    using Microsoft.AspNet.Identity;
    using Microsoft.AspNet.Identity.EntityFramework;
    using Microsoft.Practices.Unity;
    using Microsoft.Practices.Unity.Configuration;
    using MicrosoftIdentity.Controllers;
    using MicrosoftIdentity.Models;

最后,在同一个文件中,更新RegisterTypes方法如下:

        public static void RegisterTypes(IUnityContainer container)
        {
            // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
            // container.LoadConfiguration();

            // TODO: Register your types here
            container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>();
            container.RegisterType<UserManager<ApplicationUser>>();
            container.RegisterType<DbContext, ApplicationDbContext>();
            container.RegisterType<ApplicationUserManager>();
            container.RegisterType<AccountController>(new InjectionConstructor());
        }

HTH

【讨论】:

    【解决方案3】:

    您还需要解析 UserManager。以下是如何使用 UserManagerRoleManager 的示例。在这个示例中,我使用了常规的 Unity 3 包,而不是其中的派生程序或引导程序(过去曾遇到过一些问题)。

    帐户控制器

    private readonly UserManager<ApplicationUser> _userManager;
    
    private readonly RoleManager<IdentityRole> _roleManager;
    
    public AccountController(IUserStore<ApplicationUser> userStore, IRoleStore<IdentityRole> roleStore)
    {
      _userManager = new UserManager<ApplicationUser>(userStore);
      _roleManager = new RoleManager<IdentityRole>(roleStore);
    }
    

    Unity 引导程序

    var accountInjectionConstructor = new InjectionConstructor(new IdentitySampleDbModelContext(configurationStore));
    container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(accountInjectionConstructor);
    container.RegisterType<IRoleStore<IdentityRole>, RoleStore<IdentityRole>>(accountInjectionConstructor);
    

    【讨论】:

    • 谢谢,只注入 UserStore 有效。但是为什么我不尝试让 Unity 也注入 UserManager 实例呢?因为它无论如何都是框架的一部分,我不需要测试/替换代码?
    • 没有必要。你实际上可以注入这些东西。
    • 你能详细说明你传入的configurationStore吗?
    • 我使用与您相同的代码,并且 UserStore 注册良好,但它不会编译 RoleStore 注册。错误 = 类型“Microsoft.AspNet.Identity.EntityFramework.RoleStore”不能用作泛型类型或方法“Microsoft.Practices.Unity.UnityContainerExtensions”中的类型参数“TTo”。 RegisterType(Microsoft.Practices.Unity.IUnityContainer, params Microsoft.Practices.Unity.InjectionMember[])'。
    • @MikeDymond 我相信它应该是 container.RegisterType, RoleStore>(accountInjectionConstructor)。缺少字符串部分
    【解决方案4】:
    Install-Package Unity.AspNet.WebApi
    

    您需要在 HttpConfiguration.DependencyResolver 属性下注册 Unity。这让WebApi 知道它需要使用 Unity 而不是反射来实例化您的控制器。

    最简单的方法是使用上面的 nuget 包。

    【讨论】:

    • Unity.AspNet.WebApi 只是 Unity 的脚手架,而且它有一个 IDependencyResolver 的实现。 Unity 运行良好,只是不适用于特定的 ASP.NET Identity 类。我怀疑问题出在UserManager,我可能试图以错误的方式注册。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多