So far, we've focused most attention upon the Page class. The Page class is responsible primarily for managing the UI aspects of an application. Because UI processing is very involved (and much of it is boilerplate-type code) the Page class has a great deal of functionality built into it. The Page class will solve the majority of user interface requiring UI processing.
Although we haven't come across Web services yet, the WebService class implements the details required to interpret HTTP requests as method calls. Clients call Web services by packaging method calls in an XML format formalized as the Simple Object Access Protocol (SOAP). Clients call Web services in the same way they make HTTP requests for Web pages—via HTTP GET and POST requests. When the request reaches the server, it becomes the server's job to unpack the parameters, place them on a call stack, and finally invoke the correct method. Most of the work required to make a method call via HTTP is well-understood and consistent and may be pushed down into the Service class.
As we saw in Chapter 2 on ASP.NET fundamentals, the endpoint for all HTTP requests destined for ASP.NET is a class implementing IHttpHandler. IHttpHandler is a simple interface, including a mere two methods. However, any class implementing that interface qualifies to participate in the HTTP pipeline as an HTTP handler. We'll see the interface in detail shortly.
HTTP handlers are simply classes implementing IHttpHandler (just as HTTP Modules are classes implementing IHttpModule). Handlers are listed inside Web.Config. As with the HTTP Modules, ASP.NET comes out of the box with several HTTP handlers already (for implementing features such as tracing and preventing access to sensitive files on the site). ASP.NET comes with these HTTP handlers already registered in the master Web.Config (which resides alongside Machine.Config in the main configuration directory) configuration file.
So far, ASPX, ASAX, and ASCX files have seemed to magically work within ASP.NET. For example, we saw earlier that simply surfing to an ASPX file causes ASP.NET to compile the file just-in-time and to synthesize a class based on System.Web.UI.Page. The reason the ASPX files work that way is because ASP.NET includes handlers for that functionality.
ASP.NET HTTP handlers are specified in Web.Config in much the same way as HTTP Modules. The format of the handler elements includes four items. First, they include a file name and/or extension to which the handler applies. This is done through the add attribute. Remember, all HTTP requests come to the server as resource requests—the HTTP protocol is built around the idea that requests contain file names. The second part of the handler specification, verb, is a list of verbs to which this handler applies. These verbs correspond to the HTTP specification. For example, you might want a handler to apply only to GET and not to POST requests. Or you may wish to have a handler apply to all requests. The third element, type, is the name of the .NET type assigned to handle the request. Finally, the last attribute, validate, specifies whether or not ASP.NET should load the class at startup immediately or wait until a matching request is received.
Listing 18-1 includes a smattering of the HTTP handlers already installed as part of ASP.NET's Web.Config file.
<httpHandlers> <add path="trace.axd" verb="*" type="System.Web.Handlers.TraceHandler" validate="True" /> <add path="WebResource.axd" verb="GET" type="System.Web.Handlers.AssemblyResourceLoader" validate="True" /> <add path="*.axd" verb="*" type="System.Web.HttpNotFoundHandler" validate="True" /> <add path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" validate="True" /> <add path="*.ashx" verb="*" type="System.Web.UI.SimpleHandlerFactory" validate="True" /> <add path="*.asax" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" /> <add path="".ascx" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" /> <add path="*.master" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" /> <add path="*.config" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" /> <add path="*.cs" verb="*" type="System.Web.HttpForbiddenHandler" validate="True" /> <!—More handlers follow… --> </httpHandlers>
Let's take a look at a couple of specific handlers—the Trace handler and the Forbidden handler—to get a good idea as to how having a separate request handling facility (i.e., one that is not tied specifically to UI or to Web services) can be useful.