配置问题与StructureMap.MVC5身份工作 [英] Issues Configuring StructureMap.MVC5 to work with Identity
问题描述
目前我正在试图从已永远不会正确摆在首位实现的旧版本(2.6)在升级后重新配置StructureMap在我们的应用程序。
我是新来使用DI容器,首先,和我为难以找到新的StructureMap版本查找文档。我卸载了旧的2.6版StructureMap和安装StructureMap.MVC5(因为我使用MVC5)。
我有是的AccountController的问题是什么。我已经StructureMap设置为使用参数的构造函数,但是当我的应用程序试图创建的UserManager,我得到一个出现InvalidOperationException
,不owin.Environment项目是在上下文中找到。
很显然,我需要StructureMap额外的配置,但我不知道什么/如何。我能找到这个错误一百万来源,所有的暗示在web.config中添加标签,但他们都不是DI容器具体 - 当我使用StructureMap VS让框架创建控制器我只有这个问题。
下面是相关的代码; AccountController中的那款只是股票模板代码。
AccountController.cs
私人ApplicationUserManager _userManager;
公众的AccountController()
{
}
公众的AccountController(ApplicationUserManager的UserManager)
{
的UserManager =的UserManager;
}
公共ApplicationUserManager的UserManager
{
得到
{
//这就是抛出异常
返回_userManager ??
HttpContext.GetOwinContext()GetUserManager< ApplicationUserManager>();
}
私定
{
_userManager =价值;
}
}
DefaultRegistry.cs
公共DefaultRegistry()
{
扫描(
扫描=>
{
扫描。 TheCallingAssembly();
scan.WithDefaultConventions();
scan.With(新ControllerConvention());
});
。对于< IBasicRepository>()
。使用< EntityRepository>()
.LifecycleIs< HttpContextLifecycle>()
.Ctor<串>(的ConnectionString)
。是(ConfigurationManager.ConnectionStrings [MyContext]的ConnectionString);
。对于<的AccountController>()
。使用<的AccountController>()
.SelectConstructor(()=>新建的AccountController());
}
由于@Erik Funkenbusch指出,我是做竞争的事情。我最终作出的UserManager自动属性,去掉了参数的构造函数,并让StructureMap注入ApplicationUserManager。
公共ApplicationUserManager的UserManager {得到;私人集; }
公众的AccountController(ApplicationUserManager的UserManager)
{
的UserManager =的UserManager;
}
然后,我只是需要配置IUserStore和的DbContext的认同DefaultRegistry使用的.cs:
对于< IUserStore< ApplicationUser,INT>>()
。使用< UserStore< ApplicationUser, CustomRole,INT,CustomUserLogin,
CustomUserRole,CustomUserClaim>>()
.LifecycleIs< HttpContextLifecycle>();
。对于<的DbContext>()
。用(()=>新建ApplicationDbContext())
.LifecycleIs< HttpContextLifecycle>();
这是所有我需要做的就是StructureMap.MVC工作与身份。
我最初挂断的部分是,我没有意识到的方式StructureMap.MVC(和其他DI容器)的工作。 (请参见我有关问题)。我希望它只是我的股票的AccountController它得到了由框架进行初始化(并认为这神奇的拦截对象的创建注入什么,我已经配置了工作),却没有意识到StructureMap必须初始化控制器本身为了使其构造进行注射。所以,当我遇到问题,我是A.奇怪,StructureMap有什么做与我摆在首位的AccountController(因为我没有明确的配置注射任何参数的 - 只为我的存储库中的其他控制器使用)和B我并没有考虑过改变我的股票代码,而是想着如何配置StructureMap。原来,我需要做两个。幸运的是,这是一个容易修改和我学到了一点更多关于DI容器是如何工作的。
I am currently trying to reconfigure StructureMap in our application after upgrading from an old version (2.6) that was never correctly implemented in the first place. I am new to using DI Containers to begin with, and am finding documentation for newer StructureMap versions hard to find. I uninstalled the old 2.6 version of StructureMap and installed StructureMap.MVC5 (since I am using MVC5).
What I am having issues with is the AccountController. I have StructureMap set up to use the parameterless constructor, but when my application tries to create the UserManager, I get an InvalidOperationException
, "No owin.Environment item was found in the context."
Obviously I need additional configuration for StructureMap, but I have no idea what/how. I can find a million sources for this error, all suggesting adding a tag in web.config, but none of them seem to be DI container specific - and I only have this issue when I use StructureMap vs letting the framework create the controller.
Below is the relevant code; that section of the AccountController is just stock template code.
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());
}
As @Erik Funkenbusch pointed out, I was doing competing things. I ended up making UserManager an auto-property, removed the parameterless constructor, and let StructureMap inject the ApplicationUserManager.
public ApplicationUserManager UserManager { get; private set; }
public AccountController(ApplicationUserManager userManager)
{
UserManager = userManager;
}
Then, I simply needed to configure the IUserStore and DbContext that Identity uses in DefaultRegistry.cs:
For<IUserStore<ApplicationUser, int>>()
.Use<UserStore<ApplicationUser, CustomRole, int, CustomUserLogin,
CustomUserRole, CustomUserClaim>>()
.LifecycleIs<HttpContextLifecycle>();
For<DbContext>()
.Use(() => new ApplicationDbContext())
.LifecycleIs<HttpContextLifecycle>();
This was all I needed to do to get StructureMap.MVC working with Identity.
Part of my initial hangup was that I didn't realize the way StructureMap.MVC (and other DI containers) worked. (See my related question.) I was expecting it to just work with my stock AccountController which got initialized by the framework (and thought it magically intercepted object creation to inject anything I had configured), not realizing that StructureMap must initialize the controllers itself in order for it to perform constructor injection. So when I ran into issues, I was A. Surprised that StructureMap had anything to do with my AccountController in the first place (since I wasn't explicitly configuring injection for any of its parameters - only for my Repository used in other controllers), and B. I wasn't thinking about changing my stock code but rather thinking about how to configure StructureMap. It turned out I needed to do both. Luckily, it was an easy modification and I learned a little more about how DI containers work.
这篇关于配置问题与StructureMap.MVC5身份工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!