Tuesday, July 20, 2010

SharePoint Architecture on IIS 6

The primary goal of this chapter is for you to understand the internal workings of a Web application and how it initializes the WSS runtime environment.


 

IIS Web Sites and Virtual Directories

Both ASP.NET and WSS rely on IIS 6.0 to supply the underlying listening mechanism to process incoming HTTP requests and supply a management infrastructure for launching and running worker processes on the Web server. An IIS Web site provides an entry point into the IIS Web server infrastructure. Each IIS Web site is configured to listen for and process incoming HTTP requests that meet certain criteria. For example, an IIS Web site can be configured to handle requests coming in over a specific IP address or port number or can be routed to the Web server by using a specific host header.


 

IIS automatically creates and configures an IIS Web site named Default Web Site that listens for HTTP requests coming in over port 80 on any of the IP addresses supported on the local Web server. Each IIS Web site is configured to map to a root directory, which is a physical directory on the file system of the hosting Web server. For example, standard configuration for IIS maps the Default Web Site to a root directory located at C:\Inetpub\wwwroot. In the most straightforward routing scenarios, IIS maps incoming HTTP requests to physical files inside the root directory. For example, IIS will respond to a request for http://www.MyTestApp.com/page1.htm by simply loading the contents of the file located at c:\Inetpub\wwwroot\MyTestApp\page1.htm into memory and streaming it back to the client.


 

Note that IIS tracks configuration information about its IIS Web sites and virtual directories in a repository known as the IIS metabase. The IIS metabase lives on the file system of each front-end Web server running IIS. For example, when you create and configure an IIS Web site using the IIS administration utility, IIS tracks these changes by writing entries to the local IIS metabase.


 

ISAPI Extensions and ISAPI Filters


 

IIS also supports the Internet Server Application Programming Interface (ISAPI) programming model, which provides the opportunity for more sophisticated routing scenarios. In particular, the ISAPI programming model allows you to configure an IIS Web site or virtual directory so that incoming requests trigger the execution of custom code on the Web server. The ISAPI programming model consists of two primary component types: ISAPI extensions and ISAPI filters.


 

An ISAPI extension is a component DLL that plays the role of an endpoint for an incoming request. The fundamental concept is that IIS can map incoming requests to a set of endpoints that trigger the execution of code within an ISAPI extension DLL. An ISAPI extension DLL must be installed on the Web server and configured at the level of either an IIS Web site or virtual directory. Configuration commonly involves associating specific file extensions with the ISAPI extensions by using an IIS application map.


 

While an ISAPI extension serves as an endpoint, an ISAPI filter plays the role of an interceptor. An ISAPI filter is installed and configured at the level of the IIS Web site. Once installed, an ISAPI filter intercepts all incoming requests targeting that IIS Web site. The fundamental concept is that an ISAPI filter can provide pre-processing and post-processing for each and every incoming request. ISAPI filters are typically created to provide low-level functionality for an IIS Web site, such as custom authentication and request logging.


 

Application Pools and the IIS Worker Process


 

IIS provides a flexible infrastructure for managing worker processes by using application pools. An application pool
is a configurable entity that allows you to control how IIS maps IIS Web sites and virtual directories to instances of the IIS worker process. Note that instances of the IIS worker process are launched using an executable named w3wp.exe. The routing architecture of IIS is controlled by a kernel-level device driver named http.sys. This device driver listens for incoming HTTP requests and uses information in the IIS metabase to route them to whatever instance of w3wp.exe is associated with the target application pool. If http.sys determines that the target application pool doesn't have a running instance of w3wp.exe, it launches a new instance on demand to process the request.


 

Each IIS Web site and virtual directory can be configured to run in its own isolated application pool. Conversely, you can configure many different IIS Web sites and virtual directories to run in the same application pool for greater efficiency. The key observation you should make is that a tradeoff exists between isolation and efficiency. To achieve greater isolation means you must run more instances of w3wp.exe, which compromises efficiency. To achieve greater efficiency means you must map multiple IIS Web sites and virtual directories to fewer instances of the IIS worker process, which compromises isolation.


 

Every application pool has an important setting known as the application pool identity. The application pool identity is configured with a specific Windows user account that is either a local account on the Web server or a domain account within an Active Directory directory service domain. When http.sys launches a new instance of w3wp.exe for a specific application pool, it uses the application pool identity to initialize a Windows security token that serves as the process token. This is important because it establishes the "runs as" identity for code that runs within the IIS worker process.


 

By default, IIS uses the identity of the local Network Service account when you create a new application pool. However, you can configure the application pool identity by using any other user account you like. When deploying Web sites based on ASP.NET and WSS, it is recommended to configure the application pool identity with a domain account instead of the Network Service account. This is especially true in a Web farm environment when you need to synchronize the identity of an application pool across multiple front-end Web servers in the farm.


 

ASP.NET 2.0 Framework

The ASP.NET Framework is implemented as an ISAPI extension named aspnet_isapi.dll. The basic configuration for ASP.NET involves registering application maps for common ASP.NET file extensions including .aspx, .ascx, .ashx, and .asmx at the level of an IIS Web site or virtual directory. When IIS sees an incoming request targeting a file with one of these extensions, it forwards the request to aspnet_isapi.dll, which effectively passes control over to the ASP.NET Framework. The way in which the ASP.NET Framework processes a request largely depends on the extension of the target file. It is important to note that the ASP.NET Framework runs each ASP.NET application with a certain level of isolation. This is true even in a scenario when you have configured multiple ASP.NET applications to run within the same IIS application pool. The ASP.NET Framework provides isolation between ASP.NET applications running inside the same instance of the IIS worker process by loading each of them into a separate .NET Framework AppDomain.


 

HTTP Request Pipeline

Underneath the productivity-centered architecture for pages and server-side controls, the ASP.NET Framework exposes the HTTP Request Pipeline
for developers who like to work at a lower level. It provides the developer with a degree of control comparable with the ISAPI programming model. However, when you create a component for the HTTP Request Pipeline, you are able to write your code in a managed language such as C#. You can also use APIs provided by the ASP.NET Framework, which is much easier than using the ISAPI programming model.


 

The HTTP Request Pipeline has three replaceable component types: HttpHandler, HttpApplication, and HttpModule. As requests come in, they are queued up and assigned to a worker thread that then processes the request by interacting with each of these component types.


 

The ultimate destination of any request is the endpoint, which is modeled in the HTTP Request Pipeline by using an HttpHandler class, which implements the IHttpHandler interface. As a developer, you can create a custom HttpHandler component and plug it into the HTTP Request Pipeline by adding configuration elements to the web.config file.


 

The HTTP Request Pipeline places an HttpApplication component in front of the HttpHandler. On an application-wide basis, incoming requests are always routed through the HttpApplication
before they reach the target HttpHandler, thus giving the HttpApplication the ability to preprocess any request no matter which HttpHandler it is being routed to. This preprocessing stage is handled through a series of events that are defined inside the HttpApplication class such as BeginRequest, AuthenticateRequest, and AuthorizeRequest.


 

In situations when you don't want to use a custom HttpApplication component, the ASP.NET Framework initializes the HTTP Request Pipeline with a standard HttpApplication object that provides default behavior. However, you can replace this standard component by creating a file named global.asax and placing it in the root directory of the hosting ASP.NET application. For example, you can create a global.asax that looks like the following:

<%@ Application Language="C#" %>

<script runat="server">

protected void Application_AuthenticateRequest(object sender, EventArgs e) {

// your code goes here for request authentication

}

protected void Application_AuthorizeRequest(object sender, EventArgs e) {

// your code goes here for request authorization

}

</script>


 

The third replaceable component type in the HTTP Request Pipeline is the HttpModule. The HttpModule is similar to the HttpApplication component in that it is designed to handle events defined by the HttpApplication class and is processed before control is passed to any HttpHandler classes. For example, you can create a custom HttpModule component to handle request-level events such as BeginRequest, AuthenticateRequest, and AuthorizeRequest. As with the HttpHandler, an HttpModule class is defined with an interface. You can create a class that implements the IHttpModule interface and plug it into the HTTP Request Pipeline by adding configuration elements to the web.config file.


 

Whereas custom HttpApplication components can be defined as simple text files with an .asax extension, custom HttpModule components are always compiled as classes within assembly DLLs. To add a custom HttpModule component into the HTTP Request Pipeline, you then add entries into a web.config file.


 

While an HttpApplication component and an HttpModule component are similar in what they do, the HttpModule contains a few noteworthy differences. First, you are not limited to one HttpModule per application as you are with the HttpApplication components. The web.config file for an ASP.NET application can add in several different HttpModule components. Second, HttpModule components can be configured at the machine level. In fact, the ASP.NET Framework ships with several different HttpModule components that are automatically configured at the machine level to provide ASP.NET functionality for things such as Windows authentication, Forms authentication, and output caching.

The final component that we want to discuss with respect to the HTTP Request Pipeline is HttpContext. As ASP.NET initializes a request to send to the HTTP Request Pipeline, it creates an object from the HttpContext class and initializes it with important contextual information. From a timing perspective, it's important to see that ASP.NET creates this object before any custom code inside the HTTP Request Pipeline has a chance to begin execution. This means that you can always program against the HttpContext object and the child objects that it contains, such as Request, User, and Response. Whenever you are authoring a component that is to execute within the HTTP Request Pipeline, you can write code that looks like the following:


 

HttpContext currentContext = HttpContext.Current;

string incomingUrl = currentContext.Request.Url;

string currentUser = currentContext.User.Identity.Name;

currentContext.Response.Write("Hello world");


 


 

WSS Integration with ASP.NET


 

WSS integrates with ASP.NET at the level of the IIS Web site. Each IIS Web site in which you intend to host WSS sites must go through a one-time transformation process in which it is configured to become what WSS terminology refers to as a Web application. This transformation process involves adding IIS metabase entries and a WSS-specific web.config file to the root directory of the hosting IIS Web site. Once the transformation is completed, WSS extends the routing architecture of IIS and ASP.NET to properly route all incoming requests through the WSS runtime.


 

WSS must add an IIS application map to each Web application to ensure that each and every incoming request is initially routed to the ASP.NET runtime. Remember that the default configuration for ASP.NET only registers application maps for requests with well-known ASP.NET file extensions such as .aspx, ascx, .ashx, and .asmx. Therefore, WSS configures the hosting IIS Web site with a wildcard application map to route all incoming requests to aspnet_isapi.dll, including those requests with non-ASP.NET extensions such as .doc, .docx, and .pdf.


 

Because every request targeting a Web application is routed through aspnet_isapi.dll, the request gets fully initialized with ASP.NET context. Furthermore, its processing behavior can be controlled by using a custom HttpApplication object and adding configuration elements to the web.config file. The WSS team uses standard ASP.NET techniques to extend the HTTP Request Pipeline by using several custom components.


 

First, you can see that WSS configures each Web application with a custom HttpApplication

object by using the SPHttpApplication class. Note that this class is deployed in the WSS system

assembly Microsoft.SharePoint.dll. WSS integrates this custom application class by creating a

custom global.asax file at the root of the Web application that inherits from SPHttpApplication.


 

<@Application Inherits="Microsoft.SharePoint.ApplicationRuntime.SPHttpApplication" >


 

In addition to including a custom HttpApplication object, the WSS architecture uses a custom

HttpHandler and a custom HttpModule. These two WSS-specific components are integrated

into the HTTP Request Pipeline for a Web application using standard entries in the

web.config file.


 

Examine the following XML fragment that is taken from the standard web.config file used by a WSS 3.0 Web application.


 

<configuration>

<system.web>

<httpHandlers>

<remove verb="GET,HEAD,POST" path="*" />

<add verb="GET,HEAD,POST" path="*" type="Microsoft.SharePoint.ApplicationRuntime.SPHttpHandler, ..." />

</httpHandlers>

<httpModules>

<clear />

<add name="SPRequest"

type="Microsoft.SharePoint.ApplicationRuntime.SPRequestModule, ..." />

<!-- other standard ASP.NET httpModules added back in -->

</httpModules>

</system.web>

</configuration>


 

The WSS team members have created their own HttpModule named SPRequestModule to initialize various aspects of the WSS runtime environment. You can see that the standard WSS web.config file configures SPRequestModule so that it is the first HttpModule to respond to application-level events in the HTTP Request Pipeline of ASP.NET. If you examine the web.config file for a WSS Web application, you will see that WSS adds back in several of the standard HttpModule components from the ASP.NET Framework that deal with things such as output caching and various types of authentication.


 

The standard WSS web.config file also registers an HttpHandler named SPHttpHandler and configures it with a path of "*". This allows WSS to provide the SPHttpHandler class as a single endpoint for all incoming requests.


 

As you can see, the architecture of WSS is made possible through extending the HTTP Request Pipeline. This allows WSS to fully leverage the underlying capabilities of the ASP.NET Framework while also taking over control of each and every request that targets a Web application.


 


 


 


 

….. HaPpY CoDiNg

Partha(Aurum)

No comments:

Post a Comment