Thursday, February 6, 2014

Media Items are not displaying... Why?

In Sitecore, there are many reasons why your media may not show up.  Depending on the reason it could even cause a problem in your page preview.

Versioning
There are two categories of Media templates in Sitecore; versioned and unversioned.

If you image will not display, make sure that it is either of an unversioned template (you can swap between the two) or that a version exists in the language you are trying to view it in.

Publishing
While this may seem obvious, you may not think about it when adding an image to a field on a template.

When the item you referenced the image on is published, it does not automatically publish the related media item.

Using workflows, there is a work around for this one.  With a little extra code that is.

Alex Shyba wrote an article describing how to automate the publish of related media items which can be found here.

Of course no solution is going to be perfect, so double check the publish status of an image if it is not showing up.

Friday, January 24, 2014

Dynamic Key Placeholders

Dynamic Key Placeholders
This is an overview of Dynamic Key Placeholders and how to create them a video will be created later of this content.  The code for this was posted by Daveleigh at trueclarity.wordpress.com in his article about this subject, note the original implementation of this was based on that found in the article by Nick over at Techniphoria414

Placeholder Limitations
When developing a site in Sitecore there may be a time where you need to have the same layout on a page multiple times.  

The problem with this is that all Placeholder paths must be unique.  Note that I said paths as you can have the same placeholder key on a page multiple time as long as it is nested under different placeholders.  

This can cause a problem when you need to have something like a 2 column layout followed by a 3 column layout and another 2 column layout on the same page.  If you have a layout designed for a news tout, and want multiple on the page.

Usually this is solved by creating multiple sublayouts with different placeholders.  This is not the easiest way to accomplish things, and can actually get quite confusing.  Fortunately there is an easy solution.  That would be DynamicKeyPlaceholders.

What is it?
Dynamic Key Placeholders is an override on the Sitecore Placeholder that increments the key with every instance causing your placeholders to always be unique.  

How It works
A dynamic placeholder looks confusing at first look, but the process is actually quite simple.
  • Find the current placeholder
    • Get the Placeholder Stack
    • Peek at the top of the stack (the last item added)
  • Get current container within that placeholder
    • Get the Renderings from the Context Page (Sitecore.Context.Page.Renderings)
    • Filter them by the current Placeholder Key
    • Check if they have already been added to the page
    • Take the last rendering from the list (the current rendering)
  • How many times does this rendering exist in the current placeholder
    • Filter the Renderings in the current Placeholder by RenderingItem to find all instances of this Rending
    • Take the count of this result
  • Create our Placeholder with Dynamic Key
    • Create a Sitecore Placeholder
    • Set the Key to our Key name with the rendering count appended
    • Add the Placeholder to the page and expand it
How to Implement it
The implementation of dynamic key placeholders is actually more simple than the code behind it. 
  • Add the code to your library (found at the bottom of this post)
  • Register the prefix on your page (Replace Italicized text with your implementation specific values)
    • <add tagPrefix="Prefix Name" namespace="Your Namespace" assembly="Your Assembly Name" />
  • Add your placeholder (Replace Italicized text with your implementation specific values)
    • <Prefix Name:DynamicKeyPlaceholder ID="PlaceholderId" runat="server" Key="KeyName" />
  • Use your placeholder as usual keeping in mind the incrementing key
Dynamic Key Placeholders are not only simple to implement, but prove to be very useful.  They allow you to have very dynamic layouts and offer more flexibility to your clients.

Code:
using System.Collections.Generic;
    using System.Linq;
    using System.Web.UI;
    using Sitecore.Common;
    using Sitecore.Layouts;
    using Sitecore.Web.UI;
    using Sitecore.Web.UI.WebControls;

    /// <summary>
    ///
    /// </summary>
    public class DynamicKeyPlaceholder : WebControlIExpandable
    {
        protected string _key = Placeholder.DefaultPlaceholderKey;
        protected string _dynamicKey = null;
        protected Placeholder _placeholder;

        /// <summary>
        ///
        /// </summary>
        public string Key
        {
            get { return _key; }
            set { _key = value.ToLower(); }
        }

        protected string DynamicKey
        {
            get
            {
                if (_dynamicKey != null)
                {
                    return _dynamicKey;
                }
                _dynamicKey = _key;

                // Find the last placeholder processed.
                Stack<Placeholder> stack = Switcher<Placeholder,
                    PlaceholderSwitcher>.GetStack(false);
                Placeholder current = stack.Peek();

                // Group of containers which sit in the current placeholder (i.e. they have the same placeholder id).
                var renderings = Sitecore.Context.Page.Renderings.Where(rendering => (rendering.Placeholder == current.ContextKey || rendering.Placeholder == current.Key) && rendering.AddedToPage).ToArray();

                // Current container
                var thisRendering = renderings.Last();

                // get all repeating containers in the current placeholder
                renderings = renderings.Where(i => i.RenderingItem != null && i.RenderingItem.ID == thisRendering.RenderingItem.ID).ToArray();

                // Count represents how many of the same container have already been added to the page
                if (renderings.Any())
                {
                    _dynamicKey = _key + renderings.Count();
                }
                return _dynamicKey;
            }
        }

        protected override void CreateChildControls()
        {
            _placeholder = new Placeholder {Key = DynamicKey};
            Controls.Add(_placeholder);
            _placeholder.Expand();
        }

        protected override void DoRender(HtmlTextWriter output)
        {
            base.RenderChildren(output);
        }

        #region IExpandable Members

        /// <summary>
        ///
        /// </summary>
        public void Expand()
        {
            EnsureChildControls();
        }

        #endregion
    }

Thursday, January 23, 2014

Languages in Sitecore

Languages in Sitecore
This is a brief overview of languages in Sitecore and Language fallback.  You can find a video on this here.

Quirks of Languages in Sitecore
Sitecore out of the box has some quirks when it comes to languages.  These are not flaws with Sitecore, but just things to keep in mind.

First the default language is non-regionalized English en whereas the other 4 available client languages are regionalized such as Danish which is regionalized to Denmark as da-DK.   This is likely due to the more global nature of English compared to the other available client languages.

Do keep in mind that though there are only 5 standard client languages, you can have as many content languages as you want.  The client language is just the language used in the Sitecore environment.

Inability to change content language
You cannot simply change the language of an item.  If you wish to change an item’s language you must create a new version of that item in the language you want it to be in and then copy the content over. 

As this is a tedious process make sure you know what language you want your content to be in before you enter any content.  

You don’t want to enter everything in United States English and find out later that the site is actually going to be featured in Europe and need to add everything again in British English

Lack of fallback support
For most users this setup is not a big deal as they will likely be in a single language or region.  

Though this can get tricky when you go into needing region specific languages as by default there is no fallback when content does not exist in a language.

For example, if you request an item in en-US or en-GB that exists, but does not have content in that regionalized language, it will simply return a null item, even if there is a version in the non-regionalized en. 

Language Fallback
Fortunately there is a shared source module called the Language Fallback Item Provider that does a pretty good job at resolving this issue. 
  • What is it?
    • The Language Fallback Item Provider shared source module can be found in the Sitecore Marketplace found here.
    • This module adds a field to the registered language item that allows us to select a language to fall back to if the item does not exist in the selected language.  
    • You must register every language that may be requested and assign it a fallback language.  Do note that you can only have one fallback language for each registered language. 
  • How does it Work?
    • Language Fallback works by first checking if the selected item exists in the current language.  
      • If it exists then it returns the item.  
      • If it does not exist it checks the registered language item.  If the language is registered and has a fallback language it will switch the context to that language and try again. 
    • This process is repeated until an item is found or until there is no Fallback Language, in which case it will return a stub item which is basically an empty item with standard values.


Partial Language Fallback
Partial Language Fallback is a Field Level fallback that offers far more control in how fallback works.

  • Field Level Fallback
    • At a field level you have the ability to enable and even enforce language fallback.  This allows you to have only the content you want fall back, such as banners and images.
    • Enforcing fallback causes the value from the content in the fallback language to be brought over much like a standard value.  It will keep in sync with the fallback content until it is modified and the link is broken.
  • Easy Regionalization of Content
    • Since enforced fallback works similar to standard values you can populate a base language such as English (en) with content, and then create regionalized versions (en-US, en-GB, ets...) that fallback to that base and the content will be brought over similar to a standard value.  This is quite helpful when there are only small differences between the regions.
  • Control
    • In your site definition you can enable fallback for a specific site, you can also require a items to have a version in the content language before any fields will fall back.



Possible Problems
There are a few problems that you might run into with language fallback, again none of these are really flaws with the system, just things to note.
  • Circular References
    • Though you can chain fallback, you need to watch out for circular links such as en-US falling back to en and then en falling back to en-US as this could potentially cause an infinite loop when trying to find the item.  Though the code likely has a catch for this it can cause performance problems, and can be unpredictable.
  • Unexpected or Incorrect Content
    •  If a page is requested and there is no content for that page, or some content on the page is not available in the current language.
      • If there is not fallback for the language or there is no content in the fallback language, the page may not display correctly.  
      • If you fallback multiple times, you may get content you were not expecting.
    • Unfortunately there is no default for language fallback, this means that if there is not a fallback language set for a language it will not default to any language.  It just simply will not fall back.



In Sitecore it is important to understand how languages work and the quirks associated with them.

Even though Language Fallback is available it should not always be relied on.  

From a content or code point of view.  The site should function with or without it enabled, you must always be aware of the content available and what languages may be requested.  

Having a language fallback plan setup prior to the content being deployed is key to preventing possible fallback problems and rework.