A different approach to ASP.NET master pages
Quite a few people have created their own solutions to the one of the most famous shortcomings of current versions of ASP.NET: the lack of master pages. It's notoriously arduous to enclose content into a designated area of a page that has programmatical functionality elsewhere.
I am not very keen on the ASP.NET 2.0 design, either. That requires the developer to write specific server control definitions and references here and there. What I want to accomplish is to make the master paging as easy as possible (of course, easy when excluding the implementation of the master paging system).
My implementation works like this: I write an user control (.ascx) and save it in the web application directory. It is automatically mapped to a certain url and when that url is loaded, the control is enclosed into the content area. In addition to this, the system has gotten rid of file extensions, a legacy (do I hear sounds of disappointment for the lack of .aspx or .cfm or .whatever?).
Here's how it works. I have written a specific PageHandlerFactory (download), which implements the IHttpHandlerFactory interface. All the requests except for a list of predefined file types are routed to this class. The PageHandlerFactory then uses the following logic to invoke the page (.aspx) to be executed.
- If the .aspx file corresponding to the requested url exists, the execution is returned to the .NET infrastructure using
PageParser.GetCompiledPageInstance(Url, Path, Context);
- If the .aspx file corresponding to the requested url sans the .aspx file extension exists, the execution is returned to the .NET infrastructure. For example, if the user requests url http://arje.net/rss and file rss.aspx exists, the page object defined by this file will be invoked.
- If the first segment of the local path of the url has a corresponding .aspx file, this will be executed. For example, requests to http://arje.net/trackback/a_page and http://arje.net/trackback/another_page are both handled by file trackback.aspx.
- If none of the previous conditions are met, a special file, scaffold.aspx, is invoked.
The scaffold.aspx file contains the menus, headers and everything else that is consistent from one page to another. It loads the content by searching for a control in a specific directory mapped to an url. For example, if the url is http://arje.net/archive, the Scaffold searches for archive.ascx and loads that into a placeholder control. If the file does not exist, Scaffold loads a default page.
In this blog implementation the default page does the following:
- Searches the database for an entry corresponding to the url.
- Uses regular expressions to determine if the user requested an archive page.
- Displays a 404 page (with a nifty close-matching using the Levenshtein algorithm, deliberately quite lax). An example.
This implementation requires a bit more setting up to do than ASP.NET 2.0 Master Pages, but once it is set up, I think it offers better embracement for a web site, albeit you have to learn a bit more and take into account thingssuch as that files may block access to directories of the same name. There shouldn't be any additional security implications as only .aspx files will get to be executed. Of course, it is not a general purpose solution, which obviously is the aim of the .NET developers.
The setting up requires the following steps:
- Wildcard script mapping in IIS web site properties dialog. This is done differently in every IIS version so I'm not explaining it here.
- Adjustments to web.config, namely, the following segment:
<add verb="*" path="trace.axd" type="System.Web.Handlers.TraceHandler" />
<add verb="*" path="*.asax,*.ascx,*.config,*.cs,*.vb" type="System.Web.HttpForbiddenHandler" />
<add verb="*" path="*.png,*.gif,*.jpg,*.css,*.js,*.zip,*.swf" type="System.Web.StaticFileHandler" />
<add verb="*" path="*" validate="false" type="arje.net.PageHandlerFactory, name-of-dll" />
List the static files you wish to provide in the StaticFileHandler entry. Other extensions will be treated as 404 even if the file existed.
Download the PageHandlerFactory class. However, please be advised that the PageHandlerFactory changes the behaviour of ASP.NET page execution logic and there may be some residual effect I haven't thought of! Use at your own risk.