GeekDork.com - work smarter not harder

Building a better web application - The CAP method: 'Common Members'

Sections:
  1. Introduction
  2. History & How it works
  3. Skeleton Properties
  4. Site Construction
  5. Implementation
  6. 'Common Members'
  7. Issues & Conclusion

Download WebSkeleton

Using the 'CommonMembers' technique.

This section describes a technique that the WebSkeleton classes use, but is not supplied as part of WebSkeleton. This technique can be used completely apart from WebSkeleton classes. By building a web application with WebSkeleton and supplementing it with this technique, the web application becomes very intuitive and easy to construct and maintain. By implementing a single class of common members and creating an instance of that class in a base page from which all applications are derived, the developer only needs to remember that all site specific members live off of this one member of the page. In a team environment this becomes extremely helpful because developers unfamiliar with what members there are for a particular application need only remember that one page member name. When using Visual Studio.Net they will get all those common members displayed before them.

Using a CommonMembers class

This technique centers on the existence of a common class of members that are specific to an application. Any application that is heavy with user interaction often requires the use of variables that many pages use. A simple example of such is user identification data like a UserID. This is a value that many pages will need in order to do what they need. There's no end to the type of data that needs to be handled by many pages: a shopping basket, search string, etc.

The data that is used commonly between pages will often come from various sources. These sources can be browser cookies, session variables, querystring parameters or database values. Given the complexity of these various sources it can become confusing as to where to get what, what data type they are and how to store values if then need to change and seen by other code on the page or in a user control.

One of the serious payoffs of using this technique comes from what happens behind the scenes in the common members class. All these members become strongly typed, and where they come from and where they are stored only needs to be written in one place. Furthermore, because you have abstracted away their true source and destination, other developers in a team need not be concerned with those details. This virtually eliminates the time spent researching ("where do I get/put these values?") and the resulting bugs by the improper use of the value. Plus, if something changes in your application, like it's suddenly decided that a value will no longer be stored in a cookie but in the session, only one change needs to occur.

An additional level of convenience can be built into this technique by "wiring together" the common members in the page and a user control.

Building the class

Let's build a simple common members class. We'll include a single field and property for member "UserID".

Public Class CommonMembers Private _nUserID As Integer = -1 Public Property UserID() As Integer Get Return _nUserID End Get Set(ByVal Value As Integer) _nUserID = Value End Set End Property End Class

Adding the class as a member of the page

Implementing this technique requires the use of 2 base classes: one for pages and one for user controls. I typically create the classes as BasePage and BaseUserControl. Each class is derived from their respective System.Web.UI base classes (Page and UserControl):
Public MustInherit Class BasePage Inherits System.Web.UI.Page End Class Public MustInherit Class BaseUserControl Inherits System.Web.UI.UserControl End Class
Once we have the base class to add to we can put in our common members class. We'll put an instance into both the page and the user control base classes. Because this is a class we don't want callers to mess with, we'll make the public property read only. I like to use the fairly intuitive name "Common" for my common members:
Public MustInherit Class BasePage
	Inherits System.Web.UI.Page

Private _objCommon As New CommonMembers Public ReadOnly Property Common() As CommonMembers Get Return _objCommon End Get End Property
End Class Public MustInherit Class BaseUserControl Inherits System.Web.UI.UserControl
Private _objCommon As New CommonMembers Public ReadOnly Property Common() As CommonMembers Get Return _objCommon End Get End Property
End Class

Wiring "Common" between a user control and its page

Every control has a Page member that provides access to the instance of the System.Web.UI.Page object that the control lives on. Our application's pages are derived from BasePage that is derived from System.Web.UI.Page so we can see that member. Furthermore, we can check that member to see if its type matches any of several things. We are interested in whether a control's Page type matches our BasePage. If it is, we can wire together the instances of our user control's Common member with that of the page. We actually don't wire them together per se, we overwrite the user control's instance reference with the instance reference from the page. We'll do this check when the control is loaded. Here's the code we put into the BaseUserControl class :
Public MustInherit Class BaseUserControl
	Inherits System.Web.UI.UserControl

	Private _objCommon As New CommonMembers

	Public ReadOnly Property Common() As CommonMembers
		Get
			Return _objCommon
		End Get
	End Property

Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load If TypeOf Me.Page Is BasePage Then _objCommon = CType(Me.Page, BasePage).Common End If End Sub
End Class
It's that simple. Now code in the page or user control can access the UserID property simply by calling Me.Common.UserID and they will each be referencing the same object.

Common property persistence (when required)

The real benefit of centralizing common members lies in the storage of those members values when persistence is required. As described above, many of these members would consist of bits of data that need to be persisted through a user session (UserID, shopping basket contents, etc). By writing all of the "prefill" and "save" code for these members into the CommonMembers class, a lot of redundant code and confusion is eliminated from page and user control code. Here's a simple example using our existing sample CommonMembers class:
Public Class CommonMembers
	...

Public Sub LoadValues() Dim objUserID As Object = System.Web.HttpContext.Current.Session.Item("nUserID") If Not objUserID Is Nothing Then Me._nUserID = CType(objUserID, Integer) End If End Sub Public Sub SaveValues() System.Web.HttpContext.Current.Session.Item("nUserID") = Me._nUserID End Sub
End Class
Now that we have the storage and retrieval methods taken care of, we need to actually make sure they are called. This we do inside of the page base class by using the Page.Load and Page.UnLoad events:
Public MustInherit Class BasePage
	Inherits System.Web.UI.Page

	Private _objCommon As New CommonMembers

	Public ReadOnly Property Common() As CommonMembers
		Get
			Return _objCommon
		End Get
	End Property

Private Sub Page_Load1(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load Me._objCommon.LoadValues() End Sub Private Sub Page_Unload(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Unload Me._objCommon.SaveValues() End Sub
End Class


Back to: Implementation Proceed to: Issues & Conclusion

Note: This article applies to WebSkeleton version 1.0. Please see the release notes for updates.




GeekDork.com - Contact Us
This site is optimized for Internet Explorer.