Dependency injection StructureMap、Web Api 2和IUserStore错误

Dependency injection StructureMap、Web Api 2和IUserStore错误,dependency-injection,asp.net-web-api,structuremap,basic-authentication,Dependency Injection,Asp.net Web Api,Structuremap,Basic Authentication,我刚刚开始试验Web Api 2和StructureMap,安装了StructureMap.MVC4 Nuget包。在我尝试注册一个用户之前,一切似乎都很正常。当IHttpControllerActivator的此实现尝试实例化控制器时,我遇到此错误: public class ServiceActivator : IHttpControllerActivator { public ServiceActivator(HttpConfiguration configurat

我刚刚开始试验Web Api 2和StructureMap,安装了StructureMap.MVC4 Nuget包。在我尝试注册一个用户之前,一切似乎都很正常。当IHttpControllerActivator的此实现尝试实例化控制器时,我遇到此错误:

public class ServiceActivator : IHttpControllerActivator
    {
        public ServiceActivator(HttpConfiguration configuration) { }

        public IHttpController Create(HttpRequestMessage request
            , HttpControllerDescriptor controllerDescriptor, Type controllerType)
        {
            var controller = ObjectFactory.GetInstance(controllerType) as IHttpController;
            return controller;
        }
    }
我得到的错误是:

StructureMap Exception Code:  202
No Default Instance defined for PluginFamily Microsoft.AspNet.Identity.IUserStore`1[[Microsoft.AspNet.Identity.EntityFramework.IdentityUser, Microsoft.AspNet.Identity.EntityFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], Microsoft.AspNet.Identity.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
我理解错误是什么,但不完全确定如何解决它。假设StructureMap中的默认扫描程序找不到IUserStore的默认实现是否正确?以下是我使用的初始化代码:

ObjectFactory.Initialize(x => x.Scan(scan =>
            {
                scan.AssembliesFromApplicationBaseDirectory();
                scan.WithDefaultConventions();
            }));
有什么想法吗?谢谢

编辑: 我想我可能已经用这个解决了最初的问题:

x.For<Microsoft.AspNet.Identity.IUserStore<IdentityUser>>()
                    .Use<UserStore<IdentityUser>>();
现在我真的迷路了…

WithDefaultConventions调用无法获取您的DbContext和AspNet标识实现。您将需要了解其他一些方法,如SingleImplementationsOfInterface和ConnectionImplementsToTypesClosing

默认情况下,在设置StructureMap容器时,我将执行以下配置,以确保StructureMap始终将首选类的接口和基类解析为实际首选类:

ioc.For<MyDbContext>().HybridHttpOrThreadLocalScoped().Use<MyDbContext>();
ioc.For<DbContext>().HybridHttpOrThreadLocalScoped().Use<MyDbContext>();
对于新的AspNet标识类,只需对它们提供的通用类进行子类化即可:

public class MyUserManager : UserManager<MyUser> { }
public class MyUserStore : UserStore<MyUser> { }
然后再次确保StructureMap了解以下内容:

ioc.For<IUserStore<MyUser>>().Use<MyUserStore>();
ioc.For<UserStore<MyUser>>().Use<MyUserStore>();
ioc.For<UserManager<MyUser>>().Use<MyUserManager>();
一般来说,您不必使用StructureMap显式注册每个类,但是对于我的DbContext和Identity类,我更喜欢为维护目的而显式注册这些类

WithDefaultConventions调用将不会获取您的DbContext和AspNet标识实现。您将需要了解其他一些方法,如SingleImplementationsOfInterface和ConnectionImplementsToTypesClosing

默认情况下,在设置StructureMap容器时,我将执行以下配置,以确保StructureMap始终将首选类的接口和基类解析为实际首选类:

ioc.For<MyDbContext>().HybridHttpOrThreadLocalScoped().Use<MyDbContext>();
ioc.For<DbContext>().HybridHttpOrThreadLocalScoped().Use<MyDbContext>();
对于新的AspNet标识类,只需对它们提供的通用类进行子类化即可:

public class MyUserManager : UserManager<MyUser> { }
public class MyUserStore : UserStore<MyUser> { }
然后再次确保StructureMap了解以下内容:

ioc.For<IUserStore<MyUser>>().Use<MyUserStore>();
ioc.For<UserStore<MyUser>>().Use<MyUserStore>();
ioc.For<UserManager<MyUser>>().Use<MyUserManager>();

一般来说,您不必使用StructureMap显式注册每个类,但是对于我的DbContext和Identity类,我更喜欢为维护目的而显式注册这些类

ericb:我知道你所发布的内容的目的,但我不能完全让它发挥作用。MyUserManager类声明公共类MyUserManager:UserManager{}正在抱怨UserManager接口不包含接受0参数的构造函数

任何帮助都将不胜感激

顺便说一句,这绝不是一个答案,但不幸的是,我没有资格简单地评论你的答案

更新:在此处找到解决方案:

为清楚起见,我们在IoC文件中用以下内容替换了上述内容:

x.For<Microsoft.AspNet.Identity.IUserStore<ApplicationUser>>()
.Use<Microsoft.AspNet.Identity.EntityFramework.UserStore<ApplicationUser>>();

x.For<System.Data.Entity.DbContext>().Use(() => new ApplicationDbContext());

我确信我们错过了ericb通过其解决方案获得的一些额外好处,但我们没有利用任何可以利用这些好处的东西

ericb:我知道你所发布的内容的目的,但我不能完全让它发挥作用。MyUserManager类声明公共类MyUserManager:UserManager{}正在抱怨UserManager接口不包含接受0参数的构造函数

任何帮助都将不胜感激

顺便说一句,这绝不是一个答案,但不幸的是,我没有资格简单地评论你的答案

更新:在此处找到解决方案:

为清楚起见,我们在IoC文件中用以下内容替换了上述内容:

x.For<Microsoft.AspNet.Identity.IUserStore<ApplicationUser>>()
.Use<Microsoft.AspNet.Identity.EntityFramework.UserStore<ApplicationUser>>();

x.For<System.Data.Entity.DbContext>().Use(() => new ApplicationDbContext());

我确信我们错过了ericb通过其解决方案获得的一些额外好处,但我们没有利用任何可以利用这些好处的东西

或者您可以尝试构造函数注入方法:

x.For<IUserStore<ApplicationUser>>().Use<UserStore<ApplicationUser>>()
 .SelectConstructor(() => new UserStore<ApplicationUser>(new MyContext()));

或者您可以尝试构造函数注入方法:

x.For<IUserStore<ApplicationUser>>().Use<UserStore<ApplicationUser>>()
 .SelectConstructor(() => new UserStore<ApplicationUser>(new MyContext()));

对于这个问题也有一个快速而简单的解决方法,在许多情况下可能已经足够了。转到AccountController.cs和默认构造函数(其中没有参数或代码)上方添加[DefaultConstructor]并使用structuremap解析

    [DefaultConstructor]
    public AccountController()
    {
    }
虽然国际奥委会的正确解决方案是

    For<IUserStore<ApplicationUser>>().Use<UserStore<ApplicationUser>>();
    For<DbContext>().Use<ApplicationDbContext>(new ApplicationDbContext());
    For<IAuthenticationManager>().Use(() => HttpContext.Current.GetOwinContext().Authentication);

对于这个问题也有一个快速而简单的解决方法,在许多情况下可能已经足够了。转到AccountController.cs和默认构造函数(其中没有参数或代码)上方添加[DefaultConstructor]并使用structuremap解析

    [DefaultConstructor]
    public AccountController()
    {
    }
虽然国际奥委会的正确解决方案是

    For<IUserStore<ApplicationUser>>().Use<UserStore<ApplicationUser>>();
    For<DbContext>().Use<ApplicationDbContext>(new ApplicationDbContext());
    For<IAuthenticationManager>().Use(() => HttpContext.Current.GetOwinContext().Authentication);