Imagine that you wanted to tweak a page's rendered output in some manner - perhaps inject a copyright notice at the bottom of the page or ensure that <link> tags to required stylesheets were present. There are a number of options available to make this happen in ASP.NET.:
- The simplest (but least tenable) approach is to simply add the logic to each and every page that requires it. This can be a maintainence nightmare, however, as if the logic changes you need to revisit every page that has this logic hard coded. Similarly, adding new pages to the site that utilize this same logic requires copying and pasting code.
- A more centralized approach would be to tap into an application event, if available. For example, this might be a good choice if you wanted to use some kind of special encryption or compression on the page's output.
- While the Global.asax approach is better than adding the logic to each individual page, it still has the problem of tightly coupling the logic with the application. If you wanted to replicate the logic in another Web application, for instance, you'd need to replicate the code. This takes us back to our initial problem - what happens if the logic needs to change or be updated? What happens when we want to add another Web application that uses this logic? We'd need to replicate the Global.asax code in each of these applications. Boo.
A better, more losely coupled approach is to use an HTTP Module. It has access to the same application-level events, and can be packaged up as a stand-alone assembly that can be added or removed to Web applications as easily as you can add or remove a file from a directory. No recompilation/redeployment needed. (See Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components for more info on using an HTTP Modules in this manner, along with an examination of a global error logging component, ELMAH.)
- A final approach is to use a base class that the ASP.NET pages in your application extend. The logic necessary can be placed in this base class. This technique is used in DotNetNuke (well, it was in version 2.x, I haven't poked around version 3 yet). DotNetNuke uses a base class to move the __VIEWSTATE hidden form field to the bottom of the <form> so as not to gunk up search engines or Google AdSense. Here's the base class, some code has been removed for brevity:
Public Class BasePage
Inherits System.Web.UI.Page
'
' This method overrides the Render() method for the page and moves the ViewState
' from its default location at the top of the page to the bottom of the page. This
' results in better search engine spidering.
'
Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
Dim stringWriter As System.IO.StringWriter = New System.IO.StringWriter
Dim htmlWriter As HtmlTextWriter = New HtmlTextWriter(stringWriter)
MyBase.Render(htmlWriter)
Dim html As String = stringWriter.ToString()
Dim StartPoint As Integer = html.IndexOf("<input type=""hidden"" name=""__VIEWSTATE""")
If StartPoint >= 0 Then 'does __VIEWSTATE exist?
Dim EndPoint As Integer = html.IndexOf("/>", StartPoint) + 2
Dim ViewStateInput As String = html.Substring(StartPoint, EndPoint - StartPoint)
html = html.Remove(StartPoint, EndPoint - StartPoint)
Dim FormEndStart As Integer = html.IndexOf("</form>") - 1
If FormEndStart >= 0 Then
html = html.Insert(FormEndStart, ViewStateInput)
End If
End If
writer.Write(html)
End Sub
End Class 'BasePage
For more information check out the DotNetNuke source or my latest 4Guys article, Using a Custom Base Class for your ASP.NET Page's Code-Behind Classes.