【问题标题】:StructureMap, Web Api 2, and IUserStore errorStructureMap、Web Api 2 和 IUserStore 错误
【发布时间】:2013-12-18 09:22:03
【问题描述】:

我刚刚开始尝试使用 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>>();

但是现在有另一个默认实例 StructureMap 无法解决 - dbcontext。这是我收到的下一条错误消息:

ExceptionMessage=StructureMap Exception Code:  202
No Default Instance defined for PluginFamily System.Data.Entity.DbContext, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

现在我真的迷路了……

【问题讨论】:

    标签: dependency-injection asp.net-web-api structuremap basic-authentication


    【解决方案1】:

    WithDefaultConventions() 调用不会获取您的 DbContext 和 AspNet Identity 实现。您需要查看其他一些方法,例如 SingleImplementationsOfInterface()ConnectImplementationsToTypesClosing

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

    ioc.For<MyDbContext>().HybridHttpOrThreadLocalScoped().Use<MyDbContext>();
    ioc.For<DbContext>().HybridHttpOrThreadLocalScoped().Use<MyDbContext>();
    

    对于新的 AspNet Identity 类,只需将它们提供的通用类子类化即可:

    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 类,我更喜欢显式注册这些类以用于维护目的。

    【讨论】:

      【解决方案2】:

      ericb:我可以看到你发布的内容的目的,但我不能完全让它发挥作用。 MyUserManager 类声明 "public class MyUserManager : UserManager { }" 抱怨 UserManager 接口不包含接受 0 个参数的构造函数?

      任何帮助将不胜感激!

      附言。这绝不是一个答案,但不幸的是,我没有资格简单地评论你的答案!


      更新:在这里找到解决方案:Dependency Injection Structuremap ASP.NET Identity MVC 5

      为清楚起见,我们在 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 通过他的解决方案获得的一些额外好处,但我们没有利用任何可以利用它们的东西。

      【讨论】:

        【解决方案3】:

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

            [DefaultConstructor]
            public AccountController()
            {
            }
        

        虽然正确的 IoC 解决方案是这样...

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

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            猜你喜欢
            • 2014-07-20
            • 2016-02-02
            • 1970-01-01
            • 2012-08-07
            • 2015-10-01
            • 2017-09-07
            • 2016-06-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多