10

I have a custom item:saving event handler which contains some specific logic when a user user makes a change to an item. This works fine but when we create a content package from a different environment and then install it on another environment the item:saved and item:saving events are fired during the package installation. We only want the code to run when the save actions are done by the user and not during package install time, since in theory those actions were already carried out on the server we are packaging from.

We are already checking if the Items are being Published, since that causes as similar item:saving event to be raised.

protected void OnItemSaving(object sender, EventArgs args)
{
    Assert.ArgumentNotNull(sender, "sender");
    Assert.ArgumentNotNull((object)args, "args");
    if (PublishHelper.IsPublishing())
        return;
    Item obj = Event.ExtractParameter(args, 0) as Item;
    if (obj == null)
        return;
    this.DoCustomLogic(obj);
}

Is there a similar helper or how can I check if this save event is raised as a result of a package being installed?

  • If you only want to do this when the user is saving, it might be better to use a processor for the saveUI pipeline – Ben Golden Oct 6 '16 at 20:54
  • @BenGolden Could you add this as an answer and provide relevant information/code snipper? thanks – jammykam Oct 7 '16 at 8:42
  • Sure, just give me a few. I didn't make it an answer initially because, strictly speaking, it wouldn't answer your question. It's more of a side-step. – Ben Golden Oct 7 '16 at 14:51
4

If you only want to run your custom logic when the user saves an item from within the Sitecore client, you could use a saveUI pipeline processor instead. This would eliminate the need to check for these background job scenarios. Here is the basic structure of a saveUI processor:

using Sitecore.Data.Items;
using Sitecore.Pipelines.Save;

namespace Example.Web.Pipelines.Save
{
    public class MySaveProcessor
    {
        public virtual void Process(SaveArgs args)
        {
            foreach (SaveArgs.SaveItem saveItem in args.Items)
            {
                var item = Sitecore.Context.ContentDatabase.Items[saveItem.ID, saveItem.Language, saveItem.Version];
                if (item != null)
                {
                    DoCustomLogic(item);
                }
            }
        }

        protected virtual void DoCustomLogic(Item item)
        {
            // Do your thing
        }
    }
}

If you want this to run before the save actually occurs like the item:saving event does, you would want to patch this in before the Save processor:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <processors>
      <saveUI>
        <processor mode="on" type="Example.Web.Pipelines.Save.MySaveProcessor, Example.Web" patch:before="processor[@type='Sitecore.Pipelines.Save.Save, Sitecore.Kernel']" />
      </saveUI>
    </processors>
  </sitecore>
</configuration>

For more info, see this article from John West on the various ways to intercept item saves: https://community.sitecore.net/technical_blogs/b/sitecorejohn_blog/posts/repost-intercepting-item-updates-with-sitecore

4

You can achieve this with

Sitecore.Context.Job.Name

During installation it will return: "Install"

During normal item saving action Sitecore.Context.Jobproperty will be null

  • What happens if there are other background jobs running? Is the Context.Job always going to be set to install or could one of the other running Jobs be returned instead? – jammykam Oct 6 '16 at 20:24
  • It can be different depending on context. For example for indexing it is: Index_Update_IndexName=sitecore_web_index. I never tested how it behave while having different jobs running in the background. I belive Context is implemented correctly and it is different for different jobs – Alan Płócieniak Oct 6 '16 at 20:27
0

This could be a use case and candidate for creating a custom Disabler. Details on creating a custom disabler can be found in Zach Kniebel Question/Answer.

Essentially, I would write an event handler for the packageinstall:items:starting event that activates the custom disabler that you create, and then another custom event handler that disables it in the packageinstall:items:ended event handler.

Then, in your item:saved event handlers, do a check to see if the custom disabler is active or not. The linked question, has examples on that implementation.

Also good to note, that when the Package Installer is running, the first thing that is fired is the packageinstall:starting event. This calls the OnPackageInstallStartingHandler method from the PackagingEventHandler. You'll note in the snippet below, as well, that IndexCustodian (a static class that manages indexing on a global level) is called to StopIndexing().

namespace Sitecore.ContentSearch.Events
{
  public sealed class PackagingEventHandler
  {
    public void OnPackageInstallStartingHandler(object sender, EventArgs e)
    {
      CrawlingLog.Log.Warn("Stopping indexing while package is being installed.", (Exception) null);
      IndexCustodian.StopIndexing();
    }
  }
}

This means that even if the package install fails, Sitecore is smart enough to know that it has to fire the packageinstall:ended event (which resumes indexing operations).

  • What happens if the package fails to install for some reason and does not install till the end? Will the disabler remain active? Or will packageinstall:items:ended always get called? – jammykam Oct 6 '16 at 20:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.