June 23, 2011

Create a custom remote event in sitecore

Recently, I had to clear some cache on the frontend server from my backend.
To do that I have implemented a custom remote event. I did not find some documentation on sdn so here is the procedure (thank you to the Sergey Kravchenko from the sitecore support).

  1. Create your custom remote event class.  Remote event class is a usual class inherited from System.Object and marked with a [DataContract] attribute.
     
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.Serialization;
    
    namespace XXX
    {
        [DataContract]
        public class ClearCacheEvent
        {
            public ClearCacheEvent()
            {
    
            }
        }
    }
    
  2. Create a custom event arguments class, to store the arguments of the event. It also, can be empty. Both Remote event class and event arguments class will be used to add event to the EventQueue.
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Sitecore.Events;
    
    namespace XXX
    {
        public class ClearCacheEventArgs : EventArgs, IPassNativeEventArgs
        {
            public ClearCacheEventArgs(ClearCacheEvent @event)
            {
                
            }
        }
    }
    
  3. Create your custom event handler
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Sitecore.Diagnostics;
    using Sitecore.Events;
    
    namespace XXX
    {
        public class ClearCacheEventHandler
        {
            /// <summary>
            /// The methos is the method that you need to implement as you do normally
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public virtual void OnClearCacheRemote(object sender, EventArgs e)
            {
                Log.Info("Tadaa", this);
            }
    
            /// <summary>
            /// This methos is used to raise the local event
            /// </summary>
            /// <param name="event"></param>
            public static void Run(ClearCacheEvent @event)
            {
                Log.Info("ClearCacheEventHandler - Run", typeof(ClearCacheEventHandler));
                ClearCacheEventArgs args = new ClearCacheEventArgs(@event);
                Event.RaiseEvent("clearcache:remote", new object[] { args });
            }
        }
    }
    
  4. Create a custom Hook to bind event from the EventQueue and the "local event" in the CD server web config. This hook will call the method you have added in the event handler ("Run" method of the ClearCacheEventHandler class in our case)
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Sitecore.Events.Hooks;
    
    namespace XXX
    {
        public class ClearCacheHook : IHook
        {
            public void Initialize()
            {
                Sitecore.Eventing.EventManager.Subscribe(new Action(ClearCacheEventHandler.Run));
            }
        }
    }
    
  5. Trigger the event in your code
    ClearCacheEvent inst = new ClearCacheEvent();
    Sitecore.Eventing.EventManager.QueueEvent<ClearCacheEvent>(inst);
    
  6. Configure the web.config (or add it in a separated file in the /include folder it is cleaner)

    The hook:
    <hooks>
        <hook type="XXX.ClearCacheHook, XXX"/>
    </hooks>
    
    The event:
    <events>
        <event name="clearcache:remote">
            <handler type="XXX.ClearCacheEventHandler, XXX" method="OnClearCacheRemote"/>
        </event>
    </events>
    

How does it work?
  1. Your code add an event in the   EventQueue.
  2. The EventQueue is checked by the special task:
    <eventQueue>
        <processingInterval>00:00:02</processingInterval>
    </eventQueue>
    
  3. The Hook call a method who raise the corresponding local event.
  4. Your local is triggered.

15 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. A full example of code with a parameter in the event is available here: http://sitecoreblog.blogspot.be/2012/07/create-custom-remote-event-in-sitecore.html

    ReplyDelete
  3. Thanks for this useful information. Any idea of the best way to pass a Sitecore.Data.Items.Item through the event queue so that it can be picked up on the CD server?

    I ran into a load of serialization issues when I tried this. Also if I pass a .ToString() version of an ItemUri often it references the master database, which wont be available on the CD server.

    ReplyDelete
  4. When you have access to the database, I think that we can do the same way as sitecore does when they need to pass an item in the query string. You need to create multiple properties: ItemID, Version, Language, Database.

    If you don’t have access to the database maybe you can pass dictionary with all the fields where the field name will be the key and the value will be the value of the field. Don’t forget to call the item.Fields.ReadAll() to be sure that all the field are present when you will do your foreach.

    ReplyDelete
  5. Thanks Vangansewinkel. I ended up just passing the ItemUri and parsing it at the CD server end, replacing the database with 'web' and then doing Database.GetItem() to retrieve the item again on the CD server.

    Do you have any idea how to test the remote publish queue on a local dev machine? I have enabled App_config/Include/scalabilitysettings.config and can see events going into the queue in SQL server, however these events do not get processed.

    ReplyDelete
  6. If you just pass the ItemUri you will maybe not have the version and language no?

    To test your events, you may install 2 instances of sitecore on your computer with the code on both instances. And you need to set the setting "InstanceName" into the scalablitysettings.config because by default this is the machine name but here the machine is the same. So be sure that you have 2 different name for your instances in this setting.

    ReplyDelete
  7. I pass it in this format: sitecore://master/{F5244106-8774-4B83-BE61-B41331F3BD8E}?lang=en&ver=1 so still have language and version.

    Thanks for the suggestion on setting up 2 instances to test the remote publishing events. I'd hoped it would be a bit easier than this :)

    ReplyDelete
  8. Thanks a million, Ben!
    Helped me a lot :)

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
  10. This comment has been removed by the author.

    ReplyDelete
  11. Thanks for this great blog post!
    There is a bug in you code. This lin shold be replaced

    Sitecore.Eventing.EventManager.Subscribe(new Action(ClearCacheEventHandler.Run));

    by this line

    Sitecore.Eventing.EventManager.Subscribe(new Action OPEN ANGEL BRACKET ClearCacheEvent CLOSE ANGEL BRACKET (ClearCacheEventHandler.Run));

    I think the angel brackets where removed by your blog system for security reasons.

    Best,
    Jan

    ReplyDelete
  12. Hello,

    I don't think that it was an error but this one is a very old post so the API have probably evolved. Anyway, I really thanks you for your feedback. I have addapted the blog post.

    Regards,

    Benjamin

    ReplyDelete