|
|
Building a better web application - The CAP method: 'Common Members'
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.
|
|