Hide menu Last updated: Oct 09 2017
Area: Episerver CMS Applies to versions: 10 and higher
Other versions:

Implementing a custom event provider

The following example shows a simple event provider that uses MSMQ for message transportation between IIS sites on the same machine. This code is not ready for production use, it is only provided as an example of implementing an event provider for an external system.

You can find more providers, such as the Amazon provider and the Azure provider in the Episerver NuGet feed.

using EPiServer.Events;
using EPiServer.Events.Providers;
using EPiServer.Framework.Configuration;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;
using EPiServer.Web;
using EPiServer.Web.Hosting;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MSMQEventProvider
{
    #region msmq
    public class MSMQEventProvider : EventProvider
    {
        private const string EPiServerQueueName = "private$\\episerverevents";
        MessageQueue _sendQueue;
        private static object _sendLock = new object();
        IList<Timer> _receiveTimers = new List<Timer>();
        TimeSpan _waitTimeout = new TimeSpan(0, 0, 0, 0, 10);

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            base.Initialize(name, config);

            //Get all existing EPiServer queues
            var queues = MessageQueue.GetPrivateQueuesByMachine(Environment.MachineName)
                .Where(q => q.QueueName.StartsWith(EPiServerQueueName));
            _sendQueue = queues.SingleOrDefault(q => q.QueueName.EndsWith(CurrentApplicationId));

            if (_sendQueue == null)
            {
                string queuePath = ".\\" + EPiServerQueueName + CurrentApplicationId;
                _sendQueue = MessageQueue.Create(queuePath);
                _sendQueue.SetPermissions("Everyone", MessageQueueAccessRights.FullControl);
                _sendQueue.Formatter = new BinaryMessageFormatter();
            }

            //Set up recieve listners for all other queues
            foreach (var queue in queues.Where(q => !q.QueueName.EndsWith(CurrentApplicationId)))
            {
                queue.Formatter = new BinaryMessageFormatter();
                _receiveTimers.Add(new Timer(new TimerCallback(Receive), queue, 0, 1000));
            }
        }

        public override void Uninitialize()
        {
            base.Uninitialize();
            foreach (var timer in _receiveTimers)
            {
                timer.Dispose();
            }
            _sendQueue.Dispose();
        }

        public override void SendMessage(EventMessage message)
        {
            lock (_sendLock)
            {
                _sendQueue.Send(message);
            }
        }

        private void Receive(object state)
        {
            MessageQueue queue = state as MessageQueue;
            Message message = null;
            //Receive throws for empty queue therefore the check with enumerator
            while (!IsQueueEmpty(queue))
            {
                message = queue.Receive(_waitTimeout);
                OnMessageReceived(new EventMessageEventArgs(message.Body as EventMessage));
            }
        }

        private bool IsQueueEmpty(MessageQueue queue)
        {
            using (MessageEnumerator enumerator = queue.GetMessageEnumerator2())
            {
                return !enumerator.MoveNext();
            }
        }

        private string CurrentApplicationId
        {
            get { return GenericHostingEnvironment.Instance.ApplicationID.Replace('/', '_').ToLower(); }
        }

    }
    #endregion
}

 

Configuring an event provider

To add a custom event provider, add the provider configuration to the event element in the episerver.framework section of the web.config as the following example shows:

 <event defaultProvider="msmq">
        <providers>
            <add name="msmq" type="MSMQEventProvider.MSMQEventProvider, MSMQEventProvider" />
        </providers>
        </event>

Comments