Reputation: 5683
We have integrated SimpleInjector (4.4.x
) in our Sitecore 8.2
Helix project.
We have a Dependency Injection project in our Foundation Layer, which consists of the following pipeline:
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);
}
Also as described in this post, the pipeline processor is implemented in the Sitecore initialize
pipeline:
<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>
As you can see, both ASP.NET MVC
and WebApi
are used (.NET 4.6
).
Our solution consists only of MVC controllers. What we are trying to achieve is introducing WebApi
in our solution. When adding the following controller, all works well:
public class HelloController : ApiController
{
[HttpGet, Route("api/hello")]
public IHttpActionResult Get()
{
return Ok("Hello World!");
}
}
But when I add a dependency (and also register) e.g.:
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);
}
}
I'm getting the following exception message in runtime when doing the HTTP request:
System.InvalidOperationException: An error occurred when trying to create a controller of type 'HelloController'. Make sure that the controller has a parameterless public constructor.
Stack trace:
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()
InnerException:
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)
What strikes me weird is that container.Verify()
does not throw any exceptions or warnings. When debugging, I can see that the HelloController
is registered in the Root Registrations
of the container
.
Also the binding redirects for WebApi
are set in the web.config
of the root project:
<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>
Upvotes: 1
Views: 1070
Reputation: 5683
According to this answer and as Steven suggested in the comment, the dependency resolver gets overridden later in the Sitecore pipeline.
I've extended the initialize
pipeline:
<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>
Where I've also added the following processor:
public class WebApiDependenceResolverProcessor
{
public void Process(PipelineArgs args)
{
// retrieve container here
GlobalConfiguration.Configuration.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
}
}
Here we set the dependecy resolver for WebApi
after Sitecore resets it.
Upvotes: 0