Speed up project load time for Helix and TDS based Solution

Me and my colleague have been talking and we were noticing VS Hang during branch switch for one of our Helix based solution. Which has the lot of TDS Projects. We noticed when we switch branch. TDS Code generation starts code generation. Which Technically we don’t want. We want it when we do some item level changes. If you are also noticing similar challenge. Then TDS Classic team has solution for you, Which you might have not been aware/thought of.

Go to Visual Studio – Options and from here – You can configure it as per your need. And it will be persisted across all Visual Studio Instances as it is Global setting.

Read more : https://hedgehogdevelopment.github.io/tds/chapter4.html “TDS Classic Options Window”

Helix, 8.2 DI and An error occurred when trying to create a controller of type ‘ScBasics.Feature.Nav.NavController’. Make sure that the controller has a parameterless public constructor

Challenge:

The best part of our lives is, Whatever/However experience you are you will face one exception/error which challenges your experience. And that’s what happened with me recently. And I am sure you agree — That’s when your basics come to rescue — Same was the case in my case.

We were deploying Helix based solution which was working like a charm in local. [In case you haven’t heard of Helix/Habitat yet – Which I don’t expect to be the case. But If heard and not explored/clear on it. Then this post might help you]

https://i0.wp.com/www.ybrikman.com/assets/img/blog/docker/say-works-on-my-machine.jpg

But as you know “life is not as easy as it seems to be” When we deployed it on Dev/QA environment. We met following error:

Sitecore.Mvc.Diagnostics.ControllerCreationException was unhandled by user code
  ControllerName=Navigation
  HResult=-2146233088
  Message=Could not create controller: ‘Navigation’.
The item being rendered is: ‘/sitecore/content/SCBasics/Home’.
The context item is: ‘/sitecore/content/SCBasics/Home’.
The current route url is: ‘{*pathInfo}’. This is the default Sitecore route which is set up in the ‘InitializeRoutes’ processor of the ‘initialize’ pipeline.
  Source=Sitecore.Mvc
  StackTrace:
       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)
       at Sitecore.Mvc.Pipelines.Response.RenderRendering.ExecuteRenderer.Process(RenderRenderingArgs args)
       at (Object , Object[] )
       at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
       at Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain)
       at Sitecore.Mvc.Pipelines.PipelineService.RunPipeline[TArgs](String pipelineName, TArgs args)
       at Sitecore.Mvc.Pipelines.Response.RenderPlaceholder.PerformRendering.Render(String placeholderName, TextWriter writer, RenderPlaceholderArgs args)
       at (Object , Object[] )
       at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
       at Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain)
       at Sitecore.Mvc.Pipelines.PipelineService.RunPipeline[TArgs](String pipelineName, TArgs args)
       at Sitecore.Mvc.Helpers.SitecoreHelper.Placeholder(String placeholderName)
       at ASP._Page_Views_Website_Layouts_Default_cshtml.Execute() in c:\…..\Website\Views\Website\Layouts\Default.cshtml:line 38
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
       at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
       at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
       at System.Web.Mvc.Html.PartialExtensions.Partial(HtmlHelper htmlHelper, String partialViewName, Object model, ViewDataDictionary viewData)
       at Sitecore.Mvc.Presentation.ViewRenderer.Render(TextWriter writer)
  InnerException:
       HResult=-2146233079
       Message=An error occurred when trying to create a controller of type ‘SCBasics.Feature.Navigation.Controllers.NavigationController’. Make sure that the controller has a parameterless public constructor.
       Source=System.Web.Mvc
       StackTrace:
            at System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType)
            at System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName)
            at Sitecore.Mvc.Controllers.SitecoreControllerFactory.CreateController(RequestContext requestContext, String controllerName)
       InnerException:
            HResult=-2147467261
            Message=Context is null
            Source=Glass.Mapper
            StackTrace:
                 at Glass.Mapper.AbstractService..ctor(Context glassContext) in c:\TeamCity\buildAgent\work\8567e2ba106d3992\Source\Glass.Mapper\AbstractService.cs:line 103
                 at lambda_method(Closure , ServiceProvider )
                 at Sitecore.Mvc.Controllers.SitecoreDependencyResolver.GetService(Type serviceType)
                 at System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType)
            InnerException:

You might say that’s easy “controller has a parameterless public constructor.” – Just add this and it should work 🙂 But same code works in local, and second thing is we are using Sitecore 8.2 DI for controllers. And in that case, it is not required to have parameter less public constructor. And if it is same error for you, it means that, your DI is not working.

You are also facing same error? Then this post might help you!

Solution:

So, as every developer on this earth does, We also did a quick Google search and found following links, which were helpful:

  1. http://sitecore.stackexchange.com/questions/2929/no-parameterless-constructor-defined-for-this-object-after-upgrade-to-sitecore8 – dnstommy’s reply gave us a hint that our DI is not working
  2. Apart from this there were no any good results on web. So, now it was time to look back in code and see how things laid down and figuring out what’s going on

Troubleshooting process:

public static class ServiceCollectionExtensions
  {
    public static void AddMvcControllersInCurrentAssembly(this IServiceCollection serviceCollection)
    {
      AddMvcControllers(serviceCollection, Assembly.GetCallingAssembly());
    }
// Removed for simplicity
 public static void AddMvcControllers(this IServiceCollection serviceCollection, params Assembly[] assemblies)
    {
      var controllers = GetTypesImplementing<IController>(assemblies)
        .Where(controller => controller.Name.EndsWith("Controller", StringComparison.Ordinal));

      foreach (var controller in controllers)
      {
        serviceCollection.AddTransient(controller);
      }
    }
// Removed for simplicity
}
  • Looking at code, it makes sense. But it works in local. But not when deployed. So, after troubleshooting a bit. Thought to log what we get in calling assembly — We also faced challenge here. Sitecore logging will not work at this layer. So, we had to use plain old StreamWriter [You remember, I told. Basics!?]
  • The log results were something like this:
    • In local : In Calling assembly we were getting Feature assemblies
    • In QA/Dev : In Calling assembly we were getting Sitecore.Kernel
  • It was clear, Assembly.GetCallingAssembly() was misbehaving
  • Quick Google search reveled the mystery, GetCallingAssembly works different in Debug and Release mode https://blog.codeinside.eu/2014/10/05/Be-Aware-Of-Asssembly-GetCallingAssembly-Behaviour/
  • In local we are using Debug mode and on QA/Dev – We are using Release mode
  • Root cause “The JIT compiler moves code around to optimize for performance. Small methods (up to about 56 Byte IL-Code if I remember it right) can be inlined where the method call was before. But the compiler does this only in release, not in debug mode. Also when attaching the debugger to our release build the JIT compiler stopped inlining to enable debugging and our bug was gone” : Source : http://www.ticklishtechs.net/2010/03/04/be-careful-when-using-getcallingassembly-and-always-use-the-release-build-for-testing/
  • Last post had an approach — Adding [MethodImplAttribute(MethodImplOptions.NoInlining)] on method — Which somehow didn’t work for us
  • But then thought to look for some better options and we found it!
  • We added one more Service configurator in Foundation which has following code:
namespace SCBasics.Foundation.DependencyInjection.Services
{
    public class RegisterAllFeatureControllers : IServicesConfigurator
    {
        public void Configure(IServiceCollection serviceCollection)
        {
            /* We were facing issue in Release mode
               Which was not resolving  
            */
            serviceCollection.AddMvcControllers("SCBasics.Feature.*");
        }
    }
}
  • Above code, uses an alternate method for adding MVC Controllers and best part of this approach is. You no need to register your controllers, which you added in feature project. This foundation project will automatically do it! [BTW, Nothing is automatic, we wrote one time code for it ;-)]

Happy Coding! 🙂

Quick Helix deployment approach

Challenge:

I have been looking at a why, how we can deploy Helix approached solution without adding lot of tools and complexities. After investing some quality time. Have been able to do it. Few tweaks are required to this process. So, it can be automated. But basic idea should get you going!

Solution:

As you know each Foundation/Feature/Project – might have one web project Files which needs to be deployed to webroot. And TDS Items as well. Let’s look at each of them:

  1. Files : To deploy files, I prefered to use my old and gold – Web deploy! As you know for webdeploy and Visual studio publish for web project to work you need .pubxml and it holds few configurations. To centralize those configurations, here’s what we did:
    1. In Configuration folder created .targets file e.g. scbasics-pubsettings.targets
    2. Which contains publish related configurations  e.g. WebPublishMethod,MSDeployServiceURL etc.
    3. Each Web Project has its own .pubxml file which points to .targets file which we created earlier <Import Project=”..\..\..\..\..\..\Configuration\scbasics-publishsettings.targets” />
    4. So, using above approach, Configurations are centralized. So, in case if you have to change anything. You change it at one place rather than changing lot of places [depends on your feature/foundation/project count]
  2. TDS : We had access of Target server using HTTP. So, we just added required configuration in TdsGlobal.Config for that particular environment. And TDS is smart enough to take care of it! [QUICK UPDATE : 31-AUG-2017 – If you are using TDS Sync over HTTP. Then you can uncheck Build TDS Project for particular build configuration — It will save some time]

I have not been able to hook it with Teamcity and do automated deployment yet. But when I do it using .sln — I can foresee only one challenge — Build ordering – Because your project should be built at last and it should copy root’s Web.Config. But that can be resolved with some ways — Which I’ve left for you! 🙂 Or you know If I spend time on it, will share with you — I expect the same! 😉

One more Helix puzzle resolved!

Happy Deployment! 🙂

Sitecore Helix Basics

Challenge:

Hey Friends, I’m excited to share many of first post of 2017! So, far it has been great year and I know a lot of you are MVP now or MVP Again — Congratulations Very well deserved! – Please make sure you help someone else become one — Because sharing is caring — Nice story

Since last year we have been hearing a lot about Habitat and then Helix and lot of people appreciating what Habitat or Helix is. You also heard/read about it? But:

  • You are afraid of It? Because Habitat solution is huge and you get confused how to set it up. Because it involves a lot of tools to set up e.g. gulp etc. [This is good point to upgrade your web/technology knowledge. It is evolving a lot. All of us accept that FED Technology is seeing lot of huge changes, and .NET Core team is doing super awesome stuff. If you don’t upgrade your self, there are chances of you being dinosaur in this industry]
  • Confused between Habitat and Helix
  • You setup your Habitat solution. But when you opened it. You got overwhelmed?
  • In this process, you don’t know how to get started and what’s the starting path for you to embrace Sitecore Helix?

Then this post is for you — This post will do 95% job to help you getting started on Helix — What about other 5%? — Will share about it before end of this post. So, let’s Helix

Solution:

Before we get further in technical details. Let’s try to understand what is the dictionary meaning of “Helix” – Wiki says “an object having a three-dimensional shape like that of a wire wound uniformly in a single layer around a cylinder or cone, as in a corkscrew or spiral staircase.”

Source : Wiki

It will be great to hear about naming directly from horse’s mouth some day.

Let’s get on point, How I got started on Helix? Exactly in same order:

Okay, Thank you for those resources. But can you please share your basics with me? So, I can get quickly started. Sure, here we go. I will share my learnings and understandings:

  • What is difference between Habitat vs Helix?
    • Helix :
      • Sitecore® Helix is a set of official guidelines and recommended practices for Sitecore Development.
      • Set of architecture conventions and guidelines that describe how to apply recommended technical design principles to a Sitecore project.
      • Secure implementations in a future proof way by architecting them as maintainable and extensible business centric modules
      • Development process recommendations to make it as easy as possible to build, test, extend, and maintain Sitecore implementations
    • Habitat :
      • Habitat is an example project that follows the Helix principles and recommended practices.
      • PLEASE DON’T USE HABITAT AS FOUNDATION/STARTER KIT FOR YOUR NEW PROJECT – HABITAT IS NOT BUILT FOR THAT
  • Why we need Helix?
    • Dependencies : If you look at dependencies, left side-show non helix project — Where any module is talking to any module — And as project becomes huge. No one makes small change with confidence — To make a one line change — Developer/QA/Stakeholders — Have to keep their fingers crossed. And still they have issues and because of it, they either have to miss dinner/lunch/outing with friends/baseball match/cricket match. But when things are done Helix way — right side. There are some standard ways – How each module talks to each other — And that gives everyone full confidence before making any change! — It is simple maths — Invest on strong foundation and take returns in a longer run! dependencies
    • Following diagram, clarifies that — As the project dependencies grow — lot of time spent on coupling rather than feature — and that increase time taken as well!why-helix
  • There are some logical layers defined, and you try to follow it – This image is very self explanatory. You just need to know three things – Foundation, Feature, Project – And each one of them should hold things which suits to their name:layers-basic
  • Benefit of using proposed layers — See this example – When you have multiple sites — They can have all foundational and featured things available! – Standard Sitecore Multisite way of doing things:layer-example
  • Helix also guides you how you need to structure your templates – Which are heart of any Sitecore projects : helix-template-inheritance
  • There are few Helix dependency rules you need to follow — You can break it. But then there is no point in using Helix:helix-rules
    • There is a strict reference hierarchy of module categories. Projects -> Features -> Foundations.
    • Project modules cannot reference other projects, but can reference any Features and Foundations.
    • Feature modules cannot reference any Project modules or other Feature modules. They can reference Foundations
    • Foundations can only reference other Foundations.
  • How to add advance things like GlassMapper, Sitecore 8.2 DI, Code Gen, TDS : Good question, We spend sometime and made it possible. This thread might help you get quick started [If not, give me a shout] : http://sitecore.stackexchange.com/questions/4370/few-questions-related-to-helix
  • If you think — There are a lot of Manual steps involved in adding a feature and foundation – Look at the great work done by Marc : http://blog.marcduiker.nl/2016/12/28/hands-on-with-sitecore-helix-using-powershell-add-module.html
  • Akshay also did good stuff taking this forward for initial setup : https://www.akshaysura.com/2017/01/21/habi-what-a-tat-create-a-sitecore-helix-solution-from-scratch-using-powershell/

It seems a lot? I know, I realized after writing. But I wanted to share all our basics with you. Because when we had to start, we were literally struggling to get started. But now, we did it. Thought to share with you. So, it saves some of your time, which you can spend with your loved ones or for other important things!

In Summary,

  • Helix is not a rocket science, It is same Sitecore code. But how and where you write it — That is standardized by Sitecore — As Sitecore support team is also using same methodology. So, it is easy for them to help you troubleshoot
  • Just imagine, your company adopts Helix and all projects which your company does, does in Helix [Including your project :-)]. After sometime, any developer can jump from one project to another project – Project on boarding will be super easy — (S)he just need to know business domain. I have seen lot of project leads, don’t allow new developers on board even though they can support more developers in project — Because of project on boarding — Helix helps us all speak same language!
  • “Helix is like Maths, Once you get it. You enjoy it and would like to do it again and again”

I am sure you must be curious t o know what else 5% I need to do to get 100% knowledge on Sitecore Helix? It’s simple — Get your hands on it. Coding is like swimming. You have to dive in to swim/code!

It was fun to work along with Muktesh and Varun on Helix basics! Thanks to all folks who already wrote about it, which helped us to get it started sooner!

Good read:

  1. http://helix.sitecore.net/
  2. http://www.sugcon.eu/wp-content/uploads/2016/05/Introducing-Sitecore-Habitat.pdf
  3. http://www.sugnl.net/~/media/SUGNL/Meetings/Developer%20track%2019%20oktober%202016%20Achmea/Downloads/SUGNL%20Meeting%20Achmea%2020161019%20%20Robbert%20Hock%20%20Symposium%20recap.pdf
  4. https://www.dynatrace.com/blog/adding-the-how-to-what-for-sitecore-helix-test-automation/
  5. http://www.hhog.com/blog/sitecore-helix-fxcop-rules/

Happy Sitecoring! 🙂