2/02/2011
Dissecting Razor, part 2: Gluing the pieces together

Last time, we saw that ASP.Net Web Pages are implemented in two independent assemblies. These assemblies are not directly connected to each-other.

Razor Side

System.Web.WebPages.Razor.dll contains the RazorBuildProvider class, which allows ASP.Net’s build system to compile Razor pages. This class uses a WebRazorHostFactory to create WebPageRazorHosts used to process CSHTML (or VBHTML) files into CodeDOM trees. It compiles the CodeDOM tree and returns the generated type(which will typically inherit System.Web.WebPages.WebPage) to the build system.

WebPageRazorHost is coupled to the WebPages framework; it handles the non-standard base types for special pages (StartPage and ApplicationStartPage).

RazorBuildProvider can be configured to use a different WebRazorHostFactory that creates custom WebPageRazorHosts. (more on this later)

WebPages Side

The WebPages framework contains an internal WebPageHttpModule class which runs when an ASP.Net AppDomain is started. It runs any _AppStart files, and hooks the request lifecycle to handle requests for CSHTML (or VBHTML) pages.

Requests for Razor pages are handled by System.Web.WebPages.WebPageHttpHandler. This class passes the page’s virtual path to the build manager and gets a WebPage instance (It assumes that RazorBuildProvider will build the page and give a WebPage instance).

The handler calls the page’s ExecutePageHierarchy method to serve the page to the client. This method runs any _PageStart pages in the page’s parent directories, then executes the page.

The WebPageHttpHandler will also add a custom HTTP header, X-AspNetWebPages-Version: 1.0. This can be disabled by setting WebPageHttpHandler.DisableWebPagesResponseHeader to false.

As mentioned, System.Web.WebPages.dll is not directly tied to the Razor language and engine. One can create a custom build provider which compiles classes that inherit WebPage, then call WebPageHttpHandler.RegisterExtension to tell the WebPages framework to handle requests to the extension, without using the Razor parser.