【问题标题】:SimpleInjector with Sitecore and WebApi controller does not have a default constructor带有 Sitecore 和 WebApi 控制器的 SimpleInjector 没有默认构造函数
【发布时间】:2019-02-07 20:01:05
【问题描述】:

我们已将 SimpleInjector (4.4.x) 集成到我们的 Sitecore 8.2 Helix 项目中。

我们在Foundation Layer 中有一个依赖注入项目,它由以下管道组成:

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

同样如this post 中所述,流水线处理器在 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 MVCWebApi 都被使用 (.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:尝试创建“HelloController”类型的控制器时发生错误。确保控制器有一个无参数的公共构造函数。

堆栈跟踪:

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:类型“Company.Feature.Example.HelloController”没有默认构造函数

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注册在containerRoot Registrations中。

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>

【问题讨论】:

  • 我可以从异常详细信息中看到,由于某种原因(我不清楚),DefaultHttpControllerActivator 没有使用SimpleInjectorWebApiDependencyResolver,因为SimpleInjector.Integration.WebApi.SimpleInjectorWebApiDependencyResolver 永远不会当DefaultHttpControllerActivator 请求IHttpController 派生时,返回null。也许GlobalConfiguration.Configuration.DependencyResolver 稍后会再次被覆盖。您必须对此进行调试才能找出发生这种情况的原因。
  • 嗨@Steven,您的时间正好是我偶然发现的那一刻:sitecore.stackexchange.com/questions/1739/… 事实上,在 Sitecore 管道的后期,实体GlobalConfiguration 被覆盖。我已经应用了补丁,它现在可以工作了。

标签: c# asp.net-mvc asp.net-web-api sitecore simple-injector


【解决方案1】:

根据answer 和评论中建议的Steven,依赖解析器稍后在 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 重置它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 2023-03-20
    • 2016-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多