views:

313

answers:

2

I have a base master page that specifies the main layout template of a website. It also handles some logic that changes tabs depending on the section, and also sets page meta information.

I'm dynamically loading nested master pages by looking at the querystring, loading up a record from the database, and setting the nested master page dynamically based on a value found in that record. I need to load dynamic nested master pages for layout and functional differences.

There is additional information in that record that I want to use in the base master page and in the dynamically loaded master page so I can avoid additional database calls.

Currently, I have set up a class that inherits MasterPage to act as the base class for the base master page. I have a shared (static) property that holds the object representing the database call that I want to share between the base master page and the nested, dynamically called master page.

It works, but it seems a little ugly. Are there any other better solutions?

A: 

You could always pass the record in the HttpContext.Items collection. Once it is in the Items collection it is available to every thing that can reach the HttpContext for the duration of the request.

Larry Beall
Yes, this would work, but as far as I know you lose strong typing (without some extra work).
ScottE
I have generally wrapped situations where I need to pass things through the HttpContext.Items collection with either a static properties class or instance class. Meaning I would have something like a ContextItems class that has a property for the data I put in items. I do my typing in there to return the data out of the Items collection as the typed class I put in.
Larry Beall
A: 

Ok, I had to sleep on this one a bit, but I came up with a cleaner solution. I ended up using a base class for the page, instead of a base class for the master page. The base page sets the meta that I was going to set in the base master page.

Public Class PageBase
    Inherits Page

    Private _DocDetails As FolderDocument
    Public Overridable ReadOnly Property DocDetails() As FolderDocument
        Get
            Return _DocDetails
        End Get
    End Property

    Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not Page.IsPostBack() Then
            SetMeta()
        End If
    End Sub

    Protected Sub SetMeta()

        If DocDetails IsNot Nothing Then
            Page.Title = DocDetails.MetaTitle
            If DocDetails.MetaKeywords <> String.Empty Then
                Dim metaKeywords As New HtmlMeta()
                metaKeywords.Name = "Keywords"
                metaKeywords.Content = DocDetails.MetaKeywords
                Page.Header.Controls.Add(metaKeywords)
            End If
            If DocDetails.MetaDescription <> String.Empty Then
                Dim metaDescription As New HtmlMeta()
                metaDescription.Name = "Description"
                metaDescription.Content = DocDetails.MetaDescription
                Page.Header.Controls.Add(metaDescription)
            End If
        End If

    End Sub

End Class

..And then the aspx page inherits this base page and dynamically sets the master page.

<%@ Page Language="VB" Inherits="PageBase" %>
<script runat="server">

    Private _DocDetails As FolderDocument
    Public Overrides ReadOnly Property DocDetails() As FolderDocument
        Get
            Return _DocDetails
        End Get
    End Property

    Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs)
        _DocDetails = FolderDocuments.GetFolderDocument()

        If _DocDetails IsNot Nothing Then
            If _DocDetails.MasterPage <> "" Then
                Me.MasterPageFile = String.Format("~/templates/{0}.master", _DocDetails.MasterPage)
            End If
        End If

    End Sub
</script>

...and in the dynamically called master page I can reference the page's base class by casting:

Dim parentPage As PageBase = DirectCast(Page, PageBase)
Response.write(parentPage.DocDetails.Title)
ScottE