The Right Way to Perform a Custom Save Action in Sitecore

August 23, 2016

Blog | Development | The Right Way to Perform a Custom Save Action in Sitecore
Sitecore: The Right Way to Perform a Custom Save Action

Over time, a problem that plagues many Sitecore installs is sluggishness – the overall sense that things are slow or not as responsive as they once were.  Server performance and capacity issues aside, these issues often manifest themselves within the content editor (or page editor, but we’ll focus on content editor in this post) in the form of save actions taking longer than they once did or the user interface “freezing” for a moment unexplainably.  Often this culprit is a large number of custom save actions.

A simple search will yield countless examples of implementing custom save actions, or more broadly any focused user interaction (e.g. saving, publishing, copying, renaming) – that are initiated by user interaction.  Each one of these interactions from the user initiates a handler as defined in the web.config and supporting configuration files.  Many handlers are included with Sitecore – after all, something needs to happen when you hit save.

This post is intended to address the custom save actions that occur on top of what already occurs in native Sitecore.

Stop Hijacking the GUI

I will zero in on the save event, but the sentiment applies to all focused interactions as mentioned previously.

All of these events are synchronous by their nature, which means Sitecore must execute each handler one after the other.  While this is occurring, the user interface is frozen.  With enough custom handlers the end result can be a save action that takes 2, 3, 5+ seconds to complete.  The time taken is going to be different in all scenarios, but the lesson remains the same – these actions should not take any longer to execute on day 300 as they did on day 1.

The Right Way to Perform a Custom Save Action

Wherever possible, use asynchronous strategies.  Following these strategies will retain the same level of performance that came with Sitecore out-of-the-box.  While there are many ways to implement a strategy like this, below are a few examples:

Using a Task

public override void Execute(object sender, EventArgs args)
{
   if (args == null)
      return; 

   var item = Event.ExtractParameter(args, 0) as Item; 

   if (item == null)
      return;

   Task.Factory.StartNew(() => SaveAsync(item, args));
} 

private void SaveAsync(Item item, EventArgs args)
{
   // code here
}

Using a Sitecore Job

public override void Execute(object sender, EventArgs args)        
{
   Sitecore.Shell.Applications.Dialogs.ProgressBoxes.ProgressBox.Execute(
   "My Job",
   "Process", 
   StartProcess, 
   new object[]{}); 
} 

public void StartProcess(params object[] parameters) 
{
   var proc = new ImportContent();
   proc.Execute();
}

public class ImportContent{
   public void Execute(){
      // code here
   }
}

Parallel.ForEach

public override void Execute(object sender, EventArgs args) 
{
   var items = new List<Item>();
   Parallel.ForEach(items, item =>
   { 
      // code here
   });
}

The Task and Parallel.ForEach implementation are similar concepts from the same Namespace and can be used for most basic scenarios.  While a Sitecore Job locks up the UI, it makes it obvious to the user by providing feedback because it will kick off a progress dialog that can update them throughout the process.  This should only be used for very long running processes.  The progress dialog can be closed by the client and they may continue what they were doing.  Check out my post on Utilizing Pipelines for Long Processes to see a technique for organizing your long running process.

Conclusion

Sitecore clients have a large investment in the platform and deserve to have an optimal experience throughout the product lifecycle.  It’s inexcusable that poor programming practices are the reasons for a client to second guess their CMS decision.  Throwing more hardware at a server to solve a programming issue is not a solution, it’s a band-aid. Using these asynchronous strategies is a simple way to ensure you’re delivering the best results so your client has the experience they deserve.

We’re not just a service company, we’re an experience company, and pride ourselves on going above and beyond for our clients. Learn more about our philosophy and how it’s helped us grow in this post by our President and CEO, Peter Ladka.

John Rappel

Technical Lead
Tags
  • Best Practices
  • Content Editor
  • Content Management
  • Development
  • Problem Solving
  • Productivity
  • Sitecore
  • Tutorial
  • Web Development

Recent Work

Check out what else we've been working on