SimpleInjector с контроллером Sitecore и WebApi не имеет конструктора по умолчанию

Мы интегрировали SimpleInjector (4.4.x) в наш проект Sitecore 8.2спираль.

У нас есть проект Dependency Injection в нашем Базовый слой, который состоит из следующего конвейера:

public void Process(PipelineArgs args)
{
    var container = new Container();
    container.Options.DefaultScopedLifestyle = new WebRequestLifestyle();

    // register app dependencies (omitted for readability)

    // get assemblies of our application
    container.RegisterMvcControllers(assemblies);
    container.RegisterWebApiControllers(GlobalConfiguration.Configuration,assemblies);

    container.Verify();

    DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
    GlobalConfiguration.Configuration.DependencyResolver =
        new SimpleInjectorWebApiDependencyResolver(container);
}

Также, как описано в эта почта, процессор конвейера реализован в конвейере Sitecore initialize:

<configuration xmlns:patch = "http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <initializeDependencyInjection/>
      <initialize>
        <processor type = "Company.Foundation.Example.DependencyInjectionProcessor, Company.Foundation.Example"
                   patch:before = "processor[@type='Sitecore.Mvc.Pipelines.Loader.InitializeControllerFactory, Sitecore.Mvc']" />
      </initialize>
    </pipelines>
  </sitecore>
</configuration>

Как видите, используются как ASP.NET MVC, так и WebApi (.NET 4.6). Наше решение состоит только из контроллеров MVC. Чего мы пытаемся добиться, так это внедрения WebApi в наше решение. При добавлении следующего контроллера все работает хорошо:

public class HelloController : ApiController
{
    [HttpGet, Route("api/hello")]
    public IHttpActionResult Get()
    {
        return Ok("Hello World!");
    }
}

Но когда я добавляю зависимость (а также регистрируюсь), например:

public interface IFoo
{
    string Hello { get; }
}

public class Foo : IFoo
{
    public string Hello => "Hello World!";
}

public class HelloController : ApiController
{
    private readonly IFoo _foo;

    public HelloController(IFoo foo)
    {
        _foo = foo;
    }

    [HttpGet, Route("api/hello")]
    public IHttpActionResult Get()
    {
        return Ok(_foo.Hello);
    }
}

Я получаю следующее сообщение об исключении во время выполнения при выполнении HTTP-запроса:

System.InvalidOperationException: An error occurred when trying to create a controller of type 'HelloController'. Make sure that the controller has a parameterless public constructor.

Трассировки стека:

at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()

Внутреннее исключение:

System.ArgumentException: Type 'Company.Feature.Example.HelloController' does not have a default constructor

at System.Linq.Expressions.Expression.New(Type type)
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)

Что меня поражает, так это то, что container.Verify() не выдает никаких исключений или предупреждений. При отладке я вижу, что HelloController зарегистрирован в Root Registrationscontainer.

Также перенаправления привязки для WebApi устанавливаются в web.config корневого проекта:

<dependentAssembly>
  <assemblyIdentity name = "System.Web.Http" publicKeyToken = "31bf3856ad364e35" xmlns = "urn:schemas-microsoft-com:asm.v1" />
  <bindingRedirect oldVersion = "0.0.0.0-5.2.3.0" newVersion = "5.2.3.0" xmlns = "urn:schemas-microsoft-com:asm.v1" />
</dependentAssembly>

Что я вижу из сведений об исключении, так это то, что по какой-то причине (это мне неясно) SimpleInjectorWebApiDependencyResolver не используется DefaultHttpControllerActivator, потому что SimpleInjector.Integration.WebApi.SimpleInjectorWebApiDepend‌​encyResolver никогда не вернет null, когда IHttpController запрашивает производное DefaultHttpControllerActivator. Возможно, позже GlobalConfiguration.Configuration.DependencyResolver снова будет переопределен. Вам придется отладить это, чтобы выяснить, почему это происходит.

Steven 05.02.2019 14:28

Привет, @Steven, твое время как раз в тот момент, когда я наткнулся на это: sitecore.stackexchange.com/questions/1739/… Действительно, позже в конвейере Sitecore объект GlobalConfiguration переопределяется. Я применил патч, и теперь он работает.

QuantumHive 05.02.2019 14:31
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
811
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В соответствии с этим отвечать и как предложено в комментарии Стивен, преобразователь зависимостей переопределяется позже в конвейере Sitecore.

Я расширил конвейер initialize:

<configuration xmlns:patch = "http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <initializeDependencyInjection/>
      <initialize>
        <processor type = "Company.Foundation.Example.DependencyInjectionProcessor, Company.Foundation.Example"
                   patch:before = "processor[@type='Sitecore.Mvc.Pipelines.Loader.InitializeControllerFactory, Sitecore.Mvc']" />
        <processor type = " Company.Foundation.Example.WebApiDependenceResolverProcessor, Company.Foundation.Example"
                   patch:after = "*[@type='Sitecore.PathAnalyzer.Services.Pipelines.Initialize.WebApiInitializer, Sitecore.PathAnalyzer.Services']" />
      </initialize>
    </pipelines>
  </sitecore>
</configuration>

Где я также добавил следующий процессор:

public class WebApiDependenceResolverProcessor
{
    public void Process(PipelineArgs args)
    {
        // retrieve container here

        GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
    }
}

Здесь мы устанавливаем преобразователь зависимостей для WebApi. после Sitecore сбрасывает его.

Другие вопросы по теме