AspAlliance.com LogoASPAlliance: Articles, reviews, and samples for .NET Developers
URL:
http://aspalliance.com/articleViewer.aspx?aId=1356&pId=-1
Implementing Observer in ASP.NET
page
by Brian Mains
Feedback
Average Rating: 
Views (Total / Last 10 Days): 31882/ 45

Introduction

The observer pattern is a design pattern, largely popularized by the Gang of Four, which allows objects to receive notifications from another object. Imagine a newsletter signup page, where you can signup for various newsletters that are broadcasted by email. There needs to be the ability to signup multiple users for one newsletter; after all, it would be a shame to create only a one-to-one relationship. Rather, there needs to be a one-to-many relationship, with the many part being an open-ended amount of people.

It is possible to set this up in a .NET application as well. A subject (the newsletter) has one or many observers (newsletter subscribers) of that subject. Whenever the subject needs to broadcast some sort of change, all of the observers get notified of that change. In the newsletter example, when a newsletter changes its content, it is broadcasted to the subscribers. This can be more difficult to setup in ASP.NET because of some of the limitations that occur with the stateless environment. However, it is possible and this article will show you how.

Custom Pages

To make use of the observer, it is best to implement a custom page class. The custom page class is a class that inherits from System.Web.UI.Page and works like regular inheritance does. The reason to implement a custom page class is because of the specialized nature of how this will work. It is possible to not have to use a custom page class; however, for unit testing purposes it makes it helpful to do so.

One of the approaches to implementing the observer pattern is to have the page act as the subject. It is the one that controls certain interactions and notifies its children that an update needs made. The children are most likely user controls because the means to update will require the use of an interface. Each user control would implement from a custom user control base class, similar to how the custom page class works.

Implementation

The following implementation that I created provides notification about a change to an underlying data source (which could be a data table or a business object collection). Imagine this as an application that needs to make sure the information provided is current, so every postback of the page will rebind the data. All of the observers will receive any relevant information from the page.  For instance, say certain objects trigger some event whenever the selection of an item within the page occurs. Say the selection of a row of data then displays detailed information about that row, as well as triggering other items (say relevant keywords, other relevant data that is similar to the selected row, or a myriad of other features).

There are multiple ways to implement this, and the approach I am going to use is to use an interface that the child user controls will implement. This interface looks as such:

Listing 1

public interface ISelectedObserver
 {
   void Update(Assignment assignment);
 }

Each respective custom user control class inherits from a single or multiple custom user control class, depending on the setup with the defined interface to receive updates.  It could look something like this:

Listing 2

public abstract class AssignmentDetailsUserControlBase : ISelectedObserver
 {
   void ISelectedObserver.Update(Assignment assignment)
   {
     if (assignment == null)
       this.Enabled = false;
     else
     {
       this.Enabled = true;
       this.txtDescription.Text = assignment.Description;
       this.txtDueDate.Text = assignment.DueDate.ToShortDateString();
       this.Requestor.Text = assignment.Requestor;
     }
   }
 }

The custom page class defines a SetupObservers method called during page initialization, which adds all the observers to the collection. Any derivative page classes can then add additional observers, if needed.

Listing 3

protected virtual void SetupObservers()
 {
   this.Observers.Add(this.AssignmentDetails);
   this.Observers.Add(this.Comments);
   this.Observers.Add(this.SimilarItems);
 }

The Observers property is a local collection, which is adding instances of user controls. The user controls shown above are exposed as page properties (AssignmentDetails is a property of the custom AssignmentPage class). Alternatively, the page could create a RegisterObserver method that registers an observer with the page.

When the page loads after the observers are initialized, the code checks whether the main subject is selected (such as a gridview). For instance, when an item in a gridview is selected or deselected, a notification can be sent.

Listing 4

protected override void OnLoad(EventArgs e)
 {
  AssignmentCollection assignments = AssignmentsFactory.GetAssignments();
  this.AssignmentsGridView.DataSource = assignments;
  this.AssignmentsGridView.DataBind();
 
  if (this.AssignmentsGridView.SelectedIndex != -1)
    this.NotifyObservers(assignments[this.AssignmentsGridView.SelectedIndex]);
  else
    this.NotifyObservers(null);
}

This notification controls whether an item is in the selected or deselected state, and populates any relevant information.

Other Considerations

There are more dynamic ways to create these relationships. For instance, the page could iterate through the child controls, looking for user controls that implement the target interface that is designed for the observer pattern only. This would make it easier to register, but means that every user control will be registered.

In the stateless environment, the observers must be setup on every page load, unless the observer collection is serialized and stored in viewstate.  Each observer object cannot be stored directly in viewstate, but alternatively the collection could store the ID of the control, and retrieve the control again later through the Page.FindControl method. The state of the control can be stored and the observer does not need to be notified every time; however, in real-time systems, where querying the data frequently is a must, this may be desired.

Conclusion

This article has shown you how you could implement the Observer pattern in ASP.NET to provide some useful functionality.


Product Spotlight
Product Spotlight 

©Copyright 1998-2024 ASPAlliance.com  |  Page Processed at 2024-03-28 3:12:53 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search