Event Broker for ASP.NET

Event Broker for ASP.NET.

Event Broker for ASP.NET

The Event Broker is an implementation of the Observer pattern. The key benefit of an Event Broker is that it offers a loosely coupled mechanism to broadcast and receive events. This is especially useful in ASP.NET where you want to raise events in one user control, say, and handle them in another without needing to wire up each user control to each other explicitly.

I first came across the Event Broker when developing a Windows Forms application using the Smart Client Application Block and thought it was a really cool idea. I have been using the Event Broker concept ever since in various guises, and it’s especially useful in ASP.NET when you want communication between controls to be loosely coupled.

I thought I’d build a really simple implementation that can be used with Web Forms or MVC and allows you to broadcast and receive named events.

For instance let’s say you’re using Web Forms and you have a user control that has a button and you’d like to notify other user controls on a page that the button was clicked without introducing any coupling between the controls or the page they are sitting on. Using the Event Broker this is really easy to do.

My Event Broker implementation provides a way to broadcast and receive loosely coupled events. Behind the scenes the Event Broker uses the HttpContext.Items to keep track of its information. This means that the loosely coupled events are scoped to each request so events and their handlers inherently know which requests they’re for.

Loose Coupling Using Event Keys

Event keys are the trick to creating loosely coupled events with the Event Broker. Rather than explicitly wiring up handlers to an event using the standard .NET event coupling I have the concept of notifications and subscriptions.

Here is the standard event coupling code:

button.Click += MyHandler;

Here is the loosely couple equivalent using the Event Broker:

//subcribing to the event
HttpContext.Current.Subscribe<EventArgs>("EventKey", MyHandler);

//notifying about the event
HttpContext.Current.Notify("EventKey", EventArgs.Empty);

With the Event Broker, events can be raised and handled across different layers of code without each layer having to jump though hoops to wire up the events in the traditional way. This allows greater separation of concerns and is great when used with Inversion of Control patterns such as Dependency Injection. You can also pass events between user interface components such as user controls relatively easily.

The only rule you need to follow is that the notification and the subscription code must use the same event argument type and it must inherit from EventArgs like standard .NET events, for instance, if you want to use, say, a CustomEventArgs class it must inherit from EventArgs and must be used in both the subscriber and the notifier:

//subcribing
HttpContext.Current.Subscribe<CustomEventArgs>("CustomEvent", MyHandler);

//notifying
HttpContext.Current.Notify("CustomEvent", new CustomEventArgs(/*parameters*/));

User Control 1 – Event Notifying

Here we have a user control that is broadcasting an Event Broker based event. Notice how the Event Broker provides an extra method on the HttpContext via a Notify extension method to allow you to raise an event. I raise a loosely coupled event based on a button click.

<%@ Control Language="C#" AutoEventWireup="true"
   CodeBehind="UserControl1.ascx.cs" Inherits="EventBrokerSimple.UserControl1" %>

<script runat="server">

   private void OnButtonClick(object sender, EventArgs e)
   {
      Context.Notify("MyEvent", EventArgs.Empty);
   }

</script>

<asp:Button runat="server" OnClick="OnButtonClick" Text="Raise My Event!" />

When the user clicks the button the Event Broker will raise an event via the Notify method and signal any subscribers passing the event argument.

User Control 2 – Event Subscribing

Here we have a user control that is receiving an Event Broker based event. Again, the Event Broker provides an extra method on the HttpContext via a Subscribe extension method where you can attach a handler to a named event. I recommend you subscribe to the event in the Init or PreInit of the page life-cycle so your listeners are primed prior to events being raised.

<%@ Control Language="C#" AutoEventWireup="true"
   CodeBehind="UserControl2.ascx.cs" Inherits="EventBrokerSimple.UserControl2" %>

<script runat="server">

   private void Page_Init(object sender, EventArgs e)
   {
      Context.Subscribe<EventArgs>("MyEvent", MyEventHandler);
   }

   private void MyEventHandler(object sender, EventArgs e)
   {
      Response.Write("My Event Received!");
   }

</script>

The ASP.NET Event Broker

The Event Broker adds extension methods to the ASP.NET HttpContext and HttpContextBase classes and provides the means to subscribe to events, unsubscribe from events and notify about events just as you would expect from the Observer pattern. I decided to extend the HttpContext and HttpContextBase to reinforce the fact that the scope of the event subscriptions and notifications is per request. Here’s the full C# source:

using System;
using System.Web;
using System.ComponentModel;

public static class EventBroker
{
   private static object EventsKey = new object();

   public static void Subscribe<TType>(this HttpContextBase source, object key, EventHandler<TType> value)
      where TType : EventArgs
   {
      Events(source).AddHandler(key, (Delegate)value);
   }

   public static void Unsubsribe<TType>(this HttpContextBase source, object key, EventHandler<TType> value)
      where TType : EventArgs
   {
      Events(source).RemoveHandler(key, (Delegate)value);
   }

   public static void Notify(this HttpContextBase source, object key, EventArgs args)
   {
      Notify(source, key, null, args);
   }

   public static void Notify(this HttpContextBase source, object key, object sender, EventArgs args)
   {
      Delegate @delegate = Events(source)[key];

      if (@delegate != null)
      {
         @delegate.DynamicInvoke(sender, args);
      }
   }

   public static void Subscribe<TType>(this HttpContext source, object key, EventHandler<TType> value)
      where TType : EventArgs
   {
      Subscribe(new HttpContextWrapper(source), key, value);
   }

   public static void Unsubsribe<TType>(this HttpContext source, object key, EventHandler<TType> value)
      where TType : EventArgs
   {
      Unsubsribe(new HttpContextWrapper(source), key, value);
   }

   public static void Notify(this HttpContext source, object key, EventArgs args)
   {
      Notify(new HttpContextWrapper(source), key, args);
   }

   public static void Notify(this HttpContext source, object key, object sender, EventArgs args)
   {
      Notify(new HttpContextWrapper(source), key, sender, args);
   }

   private static EventHandlerList Events(HttpContextBase source)
   {
      EventHandlerList list = (EventHandlerList)source.Items[EventsKey];

      if (list == null)
      {
         source.Items[EventsKey] = list = new EventHandlerList();
      }

      return list;
   }
}

I hope you enjoy using my Event Broker in your own ASP.NET applications as it’s a really powerful and yet easy to implement bit of code. Now all your events can be loosely coupled

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s