Taking Care Of Pre_Init

Saturday, December 10, 2005

The Page class exposes a Pre_Init event because the MasterPageFile and Theme properties need to be set early in the lifecycle of a web form. Pre_Init is the event to hook if you want to assign these properties dynamically in code. The natural question is how to implement master page and theme selection for all web forms in an application without adding a Pre_Init event handler to every single web form.

Brock Allen has one elegant solution, which is to use an HttpModule. Brock’s module hooks the PreRequestExecuteHandler and ultimately handles all the PreInit events with a single method in an HttpModule. I haven’t touch VB in a week, so here is what that solution would look like in VB:

Imports System.Web

Public Class MasterAndThemeModule
    
Implements IHttpModule

    
Public Sub Dispose() Implements IHttpModule.Dispose
    
End Sub

    Public Sub Init(ByVal context As System.Web.HttpApplication) _
            
Implements IHttpModule.Init

        
AddHandler context.PreRequestHandlerExecute, _
                  
AddressOf Application_PreRequestHandlerExecute
    
End Sub

    Public Sub Application_PreRequestHandlerExecute(ByVal sender As Object, _
                                                    
ByVal e As EventArgs)
        
Dim application As HttpApplication
        application =
DirectCast(sender, HttpApplication)

        
Dim page As Page
        page =
TryCast(application.Context.CurrentHandler, Page)

        
If Not page Is Nothing Then

            AddHandler page.PreInit, _
                    
AddressOf Page_PreInit
        
End If
    End Sub

    Public Sub Page_PreInit(ByVal sender As Object, ByVal e As EventArgs)

        
Dim page As Page
        page =
DirectCast(sender, Page)
        page.MasterPageFile =
"code to select master page"

    End Sub

End
Class

You could drop the above code into an App_Code file and configure the module in web.config like so:

<httpModules>
   <
add name="MasterAndThemeSelection" type="MasterAndThemeModule"/>
</
httpModules>

Of course, the beauty of an HttpModule is that you could put the code into a class library and configure the module to run in a number of applications.

The alternative is to use inheritance, which requires a base class derived from the Page class. s

Imports System.Web.UI

Public Class BasePage
    
Inherits Page

    
Public Sub Page_PreInit(ByVal sender As Object, _
                            
ByVal e As EventArgs) Handles Me.PreInit
        
Me.MasterPageFile = "code to select master page file"
    End Sub
End
Class

Any web form that wants to take advantage of the common PreInit event handler will need to inherit from the BasePage class either by changing the Inherits attribute in the @ Page directive (for forms with no CodeFile) or by changing the Inherits line in the CodeFile. Inheritance can be slightly more intrusive, but it’s also easier to opt out of the behavior by not deriving from the BasePage.


Comments
Thomas Eyde Saturday, December 10, 2005
Thanks for the info. It's not you I am bugging, but I have this question:

Is it possible to package the master page file as a class? We don't really want to pass that look and feel *file* around, do we?

I was really hoping I could compile the master into the assembly and then reuse it in other projects. Seems like I have to wait for that one.
scott Saturday, December 10, 2005
Thomas - I think there are ways to compile pieces (master pages, user controls) and then reuse them. I have not tried it with the RTM bits so I'll need to do a few experiments...
stan Saturday, February 25, 2006
I tried to put this in global.asax file like Brock, but got error

'Page' is not a member of 'System.EventArgs'.

Do I put this is Generic Handler or in VB.Class file?

What might I be going wrong?


Sub Page_PreInit(ByVal sender As Object, ByVal e As EventArgs)
Dim t As String = HttpContext.Current.Profile.GetPropertyValue("Theme")
If t <> "" And t.Length > 0 Then
e.Page.Theme = t
Else
e.page.Theme = "ulaanBlue"
End If

End Sub
anabhra Tuesday, August 22, 2006
Any futher info on sharing the master pages across applications (in the same domain)?
scott Wednesday, August 23, 2006
anabhra, take a look at: odetocode.com/.../5469.aspx
Ezequiel Jadib Friday, October 27, 2006
I use the httpModule, but i have this error

Content controls have to be top-level controls in a content page or a nested master page that references a master page

how can i do?
scott Sunday, October 29, 2006
@ Ezequiel: You must be setting the MasterPageFile for an .aspx page that does not use master pages. To set the MasterPageFile property on an .aspx means it can only have <asp:Content> controls inside.
gravatar Kay Wednesday, November 3, 2010
I am also getting this error:
"Content controls have to be top-level controls in a content page or a nested master page that references a master page"

It is happening in accessdenied and other pages that use simple.master. I know that these pages use master pages. Any ideas? Thanks.
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!