Multiple Datasource Treelist Field

Many times we have realized the need of Treelist field which can take multiple datasource from different locations.
Suppose we have article which author can be from “Management Team” and “Board of directors”.

If we have such a need we can create our own custom field named “MultiDatasourceTreeList” in the core database at the location “/sitecore/system/Field types”-

1. Create a folder “Custom Type”
2. Add a field with name “Multi Datasouce Treelist” in this folder of the template type “/sitecore/templates/System/Templates/Template field type”
3. Add the Assembly and class details which extend the functionality of sitecore out of the box tree list class.

using System;
using System.Linq;
using Sitecore.Diagnostics;
using Sitecore.Globalization;
using Sitecore.Shell.Applications.ContentEditor;
using Sitecore.Text;
using Sitecore.Web;
using Sitecore.Web.UI.HtmlControls;
using Sitecore.Web.UI.WebControls;


namespace CommonLibrary
{
    public class MultiDatasourceTreeList : TreeList
    {
        protected override void OnLoad(EventArgs args)
        {
            Assert.ArgumentNotNull(args, "args");
            base.OnLoad(args);

            if (!Sitecore.Context.ClientPage.IsEvent)
            {
                var existingTreeView = (TreeviewEx)WebUtil.FindControlOfType(this, typeof(TreeviewEx));
                var treeviewParent = existingTreeView.Parent;

                existingTreeView.Parent.Controls.Clear();
                
                var dataContext = (DataContext)WebUtil.FindControlOfType(this, typeof(DataContext));
                var dataContextParent = dataContext.Parent;

                dataContextParent.Controls.Remove(dataContext); 
               
                var MultiRootTreeView = new Sitecore.Web.UI.WebControls.MultiRootTreeview();
                MultiRootTreeView.ID = existingTreeView.ID;
                MultiRootTreeView.DblClick = existingTreeView.DblClick;
                MultiRootTreeView.Enabled = existingTreeView.Enabled;
                MultiRootTreeView.DisplayFieldName = existingTreeView.DisplayFieldName;
               
                var dataContexts = ParseDataContexts(dataContext);

                MultiRootTreeView.DataContext = string.Join("|", dataContexts.Select(x => x.ID));

                foreach (var context in dataContexts)
                {
                    dataContextParent.Controls.Add(context);
                }

                treeviewParent.Controls.Add(MultiRootTreeView);
            }
        }
               
        protected virtual DataContext[] ParseDataContexts(DataContext originalDataContext)
        {
            return new ListString(DataSource).Select(x => CreateDataContext(originalDataContext, x)).ToArray();
        }

        /// 
        /// Creates a DataContext control for a given Sitecore path data source
        /// 
        protected virtual DataContext CreateDataContext(DataContext baseDataContext, string dataSource)
        {
            DataContext dataContext = new DataContext();
            dataContext.ID = GetUniqueID("D");
            dataContext.Filter = baseDataContext.Filter;
            dataContext.DataViewName = "Master";
            if (!string.IsNullOrEmpty(DatabaseName))
            {
                dataContext.Parameters = "databasename=" + DatabaseName;
            }
            dataContext.Root = dataSource;
            dataContext.Language = Language.Parse(ItemLanguage);

            return dataContext;
        }
    }
}

For author take the filed type “Multi Datasource Treelist” with Pipe (|) separated datasouce: Datasource=/sitecore/content/Home/Management Team|/sitecore/content/Home/Board of Directors

Finally at article you will able to select authors form both the section “Management Team” and “Board of directors”

Advertisements

Sitecore RTE Code Snippet

A snippet is a small piece of html that can be pasted into RTE field on a clicks. When there is need to write a formatted html structure again and again, the code snippet is easy way to achieve this.
Suppose you need to insert question and answer set like below and you have to insert multiple set of questions and answers, this will be very easy for content editor to create through snippet

How to create snippet-
1. Move to core database in Sitecore
2. Navigate to the below snippets folder where the snippet will be created:
/sitecore/system/Settings/Html Editor Profiles/Rich Text Full/Snippets

3. Create a snippet using the following template:
/sitecore/templates/System/Html Editor Profiles/Html Editor Snippet

This template has two fields
Header: This will be snippet name which will be shown to editor when he will open RTE
Value: The value field the html that should be pasted into the html field when the editor chooses the snippet.

How to use the Snippet-
This is the easy part, as it should be. Just go to the item where you want to use the html snippet and open the html editor.
Press the ”Question & Answer” button you will see the new snippet that you have just created.

Sitecore Item Publishing- Context Menu

This article is just to reduce the step for publishing an item, currently if we have to publish an item in content tree where the editor is, we have to navigate to publish section in the ribbon and then click publish item.

How easy the item publishing will be if the user has an option to publish the item by Right clicking of selected item.

publish

I would like this as a wish to feature with upcoming Sitecore default setup.

To get this option you have to create a context menu item named “Publish Item” in core database in Context Menues section (“/sitecore/content/Applications/Content Editor/Context Menues/Default”) of the template type Menu Item ( ”/sitecore/templates/System/Menus/Menu item”) and add desired Display Name, Icon and the message item:publish(id=$Target) and finally save it.

core

Switch to master database you will able see context menu “Publish item” from where you can perform publishing.

Sitecore Workbox – Item Language Filter

Tags

Sitecore doesn’t provide the feature to filter the items in workbox based on language. If we have multilingual site then it will be good if we have language filter option like page size in workbox. If the items count in workbox is very large then this will enable the workbox user to filter the items of a specific language.

To create this filter, there are some settings in core database as well as we have to create the language filter control and have to implement the filter logic in workbox based on language selection.

There are following steps which we need to follow:

Step 1: Creating language filter control- To create this add a class file named WorkboxLanguageFilter.cs

using Sitecore.Data.Items;
using Sitecore.Globalization;
using Sitecore.Shell.Framework.Commands;
using Sitecore.Shell.Web.UI.WebControls;
using Sitecore.Web.UI.HtmlControls;
using Sitecore.Web.UI.WebControls.Ribbons;
using System.Web.UI;
using Sitecore.Data.Managers;
using System.Collections.Generic;
using System.Linq;

namespace BusinessModules
{
    /// 
    /// Represents a panel that displays workflows Language Filter.
    /// 
    /// 
    public class WorkboxLanguageFilter : RibbonPanel
    {
        /// 
        /// Renders the panel.
        /// 
        /// 
        /// The output.The ribbon.The button.The context.
        public override void Render(HtmlTextWriter output, Ribbon ribbon, Item button, CommandContext context)
        {
            Sitecore.Data.Database masterDB = Sitecore.Configuration.Factory.GetDatabase("master");
            IEnumerable languages = LanguageManager.GetLanguages(masterDB).Where(a => a != Sitecore.Globalization.Language.Parse("fr-CA"));         

            string @Language = Registry.GetString("/Current_User/Workbox/Language", "All");
            output.Write("< div class="scRibbonToolbarPanel" > ");
            output.Write("<table class="scWorkboxPageSize"><tr><td class="scWorkboxPageSizeLabel">");
            output.Write(Translate.Text("Select Language:"));
            output.Write("</td><td>");
            output.Write("<select class=\"scWorkboxPageSizeCombobox\" id=\"lang\" onchange='javascript:scForm.invoke(\"Language_Change\")'>"");
            output.Write("<option value=\"All\"" + (@Language == "All" ? " selected=\"selected\"" : string.Empty) + ">All</option>");
            foreach (Language language in languages)
            {
                string LangName = language.CultureInfo.DisplayName;
                output.Write("<option value=\"" + language.CultureInfo.Name + "\"" + (@Language == language.CultureInfo.Name ? " selected=\"selected\"" : string.Empty) + ">" + LangName + "</option>");
            }
            output.Write("</select>");
            output.Write("</td></tr></table>");
            output.Write("</div>");
        }
    }
}

Step 2: Sitecore Core database Settings- Create the highlighted Items in core DB and give your assembly reference.
coredbsettings

Step 3: Workbox filter logic – Create a class file AdvancedWorkboxForm.cs get the code of workbox by using RedGate Reflector from the dll – “Sitecore.Client” (Stecore.Shell.Applications.Workbox.WorkboxForm,Sitecore.Client)

Add the below property and update the the function in the decompiled code and update the assembly reference in below .xml file(Workbox.xml-Website\sitecore\shell\Applications\Workbox).

workboxxml

        /// 
        /// Gets or sets the Language.
        /// 
        /// 
        /// The Selected Language.
        /// 
        public string SelectedLanguage
        {
            get
            {
                return Registry.GetString("/Current_User/Workbox/Language", "All");
            }
            set
            {
                Registry.SetString("/Current_User/Workbox/Language", value);
            }
        } 

private DataUri[] GetItems(WorkflowState state, IWorkflow workflow)
        {
            Assert.ArgumentNotNull((object)state, "state");
            Assert.ArgumentNotNull((object)workflow, "workflow");
            ArrayList arrayList = new ArrayList();
            DataUri[] items = workflow.GetItems(state.StateID);
            if (items != null)
            {
                foreach (DataUri index in items)
                {
                    Item obj = Context.ContentDatabase.Items[index];
                    if (SelectedLanguage == "All")
                    {
                        if (obj != null && obj.Access.CanRead() && (obj.Access.CanReadLanguage() && obj.Access.CanWriteLanguage()) && (Context.IsAdministrator || obj.Locking.CanLock() || obj.Locking.HasLock()))
                            arrayList.Add((object)index);
                    }
                    else
                    {
                        if (obj != null && obj.Language.CultureInfo.Name == SelectedLanguage && obj.Access.CanRead() && (obj.Access.CanReadLanguage() && obj.Access.CanWriteLanguage()) && (Context.IsAdministrator || obj.Locking.CanLock() || obj.Locking.HasLock()))
                            arrayList.Add((object)index);
                    }
                }
            }
            return arrayList.ToArray(typeof(DataUri)) as DataUri[];
        }

Final Worbox filter will look like below
woboxfilter

Sitecore 8.2 in-depth preview and an update into 8.3

Tags

, ,

The main features on which sitecore XP 8.2 is shipped are

– The Express Migration tool
– Publishing Enhancements
– Platform improvements
– Experience Accelerator

The Express Migration tool Sitecore upgrade is too time consuming process and hence too expensive as all the upgrade steps are performed step by step manually. In the current approach there is lots of chances of skipping the changes which can cause risk in future to the customer and partners. The Express Migration tool make all these task easy and minimize the chances of error.

There are two versions of this tool is available as of now, Express Migration Tool 1.0 and Express Migration Tool 2.0 and below is the version wise compatibility matrix.

migrationtool

Publishing Enhancements
Sitecore 8.2 publishing service supports enterprise level publishing on a large scale by addressing the problems that come with publishing large amounts of data across multiple destinations, including the associated time and network latency issues.

In this release, these is no need of separate Sitecore instance to publish the data. You can use a non-Sitecore server to publish your content. This enhancement has made it easy to adopt Sitecore as it reduces the requirement of new infrastructure.

Platform Improvement

– Enterprise performance Sitecore putting more focus on getting startup times improved, tweaks on caching performance and releases that come fully tested against real world data sets and solutions.

– Search and indexing enhancements- this is improved by improving SOLR support
– Experience editor Enhancement- The following enhancements have been introduced in its latest version:
1. Page workflows for creation, review, and approval of web content can now be adjusted directly from the experience editor.
2. Managing page content is easier as the experience editor has been updated to show more information on data sources. This can prove to be very helpful in managing page sources.
3. Notifications are generated to inform authors on broken pages and links before they can be published.
4.The experience editor can now be used to set marketing attributes to each page.

Experience Accelerator
Sitecore Experience Accelerator helps developers and website administrator to build and modify websites in very fast manner. With the help of this various teams can work parallel and reuse of components, layouts, forms and templates across various pages, leading to faster deployment of the website.It has a drag and drop interface that allows developers to easily add components to web pages.

Sitecore XP 8.3 Updates
-The update will include new WFFM module.
-The update will also bring us the XConnect Client API that will be used by both Sitecore products and custom developed integrations (mobile, webservices, reporting, …) alike.

Other features:
– This will be Window Server 2016 compliant
– SQL Server 2016 support
– Silverlight completely removed !
– The continuation, expanded functionalities and version support of the migration tool.
– Federated authentication support

Sitecore Caching

Tags

When we talk about a website, performance play an important role. In this article I would like to explain what are the different techniques are available for caching in Sitecore and they work.

Hopefully this will hep you in improving our site performance. The different types of cache available are

1. Prefetch Cache: For each database there is a prefetch caching. In this caching the items are pull out from database during startup. This cache contains the items that Sitecore access during and just after initialization of instance. These cache are maintained during life cycle of the application.
The Items which should be loaded as prefetch are defined in the config file specified in /app_config/prefecth folder and are the combination of the items specified in the config file for the specific database (for instance master.config) and the common.config file.

prefetch

The purpose of this caching is long startup but faster load time at run time.

2. Data Cache: This is also defined for each database. the contains the items of the Sitecore class ItemInformation.
This is populated whenever they are requested. The data is pulled from the prefetch cache, if it present there; else it is pulled out of the database, put into the prefetch cache and into then the data cache.

The purpose of this cache is to minimize the amount of requests to the database. This is extremely important for performance, as requesting items from the database is rather expensive.

We can specify the maximum size of the data cache in the web.config. You can either alter the DefaultDataCacheSize setting:

  

Or you can set it per database in the /databases/database section:

 
  20MB
  10MB
  500KB
  500KB
</cacheSizes< 

3. Item Cache: Same as data and prefetch cache, there is an item cache for each database. This cache contains objects of the Sitecore class Sitecore.Data.Items.Item, which are the one we use in our code most of the time.

The items are built from the ItemInformation objects in the data cache. So if you request an item, which aren’t present in the item cache, it will get it from the data cache and then populate it in the item cache as an Item.

The purpose of this cache is to gain performance so the ItemInformation objects don’t need to get parsed into an Item each time they are requested.

4. HTML cache (Web Cache): The cache caches the actual HTML generated from sublayouts and renderings. There is a cache per site in your solution. You can configure your HTML cache per presentation control.

You can specify the HTML cache to vary on different parameters. For instance you can set it up so it varies by query strings; then there will be stored multiple versions of the HTML depending on which query string have been specified.
htmlcache

In this image you can see that I have opened the configuration of a given sublayout. I have specified that it is cachable, so it will create an HTML cache for the given page. I have also specified that the cache should vary by data, which means that the HTML should be different if the Sitecore.Context.Item is different. In this way the HTML cache will be different depending on which item you are trying to access. Further I have set up that the cache should vary by querystrings, which will cache different HTML if a querystring is different. This is great when you for instance are using paging with querystrings.

The HTML cache is really important; especially if you have renderings or sublayouts, which are rather slow. An example can be a menu which iterates over a large amount of items. When a rendering like this is HTML cached, it renders in constant time no matter how many items are to be rendered in the menu.

You can configure the allowed size of the HTML cache and whether it should be enabled or not for each of your sites. This is done in the sites section of the web.config or sitecore.config in /app_config folder. See the following line:

<site name="website" enableTracking="true" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content" startItem="/home" database="web" domain="extranet" allowDebug="true" cacheHtml="true" htmlCacheSize=”50MB” registryCacheSize=”0″ viewStateCacheSize=”0″ xslCacheSize=”25MB” filteredItemsCacheSize=”10MB” enablePreview=”true” enableWebEdit=”true” enableDebugger=”true” disableClientData=”false” cacheRenderingParameters=”true” renderingParametersCacheSize=”10MB”/>

There are few other caches in Sitecore, but they aren’t as important for performance. These are
1. XSL cache: This caches the XSLT files you have (for instance in /xsl) so they aren’t read from the disc each time you need to use it
2. Standard values cache: Caching the standard values set on your templates.
3. Paths cache: This cache binds paths (such as /sitecore/content/home) to specific IDs
4. Registry cache: This cache stores user-based registry settings

The flow of Request and Cache.
cacheflow

  • If the item which is requested has presentations which are cached, the HTML from the HTML cache is returned and the request is ended.
  • If there isn’t any HTML cached all items needed by the presentation is requested from the item cache.
  • If the items aren’t in the item cache it is retrieved from the data cache and parsed into an Sitecore.Data.Items.Item and stored in the item cache.
  • If the item isn’t present in the data cache, it is retrieved from the prefetch cache and the ItemInformation is stored in the data cache.
  • If the item isn’t in the prefetch cache it is retrieved from the database and stored in the prefetch cache as PrefetchData.

Cache Clearing:
Cache Clearing work differently depending on environment you have. The different caches are cleared like this:

HTML cache: The HTML is always cleared on publish. So whenever you publish even a single item the complete cache is cleared. This is due to the fact, that parts of the HTML can be built from multiple items, so the cache has no way of knowing if the item being published has influence on the presentation.
Item cache: The item cache is updated incrementally in an atomized way, so if an item is updated during a publish it is updated in the item cache as well. If you publish an item which might influence other items, these items are cleared as well. For example if you publish standard values or a template, that clears more than a single item.
Further the cache is completely cleared by default if you use the staging module.
Data cache: Also the data cache is incrementally updated, when changes take effect after a publish. The cache is completely cleared by default if you use the staging module. It is rebuild incrementally when the items are requested again.
Prefetch cache: Is cleared in the same way as the data cache, but the items specified in the config files are prefetched from the database.

The important part to notice here is that publishing can make quite a big impact on performance; especially if you are running in a staged environment; so you should consider your publishing strategy carefully. You often get the best result by using scheduled publish.

The all about sitecore pipelines: Creating and extending pipeline

Tags

,

Sitecore Pipelines
The pipelines define a sequence of processors and the each processor of the pipeline contains a method named Process () that accepts a single argument and returns void.

The default argument to the Process () method is Sitecore.Pipelines.PipelineArgs. This may be of the type derived class.

Sitecore separates the pipelines into two groups:
1. Those defined within the /configuration/sitecore/pipelines- [These pipelines tend to define system processes.]

Examples:
<initialize>:Initializes the Sitecore application.
<preprocessRequest>: This is invoked for each HTTP request managed by ASP.NET. It is more common to use the pipeline for request processing logic.

The processors of this pipelines are

<processortype="Sitecore.Pipelines.PreprocessRequest.CheckIgnoreFlag, Sitecore.Kernel" />

<processortype="Sitecore.Pipelines.HttpRequest.EnsureServerUrl, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.StartMeasurements, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.IgnoreList, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.SiteResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.UserResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.DatabaseResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.BeginDiagnostics, Sitecore.Kernel" />

<processortype="Sitecore.Pipelines.HttpRequest.DeviceResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.LanguageResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.CustomHandlers, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.FilterUrlExtensions, Sitecore.Kernel"> <paramdesc="Allowed extensions (comma separated)">aspx <paramdesc="Blocked extensions (comma separated)">* <paramdesc="Blocked extensions that stream files (comma separated)">css,js <paramdesc="Blocked extensions that do not stream files (comma separated)">* 

<processortype="Sitecore.Pipelines.HttpRequest.QueryStringResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.DynamicLinkResolver, Sitecore.Kernel" />

<processortype="Sitecore.Pipelines.HttpRequest.AliasResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.DefaultResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.FileResolver, Sitecore.Kernel" />

<processortype="Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.DeviceSimulatorResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel" /> 

<processortype="Sitecore.Pipelines.HttpRequest.ExecuteRequest, Sitecore.Kernel" />

2. Those defined within the /configuration/sitecore/processors – [define pipelines that operate for sitecore client UI requests and can interact with the sitecore logged in user]

Examples:
<uiAddFromTemplate>: Add an item based on a data template, branch template or command template.
<uiCopyItems>: Copy an item and its descendants.
<uiCloneItems>: Clone an item and its descendants.
<uiDeleteItems>: Delete an item and its descendants.
<uiDragItemTo>: Invoked when a user drags and drops an item to move it.
<uiDuplicateItem>: Invoked to duplicate an item.
<uiMoveItems>: Invoked to move an item and its descendants.
<uiRenameItem>: Invoked to rename an item.
<uiGetMasters>: Determines the insert options allowed for an item.
<loggingin>: When logging in.
<loggedin>: After login.
<logout>: Implements logout.
<saveUI>: When a CMS user saves an item.
<uiUpload>: Upload a media item.

Creating Custom pipelines
1. Configure Pipeline- The new pipeline can be configure through patch file, lets say customPipeline

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <customPipeline>
 
     </customPipeline>
    </pipelines>
  </sitecore>
</configuration >

2. Create a class derived from PipelineArgs

  public class CustomPipelineArgs : PipelineArgs
  {
    public string Result { get; set; }
  }

3. Create the processor class

public class CustomProcessor
{
  public void Process(CustomPipelineArgs args)
  {
    args.Result = GetResult();
  }
 
  private string GetResult()
  {
    return "Hellow world";
  }
}

4. Insert them in your config

     <customPipeline>
        <processor type="[NAMESPACE].CustomProcessor, [ASSEMBLY]" />
     </customPipeline>

5. Calling the pipeline

    var pipelineArgs = new CustomPipelineArgs();
    CorePipeline.Run("customPipeline", pipelineArgs);
    Log.Info(args.Result, this);

Extending Existing pipeline
The Pipelines are extended by adding or replacing processors.

1.Create a processor named CustomProcessor

using Sitecore.Pipelines.HttpRequest;
using Sitecore.Configuration;
using Sitecore.Web;

namespace CommonLibrary
{
    public class CustomProcessor : HttpRequestProcessor
    {
        public override void Process(Sitecore.Pipelines.HttpRequest.HttpRequestArgs args)
        {
            if (Sitecore.Context.Item != null || Sitecore.Context.Site == null || Sitecore.Context.Database == null || WebUtil.GetRawUrl().IndexOf("/sitecore") > -1)
                return;

            //Put your logic which you need to override

        }
       
    }
}

2. Let us create patch file which extend httpRequestBegin pipeline

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <httpRequestBegin>
        <!--  ITEMRESOLVER PIPELINE
              Set the context item to null if current request points to an item with an invalid (or missing) language version.
              
              NOTE: If you do not use the general ItemResolver, please change the "path:after" attribute. If you use some
              other item resolving in your project, you have to include this pipeline after your custom resolver.
        -->
        <processor  patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']"
                    type="CommonLibrary.CustomProcessor, CommonLibrary" />

      </httpRequestBegin>
    </pipelines>
  </sitecore>
</configuration>
</pre>

Consuming sitecore items using RESTful API for external system integration

Tags

Sitecore manage content very neatly in the form of tree. You can manage your organization data easily using Sitecore. Your data need to be served to the broad range of clients including web browsers, mobile, different mobile application and other integrated services of your website. The Restful API is the way to fulfill these requirements. The output can be configured in JSON or XML format.

In this post you can learn how you can create and use REST API to expose Sitecore data for your different customers and users.

1. I have created some bios in Sitecore as below

Bios

2. Let us add an interface “IBioInfo.cs”

using System.ServiceModel;
using System.ServiceModel.Web;
using CommonLibrary;

namespace SitecorePOC
{
[ServiceContract]
public interface IBioInfo
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "?ID={BioID}&All={All}")]
BioListGetBio(stringbioID, bool All);
}
}

3.Now need to add WCF Data Service in the web project. Let us add a service with name “BioInfo.svc”which will implement the interface IBioInfo.cs

Class

//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
using CommonLibrary;
using System.ServiceModel.Activation;

namespace SitecorePOC
{
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class BioInfo : IBioInfo
{
public BioList GetBio(string bioID, bool All)
{
BioList bioList = new BioList();
return bioList.GetAllBios(bioID, All);
}
}
}

4. GetBio method internally call a function GetAllBios of CommonLibrary where actual logic is implemented to get the data based on parameters

using Sitecore.Data.Items;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;

namespace CommonLibrary
{
[DataContract]
public class BioList
{
public BioList()
{
}
private List iPeople = new List();
[DataMember(Order = 1)]
public List Persons { get { return iPeople; } set { iPeople = value; } }

public BioList GetAllBios(string bioID, bool All)
{
Sitecore.Context.SetActiveSite("website");

BioList BioList = new BioList();
List item = new List();

//Getting a specific bio feed based on its GUID
if(!string.IsNullOrEmpty(bioID))
{
var bioItem = Sitecore.Context.Database.GetItem(bioID);
if (bioItem != null)
{
Bios bio = new Bios()
{
Title = bioItem.Fields["Title"].Value,
Email = bioItem.Fields["Email"].Value,
GUID = bioItem.ID.ToString(),
FirstName = bioItem.Fields["FirstName"].Value,
LastName = bioItem.Fields["LastName"].Value
};
item.Add(bio);
}

}

//Getting all bio feed irrespective of GUID
if (All)
{
var Bios = Sitecore.Context.Database.GetItem("/sitecore/content/Home/Bios").Children;
foreach (Item bioItem in Bios)
{
Bios bio = new Bios()
{
Title = bioItem.Fields["Title"].Value,
Email = bioItem.Fields["Email"].Value,
GUID = bioItem.ID.ToString(),
FirstName = bioItem.Fields["FirstName"].Value,
LastName = bioItem.Fields["LastName"].Value
};

item.Add(bio);
}
}

return new BioList
{
Persons = item.ToList()
};
}
}
}

5. You need to add a DataContract

using System.Runtime.Serialization;
namespace CommonLibrary
{
[DataContract]
public class Bios
{
[DataMember(Order = 0)]
public string GUID { get; set; }
[DataMember(Order = 1)]
public string Title { get; set; }
[DataMember(Order = 2)]
public stringFirstName { get; set; }
[DataMember(Order = 3)]
public stringLastName { get; set; }
[DataMember(Order = 4)]
public string Email { get; set; }
}
}

6. In web.config file just add the behavior and service

<system.serviceModel>
<bindings>
<basicHttpBinding>
<bindingname="SitecoreApplicationCenter"closeTimeout="00:01:00"openTimeout="00:01:00"receiveTimeout="00:20:00"sendTimeout="00:05:00"allowCookies="false"bypassProxyOnLocal="false"hostNameComparisonMode="StrongWildcard"maxBufferSize="65536"maxBufferPoolSize="524288"maxReceivedMessageSize="65536"messageEncoding="Text"textEncoding="utf-8"transferMode="Buffered"useDefaultWebProxy="true">
<readerQuotasmaxDepth="32"maxStringContentLength="8192"maxArrayLength="16384"maxBytesPerRead="4096"maxNameTableCharCount="16384" />
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behaviorname="web">
<serviceMetadatahttpGetEnabled="true" />
<serviceDebugincludeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<servicename="SitecorePOC.BioInfo"behaviorConfiguration="web">
<endpointaddress=""binding="webHttpBinding"contract="SitecorePOC.IBioInfo"></endpoint>
</service>
</services>
<serviceHostingEnvironmentaspNetCompatibilityEnabled="true" />
</system.serviceModel>

7. After building the project when you will hit the urls you will able to get output as XML which can be consumed anywhere.
i. http://sitecorepoc/bioinfo.svc/?All=true

XML

ii. http://sitecorepoc/bioinfo.svc/?ID={DD87A2B9-0D43-4EB7-A54B-8B113B27F06A}

XMLId

To Get JSON output you need to change WebMessageFormat from Xml to Json

Json

http://sitecorepoc/bioinfo.svc/?ID=DD87A2B9-0D43-4EB7-A54B-8B113B27F06A

JsonFeed

Sitecore Custom Cache

Sitecore provide a mechanism for creating your own custom cache. This will very useful in the case if there are some data which retrieval take much time due to complex logic or data manipulation. So calling this data on each web request for each user, you can cache in your custom cache and serve the data from there which will improve the performance. Sitecore.Caching.CustomCache is base class for custom cache.

To implement custom caching we need to create following classes
1. CustomCache
2. CacheManager

CustomCache– This will be your own custom class in this case “CustomCache”, Sitecore.Caching.CustomCache is abstract class so rather than instantiating it we need to inherit.

namespace SitecorePOC
{
  public class CustomCache : Sitecore.Caching.CustomCache
   {
     public CustomCache(string name, long maxSize) : base(name, maxSize)
     {

     }
     new public void SetString(string key, string value)
     {
         base.SetString(key, value);
     }
     new public string GetString(string key)
      {
         return base.GetString(key);
      }
   }
}

CacheManager– This is needed for managing your custom cache, this instantiate CustomCache object in the constructor, where we can pass cache name which will appear on cache manager window (http://domain/sitecore/admin/cache.aspx) and size.

public static class CacheManager
{
   private static readonly CustomCache Cache;
   static CacheManager()
   {
      Cache = new CustomCache("OwnCustomCache", StringUtil.ParseSizeString("500KB"));
   }
   public static string GetCache(string key)
   {
     return Cache.GetString(key);
   }

   public static void SetCache(string key, string value)
   {
      Cache.SetString(key, value);
   }
}

Implementation-
You can set and get cache value as below in your code

 CacheManager.SetCache("myData", "Your data which you want to cache"); // cache key and Value
 string cachedData = CacheManager.GetCache("myData");

After browsing the page you will able to see your cached data from
http://domain/sitecore/admin/cache.aspx

cache

Sitecore Best Practices

Tags

,

Sitecore best practices are designed for the ease of editor, site performance (Sitecore client and website) and site maintainability. This will help Sitecore developers and administrators create optimized websites.

Below are the areas where we need to validate the best practices but this is not complete one, will be evolving in nature.

  1. Templates and _Standard Values
  2. Information / Content Architecture (IA)
  3. Security
  4. Workflow
  5. Media
  6. Caching
  7. Presentation
  8. Page Editor
  9. Solution Code
  10. System Architecture

1.    Templates and _Standard Values

  • Naming Conventions: Name of templates, its section and field should be simple, relevant and easy to understand. This should be business name which content editor can easily understand. Use the Title field of the definition item to present a different name for the field to the user
  • Folder Structure for Templates: The folder structure should be such a way that it would easy to navigate. For this create the templates folder like “Base Templates”, “Content Templates”, “Page Templates” etc.
  • Inheritance: Analyze the site fields and put the common fields and section in “Base Templates” and inherit these to wherever required rather than creating new fields. For example- Create a base template “Navigation” with fields “BrowserTitle”,”BrowserTitle”, “HideInSearch” etc. As these field are required on each and every pages so rather than creating field on each page template just inherit “Navigation” Template on page Template.
  • Avoid duplicate field name: Don’t create two fields with same name on template and also avoid the duplicity of field name in inheritance chain.
  • Template Icons: Assign icons on templates which will provide visual clue for content editor on type of item type will get created.
  • Help Option: Use the Help option in the individual field definition items to provide extra information to users about field.
  • Standard Values: Assign layout details, insert option, initial workflow on standard value. Use tokens, such as $name, $date to reduce the amount of text that a content author is required to enter when creating a new item.
  • Image field: While defining a field of type image provide source field, which will take editor to the defined source path in media library on during content editing, not the entire media library.

2.    Information/ Content Architecture (IA)

  1. Number of child items of given node should not be more than 100. This will improve the performance.
  2. Number of versions of an item should not be more than 10. You can manage version number by shared source module- http://trac.sitecore.net/VersionManager
  3. For content editor, hide standard fields to improve the performance.
  4. Don’t put JS or define structure in RTE, this should be part of business logic not of RTE field
  5. For showing big tree use TreelistEx instead of Treelist becuase TreelistEx only computes the tree when you click Edit whereas a Treelist will compute it every time it is rendered.
  6. Structure of item in tree define the URL by default, so keep in mind while creating folders in content tree because that will be part of URL.
  7. Put all the items inside home which have public URL / landing page.

3.    Security

  1. Apply security to roles rather than users, if a new user will get added then only need assign the role, the same permission will get applicable for new user.
  2. Limit access to the parts of the content tree that are relevant to the user that is logged into the system. For example, a person who is responsible for news items may not require access to the Event page.
  3. Sitecore client password should not be empty or obvious.
  4. Use admin account for administration purpose only not for content editing etc.

4.    Workflow

  1. Sitecore recommend to enable workflow, this will ensure the content will go on live website through a pre-defined approval states. This is useful for auto versioning of item on edit.
  2. Apply appropriate workflow security.
  3. Avoid email notification on every workflow state.

5.    Media

  1. The recommended practice says put the media in database, this simplifies publishing and deployment of media assets.
  2. The folder structure of the media library should be organized so that it is easy to navigate for non- technical users.
  3. Media item name should be easy to recognize and understand for business users.
  4. Media items should be optimized, using a graphics program such as Photoshop to decrease the size of a rendered page thereby increasing performance. Use sprite images where ever possible.
  5. Include the path to static media items (header images, CSS files, JavaScript files, and so on.) in the IgnoreUrlPrefixes setting located in the web.config file. This will prevent those media items from being processed through the Sitecore pipelines, improving performance.

6.    Caching

  1. Sitecore recommends to configure and tune the Sitecore database caches — prefetch, data, and item. Use the below link for the same. http://sdn.sitecore.net/upload/sitecore6/sc62keywords/cache_configuration_reference_us.pdf
  2. Cache the expensive logic and components that are retrieved frequently http://sdn.sitecore.net/upload/sitecore6/64/presentation_component_reference-usletter.pdf

7.    Presentation

  1. Limit the number of layouts in favor of sublayouts. The aim should be to have one layout per site per device
  2. Assign presentation details on the _standard values whenever possible
  3. To enable experience editor use FieldRenderer or the other Sitecore presentation controls.
  4. Use image scaling and resizing for smaller or thumbnail from large image.
  5. Make sure to use the DataSource .This facilitates creating multi-variant tests (A/B) and personalization rules.
  6. Use presentation components parameters to change the behavior of components in term of look and feels etc.
  7. Make sure to create a template for any parameters in the presentation component, and set the Parameters Template Property.

8.    Page Editor

  1. Sitecore recommend to enable and configure page editor for non-technical content editor.
  2. Configure the placeholder settings so that users are able to add the right components to the page.
  3. Consider using the Page Editor buttons, and the Datasource Location, and Datasource Template fields

9.    Solution Code

  1. Sitecore highly recommend do coding in C#.
  2. Use GUIDs where possible instead of path / name. This will improve performance, as well as prevent any breakage if you move content to a new location in the content tree.
  3. Use patch file in App_Config/Include rather than directly modifying web.config file.

10.   System Architecture

  1. The Web server(s) should run IIS 7.x with the latest security updates
  2. You use IIS 7.x in integrated mode.
  3. The Web and Database servers should be on separate computers.
  4. Implement maintenance plans to defragment indexes on the core, master, and web databases on a scheduled basis on SQL Server
  5. Enable static content compression in IIS
  6. Make sure that the content expires header is set in the common headers, particularly for the /sitecore folder in IIS
  7. Refer the links https://kb.sitecore.net/articles/087164 for sitecore compatibility of OS, database and .Net framework with Sitecore versions.