CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

David Hayden [MVP C#]

         .NET Tutorials, Patterns, and Practices

ASP.NET Page Inheritance - Base Page Classes in your Web Applications

A week ago I talked about using XML Serialization as a means to persist and retrieve application settings.  Using that example as a stepping stone, I want to extend this idea further by exposing these settings via a base ASP.NET page class for use in your web applications.

In general, base page classes in your web applications help you to remove code smells in your web applications by allowing you to "Move Up" or "Pull Up" code that is common to all your web pages.  Often, accessing application settings is one such action you do in all your web pages and is better exposed via a base page class.

I am going to take the same SiteSettings Class we used before and just expand the static methods a bit more to include saving the configuration in cache with a dependency on our sitesettings.config file in the application directory.  This will improve performance so we don't have to access the application settings from the file each time, but also have the application settings refreshed when a change is detected in the underlying file.

 

SiteSettings Class
[XmlType(Namespace="urn:davidhayden-com:config")]
[XmlRoot(Namespace="urn:davidhayden-com:config")]
public class SiteSettings
{
    #region Private Members

    private string _name;
    private string _url;
    private string _emailAddress;

    #endregion

    #region Properties

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public string Url
    {
        get { return _url; }
        set { _url = value; }
    }

    public string EmailAddress
    {
        get { return _emailAddress; }
        set { _emailAddress = value; }
    }

    #endregion

    public SiteSettings() {}

    #region Static Methods

    public static SiteSettings Fetch()
    {
        if (HttpContext.Current.Cache["SiteSettings"] != null)
            return (SiteSettings)HttpContext.Current.Cache["SiteSettings"];
        else
        {
            SiteSettings settings = SiteSettings.FetchFromFile();
            HttpContext.Current.Cache.Insert("SiteSettings", settings,
                new CacheDependency(HttpContext.Current.Server.MapPath("sitesettings.config")));
            return settings;
        }
    }

    public static SiteSettings FetchFromFile()
    {
        SiteSettings siteSettings;

        XmlSerializer serializer = new XmlSerializer(typeof(SiteSettings));

        using (StreamReader reader = new
            StreamReader(HttpContext.Current.Server.MapPath("sitesettings.config")))
        {
            siteSettings = (SiteSettings)serializer.Deserialize(reader);
        }

        return siteSettings;
    }

    #endregion
}

 

Here is our base page class, called BasePage, that essentially fetches the application settings and exposes the entire class via the protected field settings.  As all protected fields, settings is accessible to any class that derives from BasePage.

 

BasePage Class
public class BasePage : Page
{
    protected SiteSettings settings;

    public BasePage()
    {
        Init +=new EventHandler(LoadSettings);
    }

    private void LoadSettings(object sender, EventArgs e)
    {
        settings = SiteSettings.Fetch();
    }
}

 

Last, we create a page that derives from BasePage, called WorkingPage, that essentially just displays the current application settings on a web page.  The settings are grabbed from the protected field settings in BasePage and displayed accordingly.

 

WorkingPage Class
public class WorkingPage : BasePage
{
    protected Label SiteName;
    protected Label SiteUrl;
    protected Label SiteEmailAddress;

    protected override void OnInit(EventArgs e)
    {
        base.OnInit (e);
        this.Load +=new EventHandler(Page_Load);
    }
    
    private void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
            DisplaySettings();
    }
    
    private void DisplaySettings()
    {
        SiteName.Text = settings.Name;
        SiteUrl.Text = settings.Url;
        SiteEmailAddress.Text = settings.EmailAddress;
    }
}

 

And just to be complete, here is sitesettings.config and the sitesettings.aspx page used in the example:

 

sitesettings.config
<?xml version="1.0" encoding="utf-8"?>
<SiteSettings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="urn:davidhayden-com:config">
  <Name>DavidHayden.com</Name>
  <Url>http://www.davidhayden.com/</Url>
  <EmailAddress>nospam@nospam.com</EmailAddress>
</SiteSettings>

 

SiteSettings.aspx
<%@ Page Inherits="PageInheritance.WorkingPage" AutoEventWireUp="false" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>SiteSettings Test</title>
</head>
<body>
<form runat="server">
<p>Site Name: <asp:Label id="SiteName" runat="server" /></p>
<p>Site Url: <asp:Label id="SiteUrl" runat="server" /></p>
<p>Site Email Address: <asp:Label id="SiteEmailAddress" runat="server" /></p>
</form>
</body>
</html>

 

Application settings aren't the only things you can place in your base pages, but it's a good place to start if base page classes are new to you.


Published Mar 14 2005, 12:02 PM by David Hayden
Filed under: ,

Comments

Raymond Lewallen said:

I just did this exact demo, based on session wrapper classes, last Monday. Serializing session state information to disk for a session wrapper created as part of a base page class. Very similar to what I demo'd. Very good starting point for base page inheritance. For some more information, for those of you reading this post, check these links on how some of us others here at codebetter do some implementation into base pages:

http://codebetter.com/blogs/eric.wise/archive/2005/02/02/50334.aspx

http://codebetter.com/blogs/raymond.lewallen/archive/2005/02/02/50358.aspx

http://codebetter.com/blogs/brendan.tompkins/archive/2005/02/23/55903.aspx
# March 14, 2005 1:26 PM

Raymond Lewallen said:

Demo'd at my local .Net users group, for clarification :)
# March 14, 2005 1:27 PM

Sahil Malik said:

There's a problem in this logic.

Check this out -

if (HttpContext.Current.Cache["SiteSettings"] != null)
return (SiteSettings)HttpContext.Current.Cache["SiteSettings"];


So you read from the Cache. If you find it, you read AGAIN and return. What if between these 2 statements another thread kicked it out of the cache? You're screwed.

What u should do is, fetch out of cache, and assign to a variable. And then check for the variable's being not null. If it is not null, return the variable.

Man I love having time to read blogs :)
# March 14, 2005 1:38 PM

David Hayden said:

Thanks for pointing out the other posts, Raymond. Good stuff!

You should post your slides or code on the demo as I love to read through code and learn best practices done by others.
# March 14, 2005 3:56 PM

David Hayden said:

Good point, Sahil. It would be better to pull it over to a variable before doing the check and casting.
# March 14, 2005 4:02 PM
Check out Devlicio.us!

Our Sponsors

Free Tech Publications

This Blog

Syndication

News

CodeBetter.Com Home