Authentication Ticket Cleanup in Sitecore

Whenever an user gets logged in Sitecore CMS, Sitecore creates an authentication ticket in Properties table of Core database.

Sometimes Sitecore CMS login become slow with time and based on the number of users accessing the CMS. This is because of the large number of ticket records being stored in the Properties table.

Recently we faced this issue with Sitecore 9.0 update 2, in our case its was throwing 500 error and not redirecting us to launchpad (sitecore/client/Applications/Launchpad).

To fix this issue we run the below query on core DB and this worked for us.

delete FROM [dbo].[Properties]
WHERE [Key] LIKE ‘%TICKET%’
AND [VALUE] LIKE ‘%sitecore\virtualssuser%’

We raised this issue for RCA with Sirecore and came to know The issue is caused by a bug #223702 that was fixed in Sitecore 9.1.0 (release notes).

To fix this with current version they have provided the the below patch
https://sitecore.box.com/s/q9ibufmmpnnph534gml7ii4wxtosuo7c

Advertisements

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”

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