-
Corey Peplau wrote this - WFFM conflict with Unity DI and a lesson on how Sitecore community is so amazing
July 24, 2017 Rodrigo Peplau 1
This blog was since the beginning, a space to share my own experiences with Sitecore development, always trying to bring that something new, not easily seen, or showing my interpretation of common problems. But this time I need to break my own rule and bring a story starred by another person. I’m talking about my good friend Corey Smith, the most willful person I ever met.
First a small parable
An engineer was hired to fix a complex machine, which he did in less than an hour by simply twisting a single screw.
- How much it cost? Asks the client.
- 10 thousand dollars, sir…
- But that is a lot of money just to twist a screw! I need you to do an invoice with details of your job to justify this price.
And the invoice listed:
- Twist a screw: $ 5.00
- Know what screw to twist: $ 9,995.00
Corey is a step ahead of this story and managed to not only twist the right screw, but made that remotely, and for free.
The WFFM issue
Everything started when, at my first project as new member of Nish Tech Inc, I had to install WFFM 8.2 rev. 170413 (Update-3) up above an existent solution. Starting from there, any MVC WFFM form were dying with the following error:
Error Rendering Controller: Sitecore.Forms.Mvc.Controllers.FormController, Sitecore.Forms.Mvc. Action: Index: Could not create controller: ‘Sitecore.Forms.Mvc.Controllers.FormController, Sitecore.Forms.Mvc’. The item being rendered is: ‘/sitecore/content/Website/Home/Community/Cincinnati’. The context item is: ‘/sitecore/content/Website/Home/Community/Cincinnati’. The current route url is: ‘{*pathInfo}’. This is the default Sitecore route which is set up in the ‘InitializeRoutes’ processor of the ‘initialize’ pipeline.
at Sitecore.Mvc.Controllers.SitecoreControllerFactory.CreateController(RequestContext requestContext, String controllerName)
at Sitecore.Mvc.Controllers.ControllerRunner.GetController()
at Sitecore.Mvc.Controllers.ControllerRunner.Execute()
at Sitecore.Mvc.Presentation.ControllerRenderer.Render(TextWriter writer)
at Sitecore.Mvc.Pipelines.Response.RenderRendering.ExecuteRenderer.Render(Renderer renderer, TextWriter writer, RenderRenderingArgs args)Inner Exception: Resolution of the dependency failed, type = “Sitecore.Forms.Mvc.Controllers.FormController”, name = “(none)”. Exception occurred while: while resolving. Exception is: InvalidOperationException – The current type, Sitecore.Forms.Mvc.Interfaces.IRepository`1[Sitecore.Forms.Mvc.Models.FormModel], is an interface and cannot be constructed. Are you missing a type mapping? ———————————————– At the time of the exception, the container was: Resolving Sitecore.Forms.Mvc.Controllers.FormController,(none) Resolving parameter “repository” of constructor Sitecore.Forms.Mvc.Controllers.FormController(Sitecore.Forms.Mvc.Interfaces.IRepository`1[[Sitecore.Forms.Mvc.Models.FormModel, Sitecore.Forms.Mvc, Version=8.2.0.0, Culture=neutral, PublicKeyToken=null]] repository, Sitecore.Forms.Mvc.Interfaces.IAutoMapper`2[[Sitecore.Forms.Mvc.Interfaces.IFormModel, Sitecore.Forms.Mvc, Version=8.2.0.0, Culture=neutral, PublicKeyToken=null],[Sitecore.Forms.Mvc.ViewModels.FormViewModel, Sitecore.Forms.Mvc, Version=8.2.0.0, Culture=neutral, PublicKeyToken=null]] mapper, Sitecore.Forms.Mvc.Interfaces.IFormProcessor`1[[Sitecore.Forms.Mvc.Models.FormModel, Sitecore.Forms.Mvc, Version=8.2.0.0, Culture=neutral, PublicKeyToken=null]] processor, Sitecore.WFFM.Abstractions.Shared.IAnalyticsTracker analyticsTracker) Resolving Sitecore.Forms.Mvc.Interfaces.IRepository`1[Sitecore.Forms.Mvc.Models.FormModel],(none)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
at Sitecore.Mvc.Controllers.SitecoreControllerFactory.CreateControllerInstance(RequestContext requestContext, String controllerName)
at Sitecore.Mvc.Controllers.SitecoreControllerFactory.CreateController(RequestContext requestContext, String controllerName)Inner Exception: The current type, Sitecore.Forms.Mvc.Interfaces.IRepository`1[Sitecore.Forms.Mvc.Models.FormModel], is an interface and cannot be constructed. Are you missing a type mapping?
at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructInterface(IBuilderContext context)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
at lambda_method(Closure , IBuilderContext )
at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.b__0(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)The greatness of Sitecore community
After some googling I found this article from Corey Smith, where he describes a similar issue after an upgrade, which he solved by moving his Dependency Injection declaration before the InitializeControllerFactory. I know that recent versions of WFFM are using Dependency Injection, so it sounded like a good clue to start my investigation.
But in my case we were using Unity Dependency Injection, nothing registered at Sitecore Pipeline, so I thought – why not asking Corey himself for an idea? He is a great guy, as per what we’ve seen during his presentation at the Sitecore Usergroup Brazil (video can be seen here).
What followed was a real lesson for me, breaking my paradigms of balance between personal and professional life, and showing to my amazed eyes how strong, powerful and great is the Sitecore community in general, and Corey Smith in particular.
Our investigation
It was 3rd July, I was stuck at the hotel in Cincinnati with my family and this issue to solve. Corey were safe at his home in Atlanta, at the convenient distance of a single click to interrupt the chat. We were texting like crazy thru Twitter private messages. Fortunately, we both had beers at our side, would you do without some?
We started focusing at the Unity Dependency Injection setup. Under my App_Start folder I had a class called UnityMvcActivator with following decorations above the namespace:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(UnityWebActivator), “Start”)]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(UnityWebActivator), “Shutdown”)]
namespace MyClient.Website.Core.App_Start
{
public static class UnityWebActivator
{
public static void Start()
{
Line in bold is specifically setting the start-up of Dependency Injection. That would be automatically invoking (at some point in the Application_Start event) the method Start(). The exact point, however, was a mystery for us, so we managed to increase a little of our control over this. Perhaps changing the order here would make any difference?
So we removed the line in bold, then registered the method Start as an Initialize Pipeline processor. For that, the Start signature had to change into a valid Process method, as seem below:
public void Process(PipelineArgs args)
That way we would be able to control the timing when the DI start-up would occur. Promising? I thought so! However unfortunately, no matter where the registration is made, before or after everything, still the same error was showing.
Root cause
After digging a bit more, Corey came up with the root cause, and a possible solution. Happens that the controller for WFFM forms (FormController), which is the affected class at the error message, has actually two constructors: one without any parameter
public FormController()
And a second one with more parameters
public FormController(IRepository<FormModel> repository, IAutoMapper<IFormModel, FormViewModel> mapper, IFormProcessor<FormModel> processor, IAnalyticsTracker analyticsTracker)
When Unity tries to instantiate this class it is automatically choosing the controller with most parameters. And that is making the whole thing blow up to the sky.
Temporary (quick) solution
The temporary solution we ended up doing was:
- Roll back the pipeline modification and allow Unity to registry itself again
- Add the following new line to UnityConfig, RegisterTypes method:
public class UnityConfig
{
public static void RegisterTypes(IUnityContainer container)
{
// Workaround to solve WFFM issues
container.RegisterType<FormController>(new InjectionConstructor());
What the line above does is to tell Unity to register, only at the FormController class, the constructor with no parameters. This, however, is an ad-hoc solution which brings a very important indagation: What else are we breaking in Sitecore? What other controllers and dependencies do we need to register?
“You will probably find out in production, I suppose” says Corey.
Appropriate (hard) solution
Best thing to do is to abandon Unity Dependency Injection at this project and have Sitecore’s built-in Dependency Injection (Microsoft.Extensions.DependencyInjection) to handle all injections at our system. We are not gaining anything using Unity at this project, but actually we are creating problems.
Sitecore’s OOTB Dependency Injection is shipped from factory with all proper Dependency Injection configurations. That means that all Sitecore modules play very nice with it, so the whole issue we are having with Unity, for instance, simply wouldn’t even happen at first place.
Along with that, in Sitecore 8.2, we can do Dependency Injection into pipeline processors, which has always been a requirement at Nish Tech, and is also totally awesome!
Categories: Bug fixing, Sitecore Community, WFFM
PhantomJS Screenshots not being generated with Windows Authentication turned on WFFM - Sitecore Context Item NULL inside a Save Action
One thought on “Corey Peplau wrote this - WFFM conflict with Unity DI and a lesson on how Sitecore community is so amazing”
Leave a Reply Cancel reply
Proudly 9x Sitecore MVP
(2016-2024)
Localization
Recent Posts
Recent Comments
- navan on Meet MVPinny: the AI-Powered Sitecore Assistant
- Adriana on Content generation with Sitecore Connect and ChatGPT
- NAVAN on Automatic Sitecore NuGet upgrades with Powershell
- Hedipo S Menezes on Corey Peplau wrote this - WFFM conflict with Unity DI and a lesson on how Sitecore community is so amazing
- Rodrigo Peplau on ERROR [Content Testing]: Cannot find PhantomJS executable at ' (...) /data/tools/phantomjs/phantomjs.exe'. Aborting screenshot generation.
Archives
- June 2024
- April 2024
- February 2024
- December 2023
- November 2023
- August 2023
- July 2023
- January 2023
- February 2022
- December 2021
- November 2021
- March 2021
- July 2020
- February 2020
- September 2019
- July 2019
- April 2019
- March 2019
- December 2018
- February 2018
- January 2018
- November 2017
- September 2017
- August 2017
- July 2017
- March 2017
- February 2017
- November 2016
- September 2016
- August 2016
- July 2016
- April 2016
- November 2015
- September 2015
- July 2015
- April 2015
- March 2015
- February 2015
Categories
- Actions
- Active Directory
- Analytics
- Architecture
- Bug fixing
- CDP/Personalize
- ChatGPT
- Content Edition Experience
- Content Hub
- Continuous Integration
- Dev
- Development
- Environments
- Experience Editor
- Experience Forms
- Front-end
- Health Check builds
- Helix
- How To
- LDAP
- MVP
- MVP Summit
- MVPinny
- Phantom JS
- Powershell
- QA
- Richtext Editor
- Rules
- Security Provider
- SIF
- Sitecore 9
- Sitecore API
- Sitecore Community
- SItecore Connect
- Sitecore Modules
- Sitecore Rocks
- Sitecore Rule Processor
- Sitecore Symposium
- SPE
- SPEAK
- SUG
- Support Ticket
- TDS
- Team City
- Uncategorized
- Upgrades
- Visual Studio
- WFFM
- Workflow
- XConnect
- xDB
- XM Cloud
Just will share the solution for Simple Injector, because I have the same problem with that, and first I found your post to understand that the problem is the dependency injection and after that I found the solution for the Simple Injector
http://www.saschaheyer.de/wffm-and-simple-injector/