问题配置StructureMap.MVC5以使用Identity

时间:2014-10-07 16:33:11

标签: c# asp.net-mvc structuremap asp.net-identity

我目前正在尝试在从最初从未正确实现的旧版本(2.6)升级后在我们的应用程序中重新配置StructureMap。 我刚开始使用DI容器,并且很难找到较新的StructureMap版本的文档。我卸载了旧的2.6版本的StructureMap并安装了StructureMap.MVC5(因为我使用的是MVC5)。

我遇到的问题是AccountController。我将StructureMap设置为使用无参数构造函数,但是当我的应用程序尝试创建UserManager时,我得到InvalidOperationException"No owin.Environment item was found in the context."

显然我需要为StructureMap提供额外的配置,但我不知道是什么/如何。我可以找到一百万个这个错误的来源,所有这些都建议在web.config中添加一个标签,但它们似乎都不是特定于DI容器的 - 而且当我使用StructureMap而不是让框架创建控制器时我只有这个问题。

以下是相关代码; AccountController的那一部分只是股票模板代码。

AccountController.cs

    private ApplicationUserManager _userManager;

    public AccountController()
    {
    }

    public AccountController(ApplicationUserManager userManager)
    {
        UserManager = userManager;
    }

    public ApplicationUserManager UserManager
    {
        get
        {
            // This is where the exception is thrown
            return _userManager ?? 
                HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
        }
        private set
        {
            _userManager = value;
        }
    }

DefaultRegistry.cs

    public DefaultRegistry() 
    {
        Scan(
            scan => 
            {
                scan.TheCallingAssembly();
                scan.WithDefaultConventions();
                scan.With(new ControllerConvention());
            });

        For<IBasicRepository>()
            .Use<EntityRepository>()
            .LifecycleIs<HttpContextLifecycle>()
            .Ctor<string>("ConnectionString")
            .Is(ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString);

        For<AccountController>()
            .Use<AccountController>()
            .SelectConstructor(() => new AccountController());
    }

1 个答案:

答案 0 :(得分:4)

正如@Erik Funkenbusch指出的那样,我正在做竞争。我最终使UserManager成为一个自动属性,删除了无参数构造函数,并让StructureMap注入了ApplicationUserManager。

    public ApplicationUserManager UserManager { get; private set; }

    public AccountController(ApplicationUserManager userManager)
    {
        UserManager = userManager;
    }

然后,我只需要配置Identity在DefaultRegistry.cs中使用的IUserStore和DbContext:

        For<IUserStore<ApplicationUser, int>>()
            .Use<UserStore<ApplicationUser, CustomRole, int, CustomUserLogin, 
                            CustomUserRole, CustomUserClaim>>()
            .LifecycleIs<HttpContextLifecycle>();

        For<DbContext>()
            .Use(() => new ApplicationDbContext())
            .LifecycleIs<HttpContextLifecycle>();  


这就是我需要做的就是让StructureMap.MVC使用Identity。

我最初的挂断的部分原因是我没有意识到StructureMap.MVC(以及其他DI容器)的工作方式。 (参见my related question。)我期待它只能使用我的库存AccountController,它被框架初始化(并认为它神奇地拦截了对象创建以注入我配置的任何东西),没有意识到StructureMap必须初始化控制器本身,以便它执行构造函数注入。所以,当我遇到问题时,我是A.很惊讶StructureMap首先与我的AccountController有关(因为我没有明确地为其任何参数配置注入 - 仅用于我在其他控制器中使用的存储库),和B.我没有考虑更改我的股票代码,而是考虑如何配置StructureMap。原来我需要做两件事。幸运的是,这是一个简单的修改,我学到了更多关于DI容器如何工作的知识。