Sitecore Xperiences - The things I've seen as a Sitecore Developer

Powershell script to find TDS files with length error

Powershell script to find TDS files with lenght error

A very well described problem with TDS is the File Name length error. This article from Hedgehog brings everything you need to know about the issue itself, and how to work it out. The solution is to use the “Alias” TDS feature to cut down the file path length.

For instance, if you have an item with a very long name such as “Subpage with Left Rail Without Footer”, you could choose an Alias as “sub3″ and save 33 characters. Of course, your original item name is preserved, as this only applies to the file system.

In short:

  • File path should not exceed 260 chars
  • Folder path should not exceed 248 chars

What causes and what to do about

  1. You have cloned the repository into a folder with a too large name
    What to do about: 

    1. Make sure you have something short like:
      instead of
      C:Source ControlMy Client Name Is LongMy Long Project Name
  2. TDS project name is too wide – due to the Helix standard TDS projects can have longer names (Eg: MyProject.Foundation.DependencyInjection.Master)
    What to do about:

    1. New projects: avoid long names (Eg: DI instead of DependencyInjection)
    2. Existent projects:
      1. Use the Powershell script to find long paths and apply Aliases
      2. Be proactive to apply Aliases to TDS long names
  3. The Sitecore Item Path added to TDS (including the item itself) is too long
    What to do about:

    1. Use the Powershell script to identify long paths, then apply a TDS Alias to each item that makes it longer
    2. EG: this path
      /sitecore/content/mywebsite/This page has a big name/But this page also has a big name/NotToBlame
      has 2 problematic items:

      1. “This page has a big name”
      2. “But this page also has a big name”
    3. Those 2 items must be added to TDS and have their “File System Alias” setup to something smaller

Powershell script

When a certain environment has this issue, make sure to follow the steps described earlier. However, to execute Step 3 you should first discover what items are problematic.

To quickly obtain such a list, use the following Powershell script:

# Script Setup
$pathToScan = “D:srcABC”;
$outputToCsv = $false;
$outputToPrompt = $true;
$maxLength = 225;


if ($pathToScan.IndexOf(“src”) -eq -1){
$pathToScan = “$pathToScansrc”;

# Get all TDS folders
$tdsFolders = Get-ChildItem -Path $pathToScan -File -Recurse | Where-Object {($_.FullName -like ‘*.Master*’) -or ($_.FullName -like ‘*.Core*’)} | Where-Object {($_.FullName -notlike ‘*bin*’)};
#$tdsFolders = Get-ChildItem -Path $pathToScan -Directory -Recurse;

# Add properties
foreach ($folder in $tdsFolders){
$folder | Add-Member PathLength $folder.FullName.Length;

# Sort
$tdsFoldersSorted = $tdsFolders | sort FullName | sort PathLength -Descending;

# Get Max Length to filter those that will not match
#$maxLength = Read-Host -Prompt ‘Max Length allowed';
$tdsFoldersToShow = $tdsFoldersSorted | Where-Object {$_.PathLength -gt $maxLength};

# Output Loop
$fileName = “$PSScriptRootbeyond $maxLength.csv”;
$csvText = “”;
if ($outputToCsv){
$csvText = “$($csvText)Length,FullName`n”;
#Add-Content -Path $fileName -Value “Length,FullName”;
if ($outputToPrompt){

foreach ($folder in $tdsFoldersToShow){
if ($outputToCsv){
$csvText = “$($csvText)$($folder.PathLength),$($folder.FullName)`n”;
#Add-Content -Path $fileName -Value “$($folder.PathLength),$($folder.FullName)”;
if ($outputToPrompt){

if ($outputToCsv){
Add-Content -Path $fileName -Value $csvText;
Write-Output(“File $fileName saved”);


  1. Open the script in Powershell ISE as Administrator
  2. Setup script changing variables at the top:
    1. $pathToScan – should point to your git folder
    2. $outputToCsv – Set as $true if you want the script to create a CSV file with results, $false otherwise
    3. $outputToPrompt – Set as $true if you want the script to display results at prompt, $false otherwise
    4. $maxLength – Max length tolerated to a TDS item path – the script will list everything that goes beyond this vale
  3. Run the script
  4. Use the list obtained to apply instructions Aliases, making paths shorter
Publicado em Powershell, TDS

Custom Reset Layout in Content and Experience Editor Modes


Recently I had to customize the code that triggers when a Reset Layout is executed. If you ever had to attach any code to it, this post is for you!

You know, that sympathetic prompt:

Reset Layout Prompt

The first thing you need to know is that Content Editor and Experience Editor does that differently, so let’s go for them:

Round 1 – Content Editor

Content Editor uses a command for that (pagedesigner:reset), which is natively implemented by the class Sitecore.Shell.Applications.Layouts.PageDesigner.Commands.Reset. We first need to create a class that will inherit from the original, so we don’t lose the original behavior, and implement our custom logic on it.

Create a Command class like this:

using System.Web.Mvc;
using Sitecore.Shell.Applications.Dialogs.ResetLayout;
using Sitecore.Web.UI.Sheer;

namespace MyProject.Commands
    public class ResetLayoutCommand : Sitecore.Shell.Applications.Layouts.PageDesigner.Commands.Reset
        protected override void Run(ClientPipelineArgs args)
            // Runs the default behaviour

            // Skips if the Reset Layout prompt is not submited or results is undefined
            if (!args.IsPostBack || string.IsNullOrEmpty(args.Result) || args.Result == "undefined")

            // Takes the item that has been reset
            var itemReset = DeserializeItems(args.Parameters["items"])[0];

            // And here is where your custom logic will be implemented
            // .....

Then we override the default command with our class in a config patch like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="">
            <command patch:instead="*[@name='pagedesigner:reset']" name="pagedesigner:reset" resolve="true" 
                type="MyProject.Commands.ResetLayoutCommand, MyProject"/>

And this is how we run the first leg. But it is not over yet, let’s go for…

Round 2 – Experience Editor

Experience Editor, on the other hand, uses a different approach for that. It has a request node named “ExperienceEditor.ResetLayout.Execute” under <sitecore.experienceeditor.speak.requests> that we need to replace. This request node is implemented by the native class Sitecore.ExperienceEditor.Speak.Ribbon.Requests.ResetLayout.Execute, which again we are going to inherit.

So our Request class will be like this:

using System;
using System.Web.Mvc;
using Sitecore.Diagnostics;
using Sitecore.ExperienceEditor.Speak.Attributes;
using Sitecore.ExperienceEditor.Speak.Server.Responses;
using Sitecore.Shell.Applications.Dialogs.ResetLayout;

namespace MyProject.ExperienceEditor
    public class ResetLayout : Sitecore.ExperienceEditor.Speak.Ribbon.Requests.ResetLayout.Execute
        [HasItemPermissions(Id = "{BE98D7F0-7404-4F97-8E4C-8FEF4ACA5DA3}", Path = "/sitecore/content/Applications/WebEdit/Ribbons/WebEdit/Advanced/Layout/Reset")]
        public override PipelineProcessorResponseValue ProcessRequest()
            // Instantiates the returning object and 
            var processorResponseValue = new PipelineProcessorResponseValue();

                // Executes the default RESET LAYOUT process
                processorResponseValue = base.ProcessRequest();

                // Takes the item that has been reset
                var itemReset = RequestContext.Item;

                // And here is where your custom logic will be implemented
                // ..... (OF COURSE, DON'T DUPLICATE YOUR LOGIC!)
            catch (Exception e)
                    $"[ResetLayout] Cannot execute post Layout Reset operations to item '{RequestContext.Item.Paths.Path}'", e, GetType());
            return processorResponseValue;

And finally we patch it again with a config file like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="">
            <request patch:instead="*[@name='ExperienceEditor.ResetLayout.Execute']"
                type="MyProject.ExperienceEditor.ResetLayout, MyProject" />

And that’s all… You now have your custom code being triggered by both Content Editor and Experience Editor!

Publicado em Content Edition Experience, Development, Experience Editor

Sitecore 9 Update 1 – Bug saving Shared Layout in Experience Editor


A few weeks ago, while upgrading one of at Nish Tech’s early-stages projects into Sitecore 9 Update 1, a very strange behavior when you try to do a very simple task: edit a Shared Layout of a page in Experience Editor.

When you try to do that, the infamous screen “Layout not Set” shows right after saving.

Sitecore 9 Bug

Initially, I observed that when saving in a _Standard Values, but later I noticed it can also happen with ordinary items. If you want to see how to reproduce the error, check this video.

Interesting enough, when you look at your Layout and Final Layout fields in Raw mode, you notice that the Shared Layout has a value such as:

<r xmlns:p=”p” xmlns:s=”s” p:p=”1″><d id=”{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}”><r uid=”{597C17AD-DEF3-4947-BE5B-4104A2143F17}” p:after=”*[1=2]” s:id=”{493B3A83-0FA7-4484-8FC9-4680991CF743}” s:ph=”/main/centercolumn/content” /></d></r>

Which seems to have a more appropriate syntax to be in the Final Layout field instead, as you can check if you match this against the original value:

<r xmlns:xsd=””><d id=”{FE5D7FDF-89C0-4D99-9AA3-B5FBD009C9F3}” l=”{14030E9F-CE92-49C6-AD87-7D49B50E42EA}”><r ds=”” id=”{885B8314-7D8C-4CBB-8000-01421EA8F406}” par=”” ph=”main” uid=”{43222D12-08C9-453B-AE96-D406EBB95126}” /><r ds=”” id=”{CE4ADCFB-7990-4980-83FB-A00C1E3673DB}” par=”” ph=”/main/centercolumn” uid=”{CF044AD9-0332-407A-ABDE-587214A2C808}” /><r ds=”” id=”{493B3A83-0FA7-4484-8FC9-4680991CF743}” par=”” ph=”/main/centercolumn/content” uid=”{B343725A-3A93-446E-A9C8-3A2CBD3DB489}” /></d><d id=”{46D2F427-4CE5-4E1F-BA10-EF3636F43534}” l=”{14030E9F-CE92-49C6-AD87-7D49B50E42EA}”><r ds=”” id=”{493B3A83-0FA7-4484-8FC9-4680991CF743}” par=”” ph=”content” uid=”{A08C9132-DBD1-474F-A2CA-6CA26A4AA650}” /></d></r>

Sitecore Helpdesk heroes

Then I reported the issue to our amazing Sitecore Helpdesk, who after a couple weeks came out with a bugfix, that now I want to share with our Sitecore Community.

I would like to thank the whole gang of superheroes at Sitecore Helpdesk, for providing this good HotFix in a proper time and allowing me to share it, in special to Igor DenisenkoPavel Ivashchenko and Ielyzaveta Kalinchuk, the good guys who replied to my ticket. You are awesome, mates!

The cure: HotFix 203387

You can find the hotfix at this link.

  • Please be aware that the hotfix was built specifically for Sitecore XP 9.0 rev. 171219 (Update-1)! You should not install it on other Sitecore versions or in combination with other hotfixes unless explicitly instructed by Sitecore Support;
  • Note that you need to extract ZIP file contents to locate installation instructions and related files inside it.

If you have anything to add on this, please drop a comment and let me know!

Publicado em Bug fixing, Experience Editor, Support Ticket, Uncategorized

Rodrigo Peplau Wins Sitecore “Most Valuable Professional” Award

Elite distinction awarded for exceptional contributions to the Sitecore ecosystem

FLORIANÓPOLIS – SC, Brazil – January, 31th 2018 – Nish Tech today announced that Suresh Devanan, Himadri Chakrabarti, Rodrigo Peplau, and José Neto have all been named a “Most Valuable Professional (MVP)” in the Technology Category by Sitecore®, the global leader in experience management software. These four recipients are part of an elite group of only 208 Technology MVPs worldwide to be named a Sitecore MVP this year.

Now its 12th year, Sitecore’s MVP program recognizes individual technology, strategy, and commerce advocates who share their Sitecore passion and expertise to offer positive customer experiences that drive business results. The Sitecore MVP Award recognizes the most active Sitecore experts from around the world who participate in online and offline communities to share their knowledge with other Sitecore partners and customers.

“I am honored to be named a Sitecore MVP for the fourth year in a row.  I am very proud of Nish Tech’s recurring MVPs (Himadri, Rodrigo and myself) for maintaining our MVP status by being actively involved in the Sitecore Community, and excited for our most recent hire Jóse Neto, as he earns MVP designation for the first time.  We strive to share this expertise with our clients and the Sitecore community.”, stated Suresh Devanan, President of Nish Tech.

Nish Tech excels at creating efficient, flexible digital solutions to execute web marketing strategies and eCommerce plans. Through system integrations of best-in-class technology, we strive to perfect your web presence.

“The Sitecore MVP awards recognize and honor those individuals who make substantial contributions to our loyal community of partners and customers,” said Pieter Brinkman, Sitecore Senior Director of Technical Marketing. “MVPs consistently set a standard of excellence by delivering technical chops, enthusiasm, and a commitment to giving back to the Sitecore community. They truly understand and deliver on the power of the Sitecore Experience Platform to create personalized brand experiences for their consumers, driving revenue and customer loyalty.”

The Sitecore Experience Platform™ combines web content management, omnichannel digital delivery, insights into customer activity and engagement, and strategic digital marketing tools into a single, unified platform. Sitecore Experience Commerce™ 9, released in January 2018, is the only cloud-enabled platform that natively integrates content and commerce so brands can fully personalize and individualize the end-to-end shopping experience before, during, and after the transaction. Both platforms capture in real time every minute interaction—and intention—that customers and prospects have with a brand across digital and offline channels. The result is that Sitecore customers are able to use the platform to engage with prospects and customers in a highly personalized manner, earning long-term customer loyalty.

Since 2011 Nish Tech has been a digital agency who strives to help our clients gain a competitive advantage in their industry. Using enterprise technology and big data we deliver personalized web experiences for our clients’ site visitors. We focus on understanding our clients’ business needs and finding ways to meet them. For more information, please visit for more information.

Publicado em MVP

Still have ‘ERROR SCRIPTDOM NEEDED FOR SQL PROVIDER’ when installing Sitecore 9?


My friend Daniel Govier was having the following error when installing Sitecore 9 Update 1 using XP0:

[————————————————————————————— InstallWDP : WebDeploy —————————————————————————————-]
[WebDeploy]:[Path] <C:Program FilesiisMicrosoft Web Deploy V3msdeploy.exe>
At <C:Program FilesWindowsPowerShellModulesSitecoreInstallFramework1.1.0PublicTasksInvoke-CommandTask.ps1:31> char:13
+ & $Path $Arguments | Out-Default
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (Error Code: ERR…OR_SQL_PROVIDER:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError

More Information: The SQL provider cannot run because of a missing dependency. Please make sure that Microsoft SQL Server Transact-SQL ScriptDom is installed. Learn more at:

Following the traditional path of any Sitecore developer, we googled that error and ended up in this blog article from Naveed Ahmad. Problem is that Daniel had already followed his article and installed SQL Server Data-Tier Application Framework, Transact-SQL ScriptDom, and the System CLR Types.

But just like Naveed, that doesn’t work, but we found a different solution instead of modifying Windows Registry.

Do you guys think there are any issues with the following approach?

Register ‘Microsoft.SqlServer.TransactSql.ScriptDom.dll’

More googling sent us to this article. The valid answer is that we still need to register ‘Microsoft.SqlServer.TransactSql.ScriptDom.dll‘. However, of course, the answer was pointing to local folders, so we need to:

  1. Find out where ‘gacutil.exe’ is. It can be somewhere like ‘C:Program Files (x86)Microsoft SDKsWindowsv10.0AbinNETFX 4.6.2 Tools‘ as shown at the article, but it can be somewhere else. Use Windows Explorer to find it, and if you have multiple entries use the one that looks more recent.
    1. Copy the whole path to it – we will need it in step 3
  2. Find your ‘Microsoft.SqlServer.TransactSql.ScriptDom.dll‘ – again look for the newest version
    1. Copy the whole path again to use in step 3
  3. Open your command prompt and type:
    1. cd “Path_from_step_1” (enter)
    2. gacutil” /i “Path_from_step_2Microsoft.SqlServer.TransactSql.ScriptDom.dll” (enter)

If everything goes right your library is now registered on GAC and you will be able to install Sitecore 9!

Publicado em SIF, Sitecore 9

Site-specific RichText Editor Profiles – custom Source in native RichText fields

Site-specific RichText Editor Profiles - custom Source in native RichText fields

Everybody knows how to select different Editor Profiles using the Source property in a Rich Text field. Out of the box, you can only pass a hardcoded path to the Editor Profile, making the template totally linked to one and only one Profile.

Rich Text Source property


But what if we could make this dynamic and site-specific? That way, the same template could present different Editor Profiles for different websites.

Something like this:

Rich Text Site-specific Source property

Then at each of your websites you can have your own Source definition item:

Site-Specific RichText Editor Source


Site-specific field Sources

If you ever happen to play with Habitat you might have noticed it has a Multisite Module, that implements something similar for Component’s Datasources. My solution is based on that, working perfectly with Droplists and other listing fields.

Not so fast…

But unfortunately, it doesn’t work with the RichText field since it is attached to the “<getLookupSourceItems>” pipeline. The RichText field has a different implementation which does not trigger this pipeline.

Custom Source for Rich Text fields!

So how can this be customized? After a long web research and decompiling Sitecore DLLs, here is what I came out.

If you take a look at the Field item definition under core:/sitecore/system/Field types/Simple Types/Rich Text you will notice it has the following content at the Control field:

Rich Text definition item

I found out that this is similar to how a Command is registered, however no such a Command called “content:RichText” exists anywhere at my Sitecore configs. This is actually registered by the following config entry:

    <source assembly="Sitecore.Kernel" namespace="Sitecore.Shell.Applications.ContentEditor" prefix="content" mode="on"/>

The secret here is the prefix=”content” which is used as the basis to register the whole namespace, taking classes dynamically by its name (“RichText” in this case).

Step 1 – Extend native class

Create your class that extends the Rich Text field – we will inherit from the original “Sitecore.Shell.Applications.ContentEditor.RichText” and only overwrite the Source property. Notice that I am re-using the same code used at my <getLookupSourceItems> to apply the same logic to the Rich Text field.

using Sitecore.Diagnostics;
using Sitecore.Pipelines.GetLookupSourceItems;
using Website.Core.Multisite.Pipelines;
namespace Website.Core.Fields
   public class RichText : Sitecore.Shell.Applications.ContentEditor.RichText
     /// <summary>Gets or sets the source.</summary>
     /// <value>The source.</value>
     public new string Source
       get { return GetViewStateString(nameof(Source)); }
         Assert.ArgumentNotNull(value, nameof(value));
         // Reuse the same Pipeline implementation here as at my <getLookupSourceItems> pipeline
         var processor = new LookupItemsFromField();
         var args = new GetLookupSourceItemsArgs()
           Source = value,
           Item = Sitecore.Context.ContentDatabase.GetItem(ItemID)
         value = args.Source;
         SetViewStateString(nameof(Source), value);

Step 2 – Patch Sitecore to use our custom class

Now we need to patch Sitecore. Our custom class needs to be registered BEFORE the native one so it can assume its place.

<?xml version="1.0"?>
  <configuration xmlns:patch="">
        <source patch:before="source[@namespace='Sitecore.Shell.Applications.ContentEditor']" mode="on" namespace="Website.Core.Fields" assembly="Website.Core" prefix="content"/>

Now that you can intercept the native RichText implementation, you can implement your own logic for Source resolving!

You know a better way of doing this? Please let me know!

Publicado em Content Edition Experience, Experience Editor, Richtext Editor

A Helix/TDS Sitecore Solution you can use

So that finally happened (sorry for the delay!): source code for the Helix/TDS solution presented at the two Sitecore Usergroups – Brazil (watch video) and Cincinnati – is available for everyone to be used.

  • A Helix-Compliant solution, not based in a Habitat but with various “inspirations” (stealing) from there
  • TDS is used to both serialization and publishing to the Website folder
  • The “Foundation” Layer is renamed to “Basis” for alphabetic sorting purposes
  • Runs in Sitecore 8.2 update 3 – but can be easily updated to Sitecore 9 IR
  • Fresh installed with SIM and populated with Visual Studio+TDS thru Solution Deploy command

To access the code check this Git repository:

Feel free to contribute the way you want!

Publicado em Helix, SUG

Prevent orphan components in Experience Editor when deleting composed components


If an editor deletes a component in Experience Editor and that component has inner components, only the outer component will be actually deleted from the page rendering. Inner components will not show anymore (and often Content Editors will be happy), so why would that be a problem?

The problem

Take for instance this set of renderings of a certain page:

Orphan Renderings-before

If in Experience Editor someone tries to delete it:

Remove Components

The result will be a “ghost” orphan item, which will not render when the page loads because its placeholder does not exist anymore.

Orphan Renderings-after

That rendering will continue at the page rendering, being either forgotten forever or re-appearing when someone tries to add a new Carousel to the same Full-Width Container placeholder.

Not just me

I’ve seen more people concerned with that – such as the author of this question at Sitecore Exchange – and some other people suggested possible solutions.

One approach I tried was to follow this blog post by Mike Tschida and implement a pipeline processor to clean-up the Page Rendering, removing orphan components when the page is saved. That would be perfect, however during development or debugging, it is very common to temporarily move a component to an unexistent placeholder to make it vanish from the page. In cases like that, the component would be deleted, which is not desired.

Acting at the other end

So what if, instead of acting later at the server, we stop content editors at the root of the problem: the Experience Editor? At that case, when an editor attempts to delete a component which has inner components, a prompt like this would be displayed. In order to delete the outer component, the editor now needs to delete the inner components first.

Orphan Renderings-prompt

Inspired by this simple Stack Overflow post,  in which the author was looking for a way to simply ask for a confirmation before deleting a component, I ended up with the solution below.

Nip the evil in the bud

The deletion of a component is handled by javascript code located at sitecoreshellApplicationsPage ModesChromeTypesRenderingChromeType.js – more specifically at the deleteControl method. Our fix will comment out the original code (I will leave there for future reference in case of an upgrade) and add the following code:

    deleteControl: function () {
        var canDelete = this.canDeleteControl(;
        if (canDelete === false) {
            alert("Please delete inner controls before deleting this.");
            return false;
        var placeholder = this.getPlaceholder();
        if (placeholder) {
            return true;
        return false;

Along of course with the new canDeleteControl method, which does the trick of verifying if the component attempted to be deleted has inner components.

    canDeleteControl: function (chrome) {
        var canDelete = true;
        var childChromes = chrome.getChildChromes();
        for (var i = 0; i < childChromes.length; i++) {
            if (childChromes[i].type.key() == "placeholder") {
                canDelete = this.canDeleteControl(childChromes[i]);
                if (canDelete === false)
            else if (childChromes[i].type.key() == "rendering") {
                canDelete = false;
        return canDelete;

And that’s all we need! Replace this file in all instances, clean up your browser caches and don’t worry about orphan components anymore!

Publicado em Content Edition Experience, Development, Experience Editor, Uncategorized

How we won the Hackathon

How we won

dxaHackthon-AwardThe famous Sitecore Hackathon is an annual programming contest, where teams should put together, within 24 hours, a piece of software for Sitecore in one of the available categories. At this fourth edition in 2017, there were four categories: Azure PaaS Module, Sitecore Experience Accelerator, Habitat Module and Data Exchange Framework – this last the one the Go Horse Team picked.

92 teams participated with members from 26 different countries!

This was our first participation, so we were not sure what to expect. Like any other professional development we execute, we made sure to read all requirements and rules and to strictly obey to everything: deadlines, supporting documentations, Youtube video, the software itself, etc. And yes, that was important, as we’ve seen so many teams being declassified by not following just a small portion of these.

The Go Horse Team

Our team was composed by Anderson Fortaleza, João Amancio Neto and Rodrigo Peplau (myself). We joined together because at that time we were colleagues at Nonlinear Creations in Florianópolis, Brazil. Nowadays João is at Virtual Affairs in Netherlands, and I am working at Nish Tech Inc.

Go Horse WhiteBut what exactly is “Go Horse”?

The Go Horse Process is a joke in the form of a software development anti-pattern. Despite everybody knows its practices are not to be followed, the funny part is that at some point in our career, everyone had to “follow” it to deliver in time. Some of its axioms are:

  1. I think therefore it’s not Go Horse - In Go Horse you don’t think, you do the first thing that comes to your mind. There’s not a second option as the first one is faster;
  2. There are 3 ways of solving a problem: the right way, the wrong way and the Go Horse way which is exactly like the first one but faster. Go Horse is faster than any development process you know

These funny principles are pretty self-explanatory and also gives a sense of our mindset for this 24 hours contest: we got no serious ambitions, we were there just for fun, we had to be “pragmatic” but deliver something functional within the deadline.

Choosing the subject

Maybe one of the most important steps, if not the most important, was to select the subject. This step will define if you’ll have a good chance to win or if you’ll fail miserably. The first thing we made was to take our team out of the computer and go to a place where we could brainstorm.

Next, we got to measure our team and the individual skills of each member. Maybe a member of your team masters Azure technologies while other is good at doing SPEAK interfaces. During brainstorming, we wrote down any ideas (bad, good, mild) that came to our mind based on every subject of the contest. We opted as individuals to not be afraid of suggesting dummy ideas, which encouraged the whole team to not be afraid as well. Remember: from stupid ideas, good ones can come forth.

We ended up with the idea of using the Wikipedia API to generate content inside Sitecore, using Data Exchange Framework. Of course, other suggestions came before, but we decided this would be a simple one and easy to execute. One of the team members had already done some integration with Wikipedia’s API before so he was familiar with that. Other member had already implemented some SPEAK interfaces before. What remained? Learning Data Exchange Framework.

Some important things at this stage:

  • Avoid spending more than 1 hour to choose your subject. It is a 24 hours competition, and the software itself is only part of the delivery. Every minute is of much importance;
  • Don’t be too ambitious. Again, the short time to implement won’t let you much time to refinements. It’s better to deliver something simple but that works, then having to deliver something unfinished or buggy.

Execution: Work distribution and Teamwork

We choose our theme, made sure every team member was comfortable with that. What now? Let’s start to plan the execution. Who is going to do what? You don’t want to have in the middle of the Hackathon somebody in your team uncomfortable with the plan and willing to change everything. It’s the receipt to fail miserably.

In our case, I was already experienced with SPEAK, so I got responsible for the interfaces, which took most of my time. Anderson and João took the responsibility to learn Data Exchange Framework, understand how it works and come up with technical solutions that I would be binding together with the interface. From time to time, we stopped our work for a quick desk check, in a way that the whole team is aligned: I got to understand how the framework works, they got find solutions to our software needs such as how to programmatically trigger data importation.

Take a rest! It’s important

It was also very important to plan and optimize our team member’s presence. 24 hours is a little time to develop a software, but is time enough for people to get tired, and we don’t want everybody sleeping at the same time. So what we did was to plan our rests in such a way that there’s always someone producing. Honestly SPEAKing I tried to sleep but I couldn’t, my mind couldn’t stop scanning all gaps and possible flaws, so I took the time to lay down, rest my body and keep on planning and projecting.

Supporting material

As previously described at this post, the software itself was only part of the whole deliverable. Along with that, we had to prepare 1) Installation instructions (1-2 pages); 2) Module documentation (2-5 pages); 3) A video explaining the module (2-10 minutes). These tasks seems trivial, but they also demand strict attention as they count as much as the software itself. We split these tasks into our team members, each of us doing one of these.

Final touches

When everything was pretty done we still had about 1 hour to deliver, so we concentrate our efforts to revise everything. Members started to check each other’s work: does the documentation makes sense? Is there any typo? Is that covering everything? Is the module installing and working in a vanilla solution? Everything should be well aligned and ready for deployment.

Respect the deadlines!

We ended up uploading our work 20 minutes before the deadline. That is also something extremely important to respect, as the judges are not tolerant to delays. Our friends from the “Works on My Machine” team took more than it should to deliver and had their Dropbox access cut in the middle of the upload, which is frustrating after so many hours of hard work.

Judges Feedback

Since that was our first participation, we were not expecting to win. Surprise, we have been announced the winners, with very flattering feedbacks from the jury.

WikiDX - Judges feedback

Main lessons extracted from their feedbacks:

  • Choose something with a practical use. It is ok to implement an abstract case study, but if your module have a real life use, it may help judges to understand it, which can potentially call their attention to your team;
  • Be respectful to the category you chose. No matter what category you picked, someone have implemented the base software you will work to extend. Respect its principles and best practices, implementing something that creators will be glad to see.

Our module – WikiDX

Resulting module is called WikiDX and is available to download at the Marketplace – check it out!

Next Year?

Now that members of the Go Horse team are not working at the same company, will they be at the next contest? Of course we will! We need to defend our belt and have fun together again! While João is in Netherlands, and thus will have to join us remotely, myself and Anderson are still living at the same city, so we plan to get together for the next effort and repeat the good work.

What would we make different?

We were newbies and didn’t know what to expect. Our preparation was close to zero, we just got our own professional experiences and a lot of curiosity. For the next year we plan to have a better pre-Hackathon preparation: getting familiar to existent categories, getting to know for instance Sitecore on Azure, SXA in deep, etc. But it is also important to keep an eye at the new modules Sitecore launches, as new categories can arise. Data Exchange Framework for instance, was a new category this year, and has been released just a few months before the Hackathon. As a result of this preparation we may end up with a collection of knowledges and code snippets, which could be very helpful to a smoother execution.

Publicado em Uncategorized Marcado com:

WFFM – Sitecore Context Item NULL inside a Save Action


Business requirements

There is a use case in one of our clients at Nish Tech, where a WFFM form, with a Submit E-mail Save Action, is supposed to be reused at several different parts of the website. It should have the same fields and look & feel at every place we want to reuse it, the only difference would be that the e-mail would be submitted to different addresses depending on what page the form is located.

The pages where this form will be allowed are what we call “Communities”. Each of them has a couple of fields with e-mails (Eg: Sales E-mail, Human Resources E-mail) from which we wanted to have WFFM looking for, instead of using the one hardcoded at the WFFM itself.

One may ask: why not duplicate the WFFM form and hardcode a different e-mail for each page we need? The answer is plenty clear: we will have more than 80 communities, and growing. That would mean more than 80 duplications of the WFFM form, which sound quite abusive. If we happen to need some kind of maintenance at these forms, this would be a nightmare.

The resulting implementation will be subject of a future blog post, this one in particular will focus in a specific challenge: how to access the Sitecore.Context.Item inside a WFFM Save Action.

Technical challenge

So the idea is that WFFM should look into a field at the item where it is located, grabbing the destiny e-mail from there instead of the hardcoded e-mail at the WFFM Form itself. To achieve this we will need to access the current context item (Sitecore.Context.Item), which surprisingly is not available inside a Save Action, as confirmed by Sitecore in a Helpdesk ticket we created.

To be fair, Sitecore.Context.Item is available in Preview Mode because Sitecore explicitly sets the current item ID at the querystring. However, in publish mode there are no such parameter at the querystring, which happens to let Sitecore.Context.Item with value NULL when you are inside a Save Action. This happens because the Item Resolver only runs AFTER the Save Action, thus Context.Item will only be filled after the Save Action is executed.

Implementing a Solution

So here is the solution we ended up arranging, with best possible reusing of same WFFM and not jeopardizing WFFM’s or Sitecore’s normal pipelines and flows.

Step 1 – Create a new WFFM field for Sitecore.Context.Item

This would be a hidden field at the form, responsible for carry on the Sitecore.Context.Item.ID, available at the time when the form is rendering, to the Save Action where that is not available.

  1. At /sitecore/system/Modules/Web Forms for Marketers/Settings/Field Types/Simple Types start by duplicating the “Single-Line Text” field to serve as a basis for our new field;
  2. Rename it to “Sitecore Context Item ID”;
  3. Fill the field “MVC Type” with the assembly we are going to create to our new field:
    ClientName.Website.Core.WFFM.Fields.SitecoreContextItemId, ClientName.Website.Core
  4. Create a view called “SitecoreContextItemId.cshtml” for this field under /Views/Form/EditorTemplates and add the following content. Notice the <span style=”display:none;”> surrounding the field, which will make it hidden when the form renders
@using Sitecore.Forms.Mvc.Html
@model Sitecore.Forms.Mvc.ViewModels.FieldViewModel
<span style="display:none;">
@using (Html.BeginField())


Step 2 – Make that field comes auto-populated with Context.Item

This class, which is tied to the field at the bullet 3 of Step 1, implements the logic that makes the field renders with Sitecore.Context.Item.ID auto-populated. Notice that this is simply inheriting from SingleLineTextField, adding the ID to the field Value, and nothing else.

using Sitecore.Forms.Mvc.ViewModels.Fields;
namespace ClientName.Website.Core.WFFM.Fields
    public class SitecoreContextItemId : SingleLineTextField
        public override void Initialize()
            if (this.MaxLength != 0)
            this.MaxLength = 256;
            this.Value = Sitecore.Context.Item.ID.ToString();

Step 3 – Make Context.Item be automatically filled from that field

We could very well now just go ahead and read from that field, couldn’t we? But to make things pretty, instead of that we are going to implement a pipeline processor to populate Sitecore.Context.Item.

  • Create an include file “Sitecore.WFFM.SetContextItem.config” with following content:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:patch="">
        <processor type="ClientName.Website.Core.WFFM.Pipelines.SetContextItem,ClientName.Website.Core" patch:after="processor[@type='Sitecore.Forms.Mvc.Pipelines.Submit.RegisterFormSubmitEvent,Sitecore.Forms.Mvc']"/>
  • Then let’s implement this class to make Sitecore.Context.Item be populated.
using System.Linq;
using Sitecore.Data;
using Sitecore.Diagnostics;
using Sitecore.Forms.Mvc.Interfaces;
using Sitecore.Forms.Mvc.Models;
using Sitecore.Forms.Mvc.Pipelines;
namespace ClientName.Website.Core.WFFM.Pipelines
    public class SetContextItem : FormProcessorBase<IFormModel>
        public override void Process(FormProcessorArgs<IFormModel> args)
            Assert.ArgumentNotNull((object)args, "args");
            var model = args.Model as FormModel;
            if (model == null || Sitecore.Context.Item!=null)
            var contextField = model.Item.Fields.FirstOrDefault(p => p.MVCClass.Contains(typeof(Fields.SitecoreContextItemId).FullName));
            if (contextField == null)
            var contextFieldResult = model.Results.FirstOrDefault(p => p.FieldName == contextField.Name);
            if (contextFieldResult == null)
            var contextItem = Sitecore.Context.Database.GetItem(new ID(contextFieldResult.Value.ToString()));
            Sitecore.Context.Item = contextItem;

Pay special attention to the following lines:

var contextField = model.Item.Fields.FirstOrDefault(p => p.MVCClass.Contains(typeof(Fields.SitecoreContextItemId).FullName));

Where the assembly name we created at Step 2 is used to find our field and next:

var contextFieldResult = model.Results.FirstOrDefault(p => p.FieldName == contextField.Name);

 Where the ID value is taken to later populate Sitecore.Context.Item:

var contextItem = Sitecore.Context.Database.GetItem(new ID(contextFieldResult.Value.ToString()));
Sitecore.Context.Item = contextItem;


Step 4 – Add the field to your WFFM Form

Easy part, but if forgotten nothing will work. Make sure your new field is present at your WFFM Form:

WFFM Field Sitecore Context Item

Publicado em WFFM
Social Media Auto Publish Powered By :