1

Я только что начал экспериментировать с Web Api 2 и StructureMap, установив пакет StructureMap.MVC4 Nuget. Кажется, все работает нормально, пока я не попытался зарегистрировать пользователя. Я получил эту ошибку, когда эта реализация IHttpControllerActivator пытался создать экземпляр контроллера:StructureMap, Web Api 2 и ошибка IUserStore

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(); 
      })); 

Любые идеи, пожалуйста? Благодарю.

EDIT: Я думаю, что я, возможно, решить исходную проблему с помощью этого:

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 

Теперь я действительно потерял ...

ответ

6

WithDefaultConventions() вызов не будет забрать реализации DbContext и САШ, в удостоверениях личности. Вы захотите посмотреть на некоторые другие методы, такие как SingleImplementationsOfInterface() и ConnectImplementationsToTypesClosing.

По умолчанию, когда я настроить мой StructureMap контейнер, я буду делать следующую конфигурацию, чтобы гарантировать, что StructureMap всегда будет решать интерфейсы и базовые классы моего предпочтительного класса моего фактического предпочтительного класса:

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

Для новых классов Сети САШ идентичности, просто подкласс общих классов они дают вам из коробки:

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 я предпочитаю, чтобы эти объяснения были зарегистрированы для целей технического обслуживания.

5

ericb: Я вижу цель того, что вы опубликовали, но я не могу заставить его работать. Объявление класса MyUserManager «Открытый класс MyUserManager: UserManager {}» жалуется, что интерфейс UserManager не содержит конструктор, который принимает 0 аргументов?

Любая помощь была бы принята с благодарностью!

Ps. Это отнюдь не ответ, но я недостаточно квалифицирован, чтобы просто прокомментировать ваш ответ, к сожалению!


Update: Найдено решение здесь: 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 получает с его решением, но мы не используем ничего, что могло бы им воспользоваться.

0

Или вы можете попробовать метод инъекционного конструктор:

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

Существует быстрый и простой обходной путь для этой проблемы, а также, и во многих случаях может быть достаточно. Перейдите в 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);