Author: vindaav

Sitecore Content Editor: Performance Tips

Sitecore Content Editor: Performance Tips

While Sitecore continues to extend Content Editor functionality to the Experience Editor, Content Editor remains the interface of choice for developers and power users. Its performance can significantly impact the productivity of any development team. With the fairly simple adjustments I outline here, you can optimize Sitecore Content Editor performance and usability.

Continue reading “Sitecore Content Editor: Performance Tips”

Sitecore: Security best practices

From time to time developer faces with the need to perform some action with the item in the scope of administrative user. In such case there are two possibilities:
SecurityDisabler and UserSwitcher.

Both of them allows developer to solve the task.  So, let’s what is the difference between them and which of them is most preferable to use.

Continue reading “Sitecore: Security best practices”

Log4net: Including stack trace into the logs

The log4net version included in Sitecore doesn’t contains the stack trace. That means that you cannot use %stacktrace or %stacktracedetail in the conversionsPattern.

I have found the way of how to do it. As a workaround, you should override the appender!

First create the following class:

public class SitecoreLogFileWithStackTraceAppender : SitecoreLogFileAppender
{
 protected override void Append(LoggingEvent loggingEvent)
 {
 var msg = loggingEvent.MessageObject as string;
 if (msg != null)
 {
 var prop = loggingEvent.GetType().GetField("m_data", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
 var mData = (LoggingEventData)prop.GetValue(loggingEvent);
 mData.Message = $"{msg}{Environment.NewLine}{Environment.StackTrace}";
 prop.SetValue(loggingEvent, mData);
 }
base.Append(loggingEvent);
 }
}

Second step, register newly created log4net appender:

<appender name="StackFileAppender" type="AndreyVinda.Loggers.SitecoreLogFileWithStackTraceAppender, AndreyVinda.Loggers">
 <file value="$(dataFolder)/logs/log.Stacktraces.{date}.txt" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%5t %d{yyyy-MM-dd HH:mm:ss.fff} %-5p %c - %m%n%n" />
</layout>
</appender>

For one of my projects I have chosen to log all the errors and all the messages that contains [SD] within the stacktrace. The config file is the following:

<appender name="StackFileAppender" type="AndreyVinda.Loggers.SitecoreLogFileWithStackTraceAppender, AndreyVinda.Loggers">
 <file value="$(dataFolder)/logs/log.Stacktraces.{date}.txt" />
<filter type="log4net.Filter.StringMatchFilter">
<stringToMatch value="[SD]"></stringToMatch>
</filter>
<filter type="log4net.Filter.DenyAllFilter" />
<appendToFile value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%5t %d{yyyy-MM-dd HH:mm:ss.fff} %-5p %c - %m%n%n" />
</layout>
</appender>

Enjoy!

Sitecore: Force of Query String Parameters

Sitecore is a web based system and just like to others systems it uses query string parameters to pass viable data. They are used to explicitly configure such important things as display modes, sites, languages etc. Remembering of those tricky things could have a huge speed improvement in cases when dealing with multi-language, multi-device or page editor enabled solutions. Below is the list of the Sitecore query string parameters that I have been using in my day-to-day job.

Continue reading “Sitecore: Force of Query String Parameters”

Sitecore Custom Tokens

Out of the box, Sitecore comes with the following expand standard values tokens:

  • $name – Name of the item
  • $date – Current server date
  • $time – Current server time
  • $now – Current server date time
  • $id – Item ID
  • $parentid – Item’s Parent ID
  • $parentname – Item’s Parent Name

Sometimes the already existing tokens are not enough. There are cases in which the Content Editors won`t be able to access the value that needs to be populated (ex. – webservice call) or it will be hard for them to do it (ex. – the value of the item varies on many other items). In the current example, the $next token will be implemented. It will automatically replace the token with the current siblings’ count plus one  – this token is usually used in cases where there is a requirement for auto-incrementing sort order of items.

When it comes down to creating your own custom tokens, there are basically two options to choose from:

  1. Extend the MasterVariablesReplacer class
  2. Extend the ExpandInitialFieldValueProcessor class

The first option involves extending and overriding default functionality of the class, that provides the replacement mechanism for all the standard Sitecore tokens. This approach is explained in John West’s blogpost on how to add custom standard value tokens to Sitecore. It should be noted, that extending from the MasterVariablesReplacer class requires some method overriding. Be aware, that since the class is not really meant for extending in the first place you’ll have to duplicate a great amount of the private members into your own custom implementation.

The other option is the inheritance from the ExpandInitialFieldValueProcessor class, which is my preferred way to create replacement mechanisms for custom tokens in Sitecore. Using the ExpandInitialFieldValueProcessor is really easy, as it only requires you to extend from the base class and implement the void Process(ExpandInitialFieldValueArgs args) method:

namespace AndreyVinda.Processors
{
    using Sitecore.Pipelines.ExpandInitialFieldValue;

    public class TokenNextProcessor : ExpandInitialFieldValueProcessor
    {
        public override void Process(ExpandInitialFieldValueArgs args)
        {
            if (args.SourceField.Value.Contains("$next"))
            {
                if (args.TargetItem != null &amp;&amp; args.TargetItem.Parent != null &amp;&amp; args.TargetItem.Children != null)
                {
                    args.Result = args.Result.Replace("$next", args.TargetItem.Parent.Children.Count.ToString());
                }
                else
                {
                    args.Result = args.Result.Replace("$next", "0");
                }
            }
        }
    }
}

The code is pretty straightforward. It checks if the value of the field contains the $next token. If it does it checks if the parent is not null and the parent has children. If the parent is not null and there are children the value is set to the children`s count (the processor is executed after the child is added so the index will be 1 based), otherwise it sets the value to 0.

Once the token replacer is implemented, all that is left to do is to patch in the processor into the Sitecore pipeline config section for the expandInitialFieldValue pipeline:

<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <expandInitialFieldValue>
        <processor type="AndreyVinda.Processors.TokenNextProcessor , AndreyVinda.Processors" patch:after="processor[@type='type=Sitecore.Pipelines.ExpandInitialFieldValue.ReplaceVariables, Sitecore.Kernel']"/>
      </expandInitialFieldValue>
    </pipelines>
  </sitecore>
</configuration>

Enjoy!

Sitecore: Excursion though Admin pages

It is doubtful that there is a Sitecore Developer who never opened /sitecore/admin/showconfig.aspx at least once in his life to check what went wrong with the amazing configuration patch that hadn`t worked. Showconfig is just one of the many admin pages that Sitecore provided by default. Other admin pages are not so popular, so I decided to talk about them in more detail.

Continue reading “Sitecore: Excursion though Admin pages”

Sitecore Adaptive Images – Huge Crawling Logs Problem

Some time ago I have noticed that on our production environment the Crawling Log files were abnormally big – between 500 MB and 1 GB. After some digging was found out that they were just filling up with exceptions while crawling the media library. The exceptions look like this:

WARN Could not compute value for ComputedIndexField: urllink for indexable: sitecore://master/{8EA15044-EE2C-41DB-81D6-0A9C42062814}?lang=en&amp;ver=1
Exception: System.NullReferenceException
Message: Object reference not set to an instance of an object.
Source: Sitecore.Kernel
at Sitecore.Context.PageMode.get_IsNormal()
at adaptiveImages.AdaptiveImagesMediaProvider.GetMediaUrl(MediaItem item)
at Sitecore.ContentSearch.ComputedFields.UrlLink.ComputeFieldValue(IIndexable indexable)
at Sitecore.ContentSearch.LuceneProvider.LuceneDocumentBuilder.AddComputedIndexFields()

Considering the case that there are a tons of media (over 2000 items) and languages (there is a separate exception for each language) we had some pretty serious index time performance issues and hard disk space problems.

Continue reading “Sitecore Adaptive Images – Huge Crawling Logs Problem”