Experience Sitecore ! | More than 200 articles about the best DXP by Martin Miles

Experience Sitecore !

More than 200 articles about the best DXP by Martin Miles

Item not published. Why? Let's troubleshoot that!

Have you experienced that at least once? You perform publishing, and refresh the website with strong anticipation of new viewing fresh changes and.... not updated. Why? What's going on? Do not panic, let's carefully troubleshoot that step by step.

1. First, and most frequent reason for item tot being published is a case when item is in a workflow, and current workflow state is not final (ie. draft). For that scenario solution is pretty easy as there's nothing wrong - just follow the workflow until item gets to its final state and would be automatically published (that is configured as default behavior). If workflows are not part of your solution - just remove item's template and standard values out of workflow; as well as individual items manually configured; then re-publish.


2. If previous step dodn't help, find out is the item publishable at all? Check item's Publishing Restrictions. You may check that clicking Change button from Publish ribbon in Sitecore. Please find official documentation by this link, as it may be helpful to understand what Publishing Restrictions are and how they work; also there's another great article by John West about those restrictions. Ensure that your item either doesn't have time limit frames, or falls within them.


3.
Most of publishing issues occur just because of inattentiveness. Are you publishing the right version of item? if that's about child items not being published, haven't you forgotten check Publish Subitems for that (or deep=true if publish from the code)? Are you publishing to the right target? Sure about this? OK for that, but what about that target in ConnectionsString.config, does it match desired database as well? All those questions may seem silly once, but still may hurt and stole fair portion of your time and efforts.


4. Next, do not forget about security and permissions. Here is the wide range of thing to consider! Can logged user perform publish, does he have enough permissions to do that? Check if user is in Sitecore Client Publishing role. Further, does default/anonymous user have access rights for the item (or any of its parents), aren't they removed? Not obvious, but publishing won't work otherwise. If publishing is scheduled and performed by the PublishAgent, does it have rights? Please read one more great article by John West.


5. Running on Publishing Instance (that's just a dedicated clone of CM instance, scaled by design for publishing performance on highly loaded environments)? Ensure it is up and running (lol! but sad truth of life).

6. Sill with us here? It's now time to check EventQueue. Ensure all your instances have the correct time set and synced. Just to remind, Sitecore internally stores everything in UTC format. but timezones should match as well. Check Event Queue settings and ScalabilitySettings.config as well.

7. Any issues with caches? Generally, the rule is: less cache you have, slower publishing is, with a bottom moment where it stops at all. Another silly assumption - aren't you running out of free space on system drive? Also make sure HtmlCacheClearer is added to your publish:end:remote event. It will produce a log record like that:

5760 19:57:16 INFO  HtmlCacheClearer clearing HTML caches for all sites

8. Once I came across the case of a new article not being published. The item looked as normal with no publishing restrictions and outside of workflow. However, it did not appear at the publishing target, as since I was using Sitecore Publishing Service I could only see that "0 versions published".

While investigating around at publishing target, I also noted that parent item was missing. When looking at parent at master database I noticed an information bar saying that parent items had 0 versions. That was the exact reason: parent item was not published due to the lack of versions, and its actual child item did not do through because Sitecore does not allow having orphaned items - a given item did not have a parent at the destination. Creating and publishing a version for the parent item has fixed that problem.

9. The last, quite a rare scenario: some of those curious experimenters like I am, who frequently install dozens of fresh instances of Sitecore for their sandbox trials, usually forget to initially publish entire site on a fresh install, so that it process all the required dependencies. Normally, I would not mention that, but still want to share as many cases as I know.

OK, so many things to consider? Agree with you, that's why I wrote that article, sort of cheat sheet in order to have it at my fingertips. But that's not all. Look for the general troubleshooting plan when something is not been published.

  • as given, item does not present there (on target), but what about its parent item? If missing, what about parent of the parent? Go to master database and carefully inspect the highest unpublished descendant, what isn't correct with it?
  • check workflows, publishing restrictions etc. mentioned above in the beginning of this article.
  • check logs for anything helpful
  • create a copy unpublished item and try to publish that one to the same destination.
  • create another new item of the same template and try to publish it. Succeeded with that?
  • delete and recreate that and related items (layouts, renderings, template) on target, and re-publish
  • handle publish:fail event and try to identify the reason; would be great to step into the method with debugger, if available.
Finally, (remember, I said no panic in the beginning), there is a buletproof solution as the last resort - copy items between databases manually. Go to Control Panel --> Database --> Move an item to another database, where you can move items between databases. One thing to mention - do not forget to update caches after you finish copying items to your target environment.


There are few more things I'd like to mention regarding publishing:

1. I would highly recommend The Published Item Comparer - a Sitecore module that quickly validates the current item in the content tree with the same item in a target database such as the “web” database; this helps to identify publishing issues effectively.

2. Unlike presented, Smart Publishing just cannot be trusted entirely, if reliability is your number one criteria - use re-publish instead.


Hope this post helps and wish your items always to appear on targets!

Sitecore Item Extension Methods

Below, there is my collection of Sitecore Item's extension methods, I've collected them within few recent years of my career from various sources. I decided to store them here, all at the same place, so that I can pick them up from here when necessary, case by case.

Here they are:



Programmatically Get Datasource Items of a Sitecore Item

If you need to get the datasource item’s of a particular Sitecore item, we can write a few extension methods to help us out!
public static class ItemExtensions
{
        public static RenderingReference[] GetRenderingReferences(this Item i)
        {
            if (i == null)
            {
                return new RenderingReference[0];
            }
            return i.Visualization.GetRenderings(Sitecore.Context.Device, false);
        }
 
        public static List<Item> GetDataSourceItems(this Item i)
        {
            List<Item> list = new List<Item>();
            foreach (RenderingReference reference in i.GetRenderingReferences())
            {
                Item dataSourceItem = reference.GetDataSourceItem();
                if (dataSourceItem != null)
                {
                    list.Add(dataSourceItem);
                }
            }
            return list;
        }
 
        public static Item GetDataSourceItem(this RenderingReference reference)
        {
            if (reference != null)
            {
                return GetDataSourceItem(reference.Settings.DataSource, reference.Database);
            }
            return null;
        }
 
        private static Item GetDataSourceItem(string id, Database db)
        {
            Guid itemId;
            return Guid.TryParse(id, out itemId)
                                    ? db.GetItem(new ID(itemId))
                                    : db.GetItem(id);
        }
}

Example of the call:
foreach (Item dataSourceItem in Sitecore.Context.Item.GetDataSourceItems())
{
    // do something
} 

Programmatically Get Personalization Datasource Items of a Sitecore Item

In the previous blog post, Programmatically Get Datasource Items of a Sitecore Item we learned how to get the datasource items from the rendering references. This does not include the items that have been added through personalization and rules. By adding the following methods to our previous post, we can get those items.
public static List<Item> GetPersonalizationDataSourceItems(this Item i)
{
    List<Item> list = new List<Item>();
    foreach (RenderingReference reference in i.GetRenderingReferences())
    {
        list.AddRange(reference.GetPersonalizationDataSourceItem());
    }
    return list;
}
 
private static List<Item> GetPersonalizationDataSourceItem(this RenderingReference reference)
{
    List<Item> list = new List<Item>();
    if (reference != null && reference.Settings.Rules != null && reference.Settings.Rules.Count > 0)
    {
        foreach (var r in reference.Settings.Rules.Rules)
        {
            foreach (var a in r.Actions)
            {
                var setDataSourceAction = a as Sitecore.Rules.ConditionalRenderings.SetDataSourceAction<Sitecore.Rules.ConditionalRenderings.ConditionalRenderingsRuleContext>;
                if (setDataSourceAction != null)
                {
                    Item dataSourceItem = GetDataSourceItem(setDataSourceAction.DataSource, reference.Database);
                    if (dataSourceItem != null)
                    {
                        list.Add(dataSourceItem);
                    }
                }
            }
        }
    }
    return list;
}
This code loops through the rules of your personalized component and if the action is Sitecore.Rules.ConditionalRenderings.SetDataSourceAction, then we know that this will be:
foreach (Item personalizationItem in Sitecore.Context.Item.GetPersonalizationDataSourceItems())
{
     // do something
}

Get Multi Variate Test Datasource Items of a Sitecore Item

In the previous two blog posts, Programmatically Get Datasource Items of a Sitecore Item and Programmatically Get Personalization Datasource Items of a Sitecore Item we learned how to get the datasource items and personalization datasource items from the rendering references. This does not include the items that have been added through Multi Variate Testing. By adding the following methods to our previous post, we can get those items.
public static List<Item> GetMultiVariateTestDataSourceItems(this Item i)
{
    List<Item> list = new List<Item>();
    foreach (RenderingReference reference in i.GetRenderingReferences())
    {
        list.AddRange(reference.GetMultiVariateTestDataSourceItems());
    }
    return list;
}
 
private static List<Item> GetMultiVariateTestDataSourceItems(this RenderingReference reference)
{
    List<Item> list = new List<Item>();
    if (reference != null && !string.IsNullOrEmpty(reference.Settings.MultiVariateTest))
    {
        using (new SecurityDisabler())
        {
            var mvVariateTestForLang = Sitecore.Analytics.Testing.TestingUtils.TestingUtil.MultiVariateTesting.GetVariableItem(reference);
            //var mvVariateTestForLang = reference.Settings.GetMultiVariateTestForLanguage(Sitecore.Context.Language); // < Sitecore 7.5
            Sitecore.Data.Items.Item variableItem = null;
 
            if (mvVariateTestForLang != null)
            {
                variableItem = mvVariateTestForLang.InnerItem;
                //variableItem = reference.Database.GetItem(mvVariateTestForLang); // < Sitecore 7.5
            }
 
            if (variableItem != null)
            {
                foreach (Item mvChild in variableItem.Children)
                {
                    var mvDataSourceItem = mvChild.GetInternalLinkFieldItem("Datasource");
                    if (mvDataSourceItem != null)
                    {
                        list.Add(mvDataSourceItem);
                    }
                }
            }
        }
    }
    return list;
}
 
public static Item GetInternalLinkFieldItem(this Item i, string internalLinkFieldName)
{
    if (i != null)
    {
        InternalLinkField ilf = i.Fields[internalLinkFieldName];
        if (ilf != null && ilf.TargetItem != null)
        {
            return ilf.TargetItem;
        }
    }
    return null;
}
This code shown is for Sitecore 7.5 and above while the commented out lines are for versions of Sitecore below 7.5. Now that we have these extension methods, we are able to write some nice code like this:
foreach (Item multiVariateTestDataSourceItem in Sitecore.Context.Item.GetMultiVariateTestDataSourceItems())
{
     // do something
}

Is Media Item / Is Content Item

Those two properties are built in and come with sitecore initially. They simple verify item path, wether that falls under /sitecore/content or /sitecore/media library
item.Paths.IsContentItem;
item.Paths.IsMediaItem;

DoesLanguageVersionExist

This extension method will be used to check ifitem exist in current provided language
        
public static bool DoesLanguageVersionExist(this Item item, Language languageToCheck)
        {
            bool isExist = false;
            Sitecore.Data.Items.Item itemInLanguage = item.Database.GetItem(item.ID, languageToCheck);
            isExist = itemInLanguage.Versions.Count > 0;
            return isExist;
        }

GetBooleanField

Gets value of Checkbox field
        public static bool GetBooleanField(this Item item, string fieldName)
        {
            Field fieldValue = item.Fields[fieldName];

            if (fieldValue != null)
                return (fieldValue.Value == "1" ? true : false);
            else
                return false;
        }

GetMediaItemField

Returns MediaItem from Media Field
        public static MediaItem GetMediaItemField(this Item item, string fieldName)
        {
            Field fieldValue = item.Fields[fieldName];
            MediaItem mediaItem = null;

            if ((fieldValue != null) && (fieldValue.HasValue))
                mediaItem = ((ImageField)fieldValue).MediaItem;

            return mediaItem;
        }

GetStringField

Retrieves value of a string-based field - Single Line, Multiline, etc.
        public static String GetStringField(this Item item, String fieldName)
        {
            string fieldValue = string.Empty;
            if (item != null)
            {
                Field field = item.Fields[fieldName];
                if ((field != null) && (!string.IsNullOrEmpty(field.Value)))
                    fieldValue = field.Value;
            }
            return fieldValue;
        }

GetDateField

Gets DateTime value out of Date of DateTime field
        public static DateTime GetDateField(this Item item, String fieldName)
        {
            DateField fieldValue = item.Fields[fieldName];
            DateTime dateTime = DateTime.Now;
            if ((fieldValue != null) && (fieldValue.InnerField.Value != null))
                dateTime = fieldValue.DateTime;

            return dateTime;
        }

GetHtmlField

Gets the value of HtmlField
        public static HtmlField GetHtmlField(this Item item, String fieldName)
        {
            HtmlField htmlField = item.Fields[fieldName];
            return htmlField;
        }

Gets LInk Field out of corresponding item
        public static LinkField GetLinkField(this Item item, String fieldName)
        {   
            LinkField linkField = item.Fields[fieldName];
            return linkField;
        }

GetReferenceField

Gets Reference Field out of corresponding item - Droplink, Droptree, Grouped Droplink etc.
        public static ReferenceField GetReferenceField(this Item item, String fieldName)
        {            
            ReferenceField referenceField = item.Fields[fieldName];
            return referenceField;
        }

GetReferenceFieldItem

Gets an associated item out of Reference Field of an item - Droplink, Droptree, Grouped Droplink etc.
        public static Item GetReferenceFieldItem(this Item item, String fieldName)
        {
            Item targetItem = null;
            ReferenceField referenceField = item.Fields[fieldName];
            if ((referenceField != null) && (referenceField.TargetItem != null))
                targetItem = referenceField.TargetItem;

            return targetItem;
        }

GetMultilistField

Returns Multilist Field
        public static MultilistField GetMultilistField(this Item item, String fieldName)
        {
            MultilistField multilistField = item.Fields[fieldName];
            return multilistField;
        }

GetMultilistFieldItems

Returns associated items of Multilist Field; works also with Checklist, Treelist, Treelist-Ex
        public static Item[] GetMultilistFieldItems(this Item item, String fieldName)
        {            
            Item[] targetItems = null;
            MultilistField multilistField = item.Fields[fieldName];
            if ((multilistField != null) && (multilistField.InnerField != null))
                targetItems = multilistField.GetItems();

            return targetItems;
        }

Publish

Performs publishing of an item. Deep parameter makes publishing recursice against all the subitems
public static void Publish(this Item item, bool deep)
{
    var publishOptions = new PublishOptions(item.Database,
                                        Database.GetDatabase("web"),
                                        PublishMode.SingleItem,
                                        item.Language,
                                        DateTime.Now);
    var publisher = new Publisher(publishOptions);
    publisher.Options.RootItem = item;
    publisher.Options.Deep = deep;
    publisher.Publish();
}

Unpublish

Unpublishes current item
public static void UnPublish(this Item item)
{
    item.Publishing.UnpublishDate = DateTime.Now;
    item.Publish(true);
}

IsPublished

Finds out if item is already published
public static bool IsPublished(this Item pItem)
{
    Database lWebDb = Factory.GetDatabase("web");
    if (pItem != null && lWebDb != null)
    {
        Item lWebItem = lWebDb.GetItem(pItem.ID, pItem.Language, pItem.Version);
        if (lWebItem == null || pItem.Statistics.Updated > lWebItem.Statistics.Updated)
        {
            return false;
        }
    }
    return true;
}

ParentList

Gets an array of all hierarchial parent items of a current item, can be useful for creating breadcrumbs
public static IEnumerable<Item> ParentList(this Item item, Boolean descending = true)
{
    if (item == null)
        return null;
 
    List<Item> parents = new List<Item>();
 
    Item currentItem = item.Parent;
    while (currentItem != null)
    {
        parents.Add(currentItem);
 
 
        currentItem = currentItem.Parent;
    }
 
    if (descending)
        parents.Reverse();
 
    return parents;
}

GetReferrersAsItems

Get referrers of an item using the link database
public static IEnumerable<Item> GetReferrersAsItems(this Item item)
{
    var links = Globals.LinkDatabase.GetReferrers(item);
    return links.Select(i => i.GetTargetItem()).Where(i => i != null);
}

IsDerived

Tells, if a given item derives from a specific template
public static bool IsDerived(this Item item, ID templateId)
{
  if (item == null)
    return false;
 
  if (templateId.IsNull)
    return false;
 
  TemplateItem templateItem = item.Database.Templates[templateId];
 
  bool returnValue = false;
  if (templateItem != null)
  {
    Template template = TemplateManager.GetTemplate(item);
 
    returnValue = template != null && template.ID == templateItem.ID || template.DescendsFrom(templateItem.ID);
  }
 
  return returnValue;
}

ChildrenDerivedFrom

Returns children items derived from a specific template
 
public static IEnumerable<Item> ChildrenDerivedFrom(this Item item, ID templateId)
{
    ChildList children = item.GetChildren();
    List<Item> childrenDerivedFrom = new List<Item>();
 
    foreach (Item child in children)
    {
        if (child.IsDerived(templateId))
            childrenDerivedFrom.Add(child);
    }
 
    return childrenDerivedFrom;
}

IsTemplate

Checks wether specific item is a template item
public static bool IsTemplate(this Item item)
{
    return item.Database.Engines.TemplateEngine.IsTemplatePart(item);
}

HasLanguage

Tells, if an Item has a version in a specific language
public static bool HasLanguage(this Item item, string languageName)
{
    return ItemManager.GetVersions(item, LanguageManager.GetLanguage(languageName)).Count > 0;
}

public static bool HasLanguage(this Item item, Language language)
{
    return ItemManager.GetVersions(item, language).Count > 0;
}

LanguageVersionCount

Gives the amount of versions that a given item has in a given language
public static int LanguageVersionCount(this Item item, Language lang)
{
    if (item == null)
        return 0;
    Item currentItem = item.Database.GetItem(item.ID, lang);
    if (currentItem.Versions.Count > 0)
        return currentItem.Versions.Count;
    else
        return 0;
}

AddItemToIndex

Adds given item into specified index
public static void AddItemToIndex(this Item item, string indexName)
{
    var tempItem = (SitecoreIndexableItem)item;
    ContentSearchManager.GetIndex(indexName).Refresh(tempItem);
}

UpdateItemInIndex

Updates current item within an index
public static void UpdateItemInIndex(this Item item, string indexName)
{
    var tempItem = (SitecoreIndexableItem)item;
 
    ContentSearchManager.GetIndex(indexName).Delete(tempItem.UniqueId);
    AddItemToIndex(item, indexName);
}

PublishItem

One more version of Publish method for current item
public static void PublishItem(this Item item)
{
    var publishOptions = new PublishOptions(item.Database,
        Database.GetDatabase("web"),
        PublishMode.SingleItem,
        item.Language,
        DateTime.Now); // Create a publisher with the publishoptions
 
    var publisher = new Publisher(publishOptions);
 
    // Choose where to publish from
    publisher.Options.RootItem = item;
 
    // Publish children as well?
    publisher.Options.Deep = true;
 
    // Do the publish!
    publisher.Publish();
}

Url

Returns user-friendly URL of an item
public static string Url(this Item item)
{
    return LinkManager.GetItemUrl(item);
}

GetMembershipUser

Returns the System.Web.Security.MembershipUser associated with a Sitecore.Security.Accounts.User object
public static MembershipUser GetMembershipUser(this Account account)
{
return Membership.GetUser(account.Name);
}

HasBaseTemplate

Returns true if current template item is derived from another template
public static bool HasBaseTemplate(
      this TemplateItem me,
      ID templateID,
      bool includeSelf = false,
      bool recursive = true)
    {
      if (includeSelf && me.ID == templateID)
      {
        return true;
      }
 
      if (recursive)
      {
        foreach (TemplateItem baseTemplate in me.BaseTemplates)
        {
          if (baseTemplate.HasBaseTemplate(
            templateID,
            true /*includeSelf*/,
            true /*recursive*/))
          {
            return true;
          }
        }
      }
 
      return false;
    }

HasChild

Identifies if current item has a child with a specific ID
public static bool HasChild(this Item item, string childIdStr)
{
    ID childId = new ID(childIdStr);
    return HasChild(item,childId);
}

public static bool HasChild(this Item item, ID childId)
{
    foreach (Item child in item.Children)
    {
        if (child.ID == childId)
            return true;
    }
    return false;
}

HasDescendant

Identifies if current item has a decscendant with a specific ID
public static bool HasDescendant(this Item item, string descendantIdstr)
{
    ID descendantId = new ID(descendantIdstr);
    return HasDescendant(item, descendantId);
}

public static bool HasDescendant(this Item item, ID descendantId)
{
    foreach (Item child in item.Children)
    {
        if (child.ID == descendantId)
            return true;
        
HasDescendant(child, descendantId); } return false; }

IsStandardValue

Indicates whether an item is a standard value item or not
public static bool IsStandardValues(this Item item)
{
  if (item == null)
    return false;
  bool isStandardValue = false;
         
  if (item.Template.StandardValues != null)
    isStandardValue = (item.Template.StandardValues.ID == item.ID);
         
  return isStandardValue;
}

HasRenderings

Indicates if an item has versioned renderings.
public static bool HasRenderings(this Item item)
{
    return item.Visualization.GetRenderings(Context.Device, false).Any();
}
public static bool HasRenderings(this Item item, DeviceItem device)
{
    return item.Visualization.GetRenderings(device, false).Any();
}

HasVersionedRenderings

Indicates if an item has versioned renderings.
public static bool HasVersionedRenderings(this Item item)
{
   if (item.Fields[FieldIDs.FinalLayoutField] == null)
      return false;

   var field = item.Fields[FieldIDs.FinalLayoutField];
   return !string.IsNullOrWhiteSpace(field.GetValue(false, false));
}

public static bool HasVersionedRenderingsOnLanguage(this Item item, Language language)
{
    return item != null && item.Database.GetItem(item.ID, language).HasVersionedRenderings();
}
public static bool HasVersionedRenderingsOnAnyLanguage(this Item item)
{
   return ItemManager.GetContentLanguages(item).Any(item.HasVersionedRenderingsOnLanguage),
}
public static bool HasVersionedRenderingsOnContextLanguage(this Item item)
{
   return item.HasVersionedRenderingsOnLanguage(Context.Language);
}

StackOverflow: Is it possible to change a Page to branch?

Another question I have explained on StackOverflow - (original link on StackOverflow):

Is it possible to change the Template of a page to Branch Template? When I try in Sitecore 7.0 UI it gives a error message stating to "Select a Template".

Is there any other way to change an Item's Template to be a Branch Template?

Answer: You cannot just substitute a template of an item with a branch template. You might be probably confused by mutual term template they both use and the fact the both exist undet /sitecore/templates node, however they are absolutely different in their internals.

Branch templates are just template sub-nodes that are being copied in instantiation. You may still use tokens and they would apply for every single item in a branch. But each of the items from a branch would still origin from certain individual template.

enter image description here

Thus, you cannot just do Configure --> Change on an item and then select a branch template instead of ordinary template, that's why Branches node is highlighted with grey color and even if you try to select any - sitecore will tell you "please select a template".

enter image description here

What you can do is just to re-create your item from branch template and (assuming) previous item now becomes a part of your branch - you may simply manually copy all the presentation details. However an ID of that item would differ with an ID of initial item (unless you manually replace original item into a branch instantiated)

I previously wrote an article on how to copy presentation detail manually between items, it will help you with your case:

https://blog.martinmiles.net/post/copying-presentation-details-manually

Sitecore 8: Federated Experience Manager - what is all about?

One of the greatest features of Sitecore 8 is Federated Experience Manager (FXM). What is FXM about and how can it help us?

Previously we had Page Editor - the tool allowing content editors to author and save content inline, right on the page. It also offered other flexible options to operate with non-visible content of features that cannot be edited inline (ie. Edit Frames), also do customisation (A/B multivariate testing), personalisation on rule-based criteria and much more. So far, so good.

In Sitecore 8, Page Editor was replaced with a new feature called Experience Editor (EE). EE is not just a rename for Page Editor, despite it does all the same old good features, it brings great new opportunities in chain with FXM.

With FXM it is now possible to customise any other website page, not only those coming from Sitecore, but even any PHP or just static HTML. And further on, with EE it is now possible to do all good old Page Editor features, such as replace content on external website, create placeholders and append sitecore components there, apply personalisation, set goals etc.

Sounds fantastic and impossible? Not as much - all that is working out box now, and moreover is very simple. Let's take a look on how that works and what is involved.


FXM is an applications shipped out of box and is available from Launchpad - just a usual SPEAK application. As soon as it loads, you'll get a management screen to register external websites. Clicking Add External Website will load you the following screen:


What is required on that step is to provide a hostname for external website and add one line of code into external website pages - a javascript reference for a beacon:


So, it stands obvious that you need to have an access to modify the code of pages on that website. Normally you'd do that for all pages, so it makes sense to modify some master layout or any sort of global header.

One important thing to note: external html should be properly formed, otherwise there will be an error. Saying properly formed I mean just opening and closing tags for html head and body, as minimal as:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head></head>
    <body></body>
</html>
After that done - it becomes possible to open that external website with Experience Editor. And here you can perform:
  • tracking of external website into xDB
  • create placeholders before, after or instead certain html elements on external website
  • having Sitecore-controlled placeholders it is now possible to append components from Sitecore there
  • components from Sitecore can be literary everything, even WFFM forms (however not yet in current version)
  • cleaning up, replacing or extending original content from external website
  • apply customisation and / or personalisation to external content, controllable from Sitecore
  • set goals


It is essential to understand that those features work due cross site scripting called CORS, so certain limitations should be taken off, other wise it won't work

After site has been created at /sitecore/system/Marketing Control Panel/FXM/External you need to open that node and create a rule in order to match the same domain. Without doing that it would work only in Experience Editor, but not on the live website.



When opening external website it in Experience Editor, click on Add Placeholder button twice (to get it activated), then click first paragraph. You will see it identified as div with three options on how to insert a Sitecore-controllable placeholder: before, after or replace that div element. Let's choose after, in order to implement sitecore controllable rendering in between those two paragraphs on external website:

After choosing where exactly to implement a placeholder, you'll be prompted to enter placeholder name and select parent website:


Note: licensing is important to mention. FXM works only with new license issued with Sitecore 8, so if you have license file from one of previous versions, it would not have appropriate permission (Sitecore.Federated Experience) for running FXM. For some reasons Sitecore did not implement obvious message telling that you are not able to set a placeholder externally because of license. I spent decent time previously trying to understand why that did not work for me. Please find more details in my answer on StackOverflow for that question.

Once done, there will be last screen, showing newly created placeholder exactly in between those two paragraphs and offering to append a rendering to it:


To make things easier, I have just slightly modified Sample Rendering that comes with Sitecore, so that it now looks like that:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:sc="http://www.sitecore.net/sc"
  xmlns:sql="http://www.sitecore.net/sql"
  exclude-result-prefixes="sc sql">
  <xsl:output method="html" indent="no" encoding="UTF-8"  />

  <xsl:template match="*">
    <div>
      <h3>FXM-powered placeholder</h3>
      <span>This content comes from Sitecore and is editable with Experience Editor. 
      Other cool features as personalization are also available with FXM.</span>
      <br/><br/>
    </div>
    
  </xsl:template>
</xsl:stylesheet>
That's mostly done! Do not forget to publish your site definition (under FXM node) with children (there will be placeholder item we've just created) to content delivery environment in order to work there. Let's now test it! I enter http://external into a browser and get exactly what expected - there is a sitecore controllable placeholder in between the paragraphs and it has a rendering being set into it:



Opening that in any dev. tools like Firebug will show the following nice and clean code has been rendered:


Basics: working with generic content in Sitecore

Problem: let's imagine you have a website with a multiple pages where editors supposed to create content, consistent from pre-styled components, coming in various order and in various places. How would you do that?

Idea: to my mind, the most obvious answer would be to classify content to several atomic types. These can be Header, SubHeader, Paragraph, Link, LinkList, Image, BlockQuote etc. whatever you may need. These "primitives" on higher level are wrapped by container types, that server as data sources for certain renderings.

Implementation: imagine a page that has a main content with a sidebar. We want content authors to be able either to select from already pre-defined sidebar components (like LoginForm or let's say TwitterFeed component), or create a custom sidebar with some generic content, or both, and in various orders. In order to do that we need to associate SidebarHolder rendering with a corresponding placeholder, so that only that rendering would be possible to add to particular placeholder. After that done you need to associate related content (remember, that you may restrict location of those container data items from Datasource Location field of corresponding rendering item; also you may limit to specific container template with Datasource Template field).

We insert GenericContentSidebar container for our example. As soon as container is inserted as a datasource for the SidebarHolder rendering, you may start creating primitive content items as the children of a container. But before doing that you may consider assigning insert options for rendering's datasource container template item. To do that - go to Standard values of that template item and assign insert options for those primitives' templates you may want to have available for that particular datasource type.

Code: let's assume we are using controller rendering that addresses the following controller action:

public ViewResult GenericControlsHolder()
{
    var content = BaseGenericControl.Iterate(RenderingContext.Current.Rendering.Item);
    return View("/Views/Renderings/PageComponents/GenericControlsHolder.cshtml", content);
}
That controller rendering is passing List<dynamic> as model into GenericControllerHolder view. Let's see the implementation for BaseGenericControl class and Iterate() method within it. I also included two public properties into BaseGenericControl in order to be able to specify custom CSS class for wrapping tags in cases when they wrap output values in overridden Render().
I use dynamics instead of base class because not all of primitives derive from base class, but they all have render method, so if you want to be strict with your types - you may use interfaces instead (let's stay very simple here)
public class BaseGenericControl
{
    public static class Constants
    {
        public static class Templates
        {
            public const string Title = "{38B8D602-9EB4-4DDA-973F-1CA48CC42E19}";
            public const string SubTitle = "{FC85D20A-4DE7-476B-AC8D-0717BA8FD23A}";
            public const string RichText = "{7EACE00C-552E-419F-9ACB-51A98998CA39}";
            public const string Paragraph = "{8A4F87F2-E36D-4377-B5A0-9866E64D3AE5}";
            public const string LinksList = "{7466407B-3839-4EBE-9FC7-20AF9217FFAB}";
            public const string Link = "{D38B51D6-74CF-40E2-A86F-97D346C17128}";
            public const string Separator = "{9542C6DA-2FDA-482C-A6CF-B07F85D3CEE5}";
        }
    }

    public HtmlString Value { get; set; }
    public HtmlString CssClass { get; set; }

    public BaseGenericControl()
    {
    }

    public BaseGenericControl(Item item)
    {
        Value = new HtmlString(FieldRenderer.Render(item, "Value"));
        CssClass = new HtmlString(FieldRenderer.Render(item, "CSS Class"));
    }

    public virtual string Render()
    {
        return Value.ToString();
    }

    public static dynamic Iterate(Item datasourceItem)
    {
        var content = new List<dynamic>();

        if (datasourceItem != null)
        {
            foreach (Item item in datasourceItem.Children)
            {
                if (item.TemplateID == new ID(Constants.Templates.Title))
                {
                    content.Add(new Title(item));
                }
                else if (item.TemplateID == new ID(Constants.Templates.SubTitle))
                {
                    content.Add(new SubTitle(item));
                }
                else if (item.TemplateID == new ID(Constants.Templates.Paragraph))
                {
                    content.Add(new Paragraph(item));
                }
                else if (item.TemplateID == new ID(Constants.Templates.RichText))
                {
                    content.Add(new RichText(item));
                }
                else if (item.TemplateID == new ID(Constants.Templates.LinksList))
                {
                    content.Add(new LinksList(item));
                }
                else if (item.TemplateID == new ID(Constants.Templates.Link))
                {
                    content.Add(new GenericLink(item));
                }
                else if (item.TemplateID == new ID(Constants.Templates.Separator))
                {
                    content.Add(new Separator()); // no need to pass item, as it's just static HR tag.
                }
            }
        }

        return content;            
    }
}
What we see above is just an iterator that instantiates an object of specific type and saves it into list. Let's then take a look on Paragraph class as an example of such a class, that being instantiated:
public class Paragraph : BaseGenericControl
{
    public Paragraph(Item item) : base(item)
    {
    }

    public override string Render()
    {
        return string.Format("<p class='{0}'>{1}</p>", CssClass, Value);
    }
}

The CSHTML view for that rendering seems to be very minimal - it accepts list of dynamics as the model and passes it into HTML helper method:
@model List<dynamic>
@Html.Sitecore().RenderGenericControls(Model)

RenderGenericControls helper just iterates all our primitive types in dynamic list and calls render for each of them (again, you would probably be strict on types and use interfaces instead of dynamics):

public static HtmlString RenderGenericControls(this SitecoreHelper html, dynamic content)
{
    var htmlBuilder = new StringBuilder();

    foreach (dynamic component in content)
    {
        htmlBuilder.Append(component.Render());
    }

    return new HtmlString(htmlBuilder.ToString());
}

The order of primitives remains the same as they are kept in Sitecore within container item.

This is not an universal approach for generic content, but still worth of mentioning.

StackOverflow: Sitecore FXM issue - parent selector is missing in Add to Placeholder dialog

A guy on StackOverflow recently asked about unfunctional Parent control on Federated Experience Manager in Siecore 8.0. Here is his original question:


"I am trying to use Federated Experience Manager with an external website. The static website has a JS beacon, so now I am able to open external page with Experience Editor.

The issue happens when I try to add a placeholder to that external static page (as per guide), parent dropbox do not present, so I am not able to create a placeholder and any other operations FXM allows."


I have met that issue before, so was happy to share my experience:

I had that issue in past when tried to investigate Sitecore 8 new features. I know it may sound weird, but this happens because your license does not have FMX in it.

If you got you your license.xml file from previous sitecore versions, then FXM would not be there, you need to request new license from Sitecore that has this feature enabled.

Update: The good way to test that is to look beacon file content (ex. in dev. tools) - if you do no have license beacon would just have missing license text without any actual content. You may check what you are actually licensed for from Sitecore menu (or hamburger menu in 8.0+) from Content Editor, then selecting Licenses. If you do not see something like Sitecore.Federated Experience (or similar by sense) then you are definitely out of license for FXM.

Also, it is mentioned in the official Requirements and Limitations article: https://goo.gl/wZfEhQ

original StackOverflow link

Hope this helps someone!

Version Layouts - what is that for?

Every good Sitecore developer is familiar with the principle of versioned and shared fields - an item can contain a mixture of both types. People often wrongly consider items are versioned (for simplicity), however in fact that is not quite true. Fields may have versions, not items. When user creates a new version of item in fact only new versions of versioned fields are created, and not the shared. This concept aims to address effectiveness of data storage and it works well and transparent to users. So far, so good.

Previously, we did not have similar feature for Presentation details - it was always shared. Saying Presentation I mean layout details for devices, renderings, placeholders etc. - everything that stored in Renderings field of Layout section of Standard Template every page should inherit from.


Final presentation for an item was merged from whatever stored in Standard values (for item's template) with Layout Delta (changes individually applied to item - a delta from those in Standard Values). Standard values were stored at Rendering field of Standard Values item for a template of that specific item, thus it was the chared for all the items of that particular template; Layout Delta was physically stored in Renderings (shared) field, but of that specific item, thus applied individually to that item.

Since Sitecore 8 - there is one more point for consideration - a version. Standard Template has been extended with one new field called Final Renderings, and what is principally important at that moment - Final Renderings is a versioned field. The point of introducing that new field was that now it becomes possible to have different presentation of a page for different languages and various versions. Also, now it is possible to have a specific version of page's presentation and have it published for a while (without creating duplicates and renaming the in real-time) - now all the information is stored withing same page item.


So, before, while building the presentation Sitecore had to consider only two Renderings fields - one from item's template's Standard values, another from item itself. As both parts were shared - resulting presentation was always the same across languages and versions. Previously if you wanted a page to look different for different laguages - you were limited to personalizing renderings by specifying languages and renderings in Rules Engine. No more personalisaion required since now!

At the moment we have following configuration, in that particular order on how final presentatin is calculated:

  1. Standard Values - Renderinds field - shared.
  2. Standard Values - Final Renderinds field - versioned.
  3. Item - Renderinds field - shared.
  4. Item - Final Renderinds field - versioned.

Here's the diagram (from official site) on how final presentation is calculated with the above bunch of sources of presentation:


Thus, important advice - do not use them four at the same time, as it may behave unpredictable. Before Sitecore 8 most popular combitaion user for presentation calculation was (1)-(3), less often just (1) or (3) solely by themselves. Now you may safely use combitations of (1)-(2)-(4) or (1)-(3)-(4), as they were tested and proved with time. Of course, previous (1)-(3) from migrated projects will work as before, until you modify and save it with Experince Editor. Experince Editor works with Final Renderings field and not with shared Renderings field.

These above were just brief notes about Versioned Layouts, I left that in blog mostly for myself to have quick access to. But if you may want to understand how Versioned Layouts work in details,I would highly recommend to read a series of articles called Version Layout - Mixed Feelings (part 1, part2 and part 3).

See also Sitecore item's extension methods for identifying version layouts (link).

Hope you find this post helpful!

Unicorn - the simplest way to share Sitecore items in the soure control along with your code

Annoyed of the necessity of creating packages with recent items in order to share that with your colleagues? Tired of items' versioning? Why not to version those items in source control then?


My favorite tool for achieving that is Unicorn. It does exactly what it suppose to - syncs certain Sitecore items (recursively with children) within a directory, as configured, so that you are able to check-in the folder with all serialized items, so that your colleagues can sync that changes into their database; that means new features / fixes deliver items deltas simultaneously with their code counterparts.

Here is the example of configuration, whatever sits under mentioned paths (recursively) will be serialized:

    





The greatest thing I love about Unicorn is simplicity - as simple as the following:

  • It installs as NuGet package.
  • Consists of 2 DLLs and a config patch file.
  • Just one control page at the web root to perform sync / revert
  • Simple configuration file.

From limitations I would only mention recursiveness - specifying an item in config processes it will all child items and that cannot be overridden. Of course, this is not a problem in more advanced solution - TDS, but are we here about simplicity?


Installation from NuGet Package Manager Console:

PM> Install-Package Unicorn

See also: GitHub source code

Update: now version 3 has been released with great, even revolutionary, changes and it became more friendly. So, please read:




How to check your license in Sitecore

From time to time you may need to obtain your licensing information, for instance when you need to submit support ticket.

License information is displayed right at the loging screen in Sitecore 6.X - 7.X (as per screenshot below):


Once you need more details about current license, (for example to see which modules you are licensed to) you may find that from two menus (Licenses and About) under Sitecore button in Content Editor:



However Sitecore 8 login screen does not show this information by default anymore. To enable displaying licensing info, you need to change one configuration file switch:

<setting name=”Login.DisableLicenseInfo” value=”false” />

Then you'll get a button that reveals your licensing information, including the License key:


Sitecore button in the left top corner of Content Editor has now become "hamburger" button, but provides all the same functionality:



For me (being a developer), the quickest option to remind the license number is just looking up directly at License.xml file:


Hope this helps!

Sitecore 8.0 Update 5 is released

Sitecore 8.0 Update 5 is released

Now with Mongo 3!

  • Support has been added for MongoDB 3.0.
  • The MongoDB driver has been upgraded to 1.10.
  • Generic security enhancements have been made.

It works fine with previous SIM (Sitecore Instance Manager) release revision 150618 as soon as you place webroot archive Sitecore 8.0 rev. 150812.zip into repository folder. To retrieve your repository folder with SIM navigate Settings -> Local Repository.