Friday, 30 June 2017

Find MongoDB contact using SC_ANALYTICS_GLOBAL_COOKIE

These days I was working on resolving some issues with Sitecore Analytics and need to find the corresponding contact stored in the Contacts collection database in MongoDB easily.

Sitecore generates the analytics cookie value (in GUID) and stores it in the SC_ANALYTICS_GLOBAL_COOKIE cookie which looks like 95f08e09d56348c9bc285080e91be04b|False. That letters/digits combination is a short, lowered version of GUID which is an important identifier for the contact record that gets stored in MongoDB.

However when you try to find this in MongoDB (using Robomongo which is now Robo 3T, make sure to check the latest version), you will not find it because some parts of the GUID are shifted (i.e. first 8 characters, followed by next two groups of 4 letters).

To make things easier, you could run a C# Program query in LINQPad by pasting the below code in, or visit my fiddle page.

    
    void Main()
    {
       // Value from SC_ANALYTICS_GLOBAL_COOKIE (you can copy the |True or |False part which will be trimed too)
       var guidFromCookie = "95f08e09d56348c9bc285080e91be04b|False".Split(new char[] {'|'})[0]; 
       var mongoDbLUUID = string.Format("{0}-{1}-{2}-{3}-{4}",
                              Flip(guidFromCookie.Substring(0,8)), 
                              Flip(guidFromCookie.Substring(8,4)), 
                              Flip(guidFromCookie.Substring(12,4)),
                              guidFromCookie.Substring(16, 4),
                              guidFromCookie.Substring(20,12));
  
       Console.WriteLine("MongoDB query:");
       Console.WriteLine("db.Contacts.find({" + string.Format("_id:LUUID('{0}')", mongoDbLUUID) + "})");
    }

    string Flip(string s)
    {
       var output = "";
       for (var i=s.Length-2; i>=0; i-=2)
       {
           output += s.Substring(i, 2);
       }
 
       return output;
    }

The code will output a query which you can paste directly to Robo 3T.

Thursday, 11 May 2017

CSS rule that might break your Sitecore 8.2 Experience Editor

Today when I was using the Experience Editor on my Sitecore 8.2 Update 3 site and I found that nothing of the following works:

  • Assigning renderings to placeholders
  • Some of the buttons in the ribbon does nothing when clicked
  • Etc, etc
I have checked Chrome console logs... no javascript errors, no 500 or 404 under network tab. Checked Sitecore logs... no exceptions were thrown.

What could it be? I have started scratching my head...

Checking here, checking there, asking my colleague and starting removing whatever is on the page one by one.

At the end we figured out that there is one CSS rule:

body > iframe { display: none;}

We removed it and the Experience Editor starts working again. Why?

This rule effectively hide any iframes that are directly under the body tag, whether they are created dynamically by external javascripts or by yourself. Unfortunately Sitecore Experience Editor also has an iframe directly under body for serving the modal dialog. Therefore when this rule is present, the functionality behind the buttons (that pop up a modal dialog) actually works but the dialog is not showing.

We have only tested this on Sitecore 8.2 so not sure if it affects earlier 8.x versions. The iframe used by Sitecore looks like:

  
  <iframe allowtransparency="true" 
         frameborder="0" 
         id="jqueryModalDialogsFrame" 
         src="/sitecore/shell/Controls/JqueryModalDialogs.html">
      ...
  </iframe>

So once we know this, we can get around this by excluding this from the CSS rule:

body > iframe:not(#jqueryModalDialogsFrame) { display: none;}
Hopefully this helps!

Monday, 1 May 2017

Sitecore Habitat and Fortis

If you don't know what is Habitat yet, please have a look at its Github: https://github.com/Sitecore/Habitat.

By default, Habitat does not use any mapping tool (such as Glass Mapper, Fortis, or the emerging Synthesis) so keep it simple however it does not mean that Sitecore doesn't prefer using one of those.

I have created a fork of the original Habitat solution and made it Fortis-enabled. A Fortis.Foundation module is added to the foundation layer which is responsible for the registration of Fortis and the code-generation of the Fortis model based on Unicorn.

You can find the repo here: https://github.com/codingdennis/Habitat/tree/feature/fortis-integration.

[Updated 2017-05-03] I have also updated this Habitat to support Sitecore 8.2 Update 3, check https://github.com/codingdennis/Habitat/tree/feature/fortis-integration-sc82u3 if required.

Happy Habitating!

Wednesday, 29 March 2017

Sitecore SIM 1.5

There were heaps of development work undergoing since the last release 1.4 Update-3 about a year ago. Alen is in the process of merging of everything from develop to master and we should expect version 1.5 to be released soon which I was lucky enough to also contribute a small portion to it.

Keep an eye on the SIM's GitHub for any updates.

Thursday, 23 February 2017

Script to flush Sitecore xDB

Many people have been talking about how to flush current visit to xDB without playing around the session timeout. Here is just a script ready for use when I need it.

<%@ Page Language="C#" AutoEventWireup="true" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Flush xDB</title>
    <script runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Sitecore.Analytics.Tracker.Current != null)
            {
                Sitecore.Analytics.Tracker.Current.EndTracking();
                Session.Abandon();

                Response.Write("xDB flushed.");
            }
        }
    </script>
</head>
<body></body>
</html>

Save as a ASPX page and put it somewhere on the site and browse to it to flush current visit into xDB.

Wednesday, 22 February 2017

Sitecore ShowConfig on CD servers

I have to say that this is not recommended, not recommended, not recommended... and you are doing this on your own risk.

So, what is it? We have followed all the recommendation on disabling stuff on CD servers but I am sure sometimes we want to see the famous showconfig results on CD servers so we can investigate the configurations only for CD servers. Because CD should not have Sitecore client and the admin pages, so we have removed them. Then how?

Sounds evil? Yes it is so risk is yours :)

When Sitecore does this in CM server, the showconfig.aspx checks if you are logged in. We cannot do that on CD so we just need to create the same page with code that does not do the security checking and put this, say, EvilShowConfig.aspx somewhere on CD server and remove it as soon as you have collected the configurations.

Save the following content into a text file named EvilShowConfig.aspx and put the file on CD at the location of your choice and browser to it.

<%@ Page Language="C#" AutoEventWireup="true" %>
<%@ Import NameSpace="Sitecore.Configuration" %>
<%@ Import NameSpace="System.Xml" %>
<html>
    <head>
        <title>Very Evil ShowConfig</title>
        <script runat="server">
            protected void Page_Load(object sender, EventArgs e)
            {
                XmlDocument configuration = Factory.GetConfiguration();
                Response.Clear();
                Response.ContentType = "text/xml";
                Response.Write(configuration.OuterXml);
                Response.End();
            }
        </script>
    </head>
    <body></body>
</html>

Tuesday, 14 February 2017

Sitecore.ExperienceExplorer.Business.Pipelines.HttpRequest.EnableExperienceModePipeline.Process exception

When building a Sitecore site sometimes you might suddenly see the following exception thrown as soon as you browse to the site:

[NullReferenceException: Object reference not set to an instance of an object.]
   Sitecore.ExperienceExplorer.Business.Pipelines.HttpRequest.EnableExperienceModePipeline.Process(HttpRequestArgs args) +950
   (Object , Object[] ) +73
   Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +483
   Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain) +21
   Sitecore.Nexus.Web.HttpModule.’ (Object  , EventArgs  ) +531
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +141
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +91


I discovered this while playing around the Sitecore demo sites that are built on top of Habitat Demo. This issue should only happen on multisite scenario where the Sitecore setting Preview.DefaultSite is set to a site that does not exist.

In my case, I have removed the habitat site and by default the Habitat Demo sets the Preview.DefaultSite value to habitat. Since I do not have it anymore the exception is thrown.

To fix the issue, patch the value of the setting to one of your site's name (which one is up to you).

Hope this helps!