Experience Sitecore ! | September 2015

Experience Sitecore !

More than 200 articles about the best DXP by Martin Miles

Productivity Improvement: Creating a Presentation Exists Gutter - get even faster access to item's Presentation Details

Previously I have described how easily you can create a shortcut to Device Editor of Presentation Details right at the item's Context Menu - access that as much as in two clicks! But there's even easier (and more visual) way - create a specific Sitecore Gutter.
So, what Gutters are? Gutters are sort of visual markers you can optionally enable / disable in your Content Editor. Have you seen a vertical bar, immediately left hand side from Sitecore tree? That is a Gutters Area and once you do right click on it - you may enable / disable some gutters already installed. Also, gutters can be clickable, and on click handler you may also call Sitecore commands, so why not to call our familiar item:setlayoutdetails that opens Device Editor dialog for corresponding item?

So, let's create our own gutter. Every gutter is configured within core database under /sitecore/content/Applications/Content Editor/Gutters folder. We are going to create a new item called ... derived from /sitecore/templates/Sitecore Client/Content editor/Gutter Renderer template (all gutters derive from that one). There are only two fields we need to set there - Header which is just a gutter name and Type - fully qualified class name:

So now let's implement PresentationExists class. Briefly, every gutter derives from GutterRenderer class which returns GutterIconDescriptor object when gutter should be shown next to corresponded item otherwise just null. Implementation below checks whether current item has a Layout associated, and if yes - it returns a GutterIconDescriptor with a item:setlayoutdetails command for that item.
public class PresentationExists : GutterRenderer
{
    protected override GutterIconDescriptor GetIconDescriptor(Item item)
    {
        if (item != null)
        {
            var layoutField = item.Fields[Sitecore.FieldIDs.LayoutField];
            var layoutDefinition = LayoutDefinition.Parse(LayoutField.GetFieldValue(layoutField));

            if (layoutDefinition != null && layoutDefinition.Devices.Count > 0)
            {
                GutterIconDescriptor gutterIconDescriptor = new GutterIconDescriptor
                {
                    Icon = "Applications/32x32/window_colors.png",
                    Tooltip = Translate.Text("Presentation is set for this item.")
                };

                if (item.Access.CanWrite() && !item.Appearance.ReadOnly)
                {
                    gutterIconDescriptor.Click = string.Format("item:setlayoutdetails(id={0})", item.ID);
                }
                return gutterIconDescriptor;
            }
        }

        return null;
    }
}
So as soon as you compile and place resulting DLL under <web_root>\bin folder, your gutter wil work like below:

Clicking that icon will immediately show Device Editor dialog. Job's done!

Downloads: you can access source code at Sitecore Improvements project GitHub page, or you can download ready-to-use package by this link.

Please note: improperly implemented gutters may affect performance of Content Editor, as the code above runs for each item. So please be extremely attentive on what you're doing within GetIconDescriptor() method.

StackOverflow: Including MVC in existing Sitecore Project

Recently one chap has asked a question oh how to include MVC into existing Sitecore project. A guy coming from classical ASP.NET MVC background experienced confusion with MVC implemented in Sitecore (here's an original link on StackOverflow). I decided to give a comprehensive answer on how MVC work with Sitecore:


Answer: In the very simplest way, you need to have the following:

  1. Item for your page, the one that has URL; that is as normal in Sitecore
  2. That page Item should have Layout assigned. From Presentation --> Details menu select at least a layout on that stage. If you do not have layout yet, you need to create a layout definition item under /Layout/Layouts folder and associate it with certain *.cshml file. Also mention that layout should have a placeholder where you will "inject"your rendering.

    @Html.Sitecore().Placeholder("Main")
    
  3. You need to create a Controller Rendering under /Layout/Renderings folder in Sitecore. Make sure you set Controller and Controller Action fields to your controller name and action method name. enter image description here

  4. Finally, go again to Presentation --> Details --> Edit --> Controls and add your newly created rendering into a placeholder that you have on your layout *.cshtml file. enter image description here

That's all done.


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.