ASP.NET中的HttpWorkerRequest对像及其应用

HttpWorkerRequest对像在ASP.Net处理流程中的位置:

每一个ASP.NET程序执行时都会对当前URL的请求进行解析,本文将分析ASP.NET页面请求的原理。当我们在浏览器上输入一个URL时, 流程如下:

首先被WWW服务器截获(inetinfo.exe进程), 该进程首先判断页面后缀, 然后根据IIS中配置决定调用具体的扩展程序。

如aspx就会调用aspnet_isapi.dll, 然后由aspnet_isapi.dll发送给w3wp.exe(iis 工作者进程,IIS6.0中叫做 w3wq.exe,IIS5.0中叫做 aspnet_wp.exe).

接下来就是w3wp.exe调用.net类库进行具体处理,流程如下:

ISAPIRuntime-->HttpRuntime-->HttpApplicationFactory-->HttpApplication-->HttpModule--HttpHandlerFactory-->HttpHandle

1. ISAPIRuntime

主要作用是调用一些非托管代码生成HttpWorkerRequest对象,HttpWorkerRequest对象包含当前请求的所有信息,然后传递给HttpRuntime,这里生成的HttpWorkerRequest对象可以直接在我们的页面中调用的,通过它取得原始的请求信息:

2. HttpRuntime
a. 根据HttpWorkerRequest对象生成HttpContext,HttpContext包含request、response等属性;
b. 调用HttpApplicationFactory来生成IHttpHandler(这里生成的是一个默认的HttpApplication对象,HttpApplication也是IHttpHandler接口的一个实现)
c. 调用HttpApplication对象执行请求

3. HttpApplicationFactory.

主要是生成一个HttpApplication对象:

首先会查看是否存在global.asax文件,如果有的话就用它来生成HttpApplication对象,从这里我们可以看到global.asax的文件名是在asp.net的框架中写死的,不能修改的。如果这个文件不存在就使用默认的对象。

4. HttpApplication

这个是比较复杂也比较重要的一个对象, 首先是执行初始化操作,比较重要的一步就是进行HttpModule的初始化:

HttpApplication代表着程序员创建的Web应用程序。HttpApplication创建针对此Http请求的 HttpContext对象,这些对象包含了关于此请求的诸多其他对象,主要是HttpRequest、HttpResponse、 HttpSessionState等。这些对象在程序中可以通过Page类或者Context类进行访问。

它会读取web.config中所有HttpModule的配置

5. HttpModule

6. HttpHandlerFactory

7. HttpHandler

HttpWorkerRequest 的应用

1. Using HttpWorkerRequest for getting headers

First, the HttpWorkerRequest class is used internally by ASP.NET, and provides a lower-level way of accessing ASP.NET internals. In this code, we see that you can use the HttpContext to call GetService and get the current worker. Then, you can use the same code that the intrinsic objects use, but with no overhead.

using System;
using System.Web;

public class Handler1 : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        IServiceProvider provider = (IServiceProvider)context;
        HttpWorkerRequest worker = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
        //
        // Get the Referer with HttpWorkerRequest.
        //
        string referer = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderReferer);
        //
        // Get the Accept-Encoding with HttpWorkerReqest
        //
        string acceptEncoding = worker.GetKnownRequestHeader(HttpWorkerRequest.HeaderAcceptEncoding);
        //
        // Display the values.
        //
        HttpResponse response = context.Response;
        response.Write("Referer: ");
        response.Write(referer != null);
        response.Write(" Accept-Encoding: ");
        response.Write(acceptEncoding);
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

Description of the HttpHandler. This is a generic handler you can run in the code-behind file of a HTTP handler. You can use the contents of the ProcessRequest method anywhere in ASP.NET, through. The first lines with IServiceProvider simply use an interface to get the HttpWorkerRequest.

Using the worker instance. The example shows how you can get the referer of the page and also the Accept-Encoding headers. You can do this with the Request object, but it is slower and more prone to errors. Finally, the example prints the text of the headers it accessed.

2. Using HttpWorkerRequest for setting headers

Here we see how you can set HTTP headers with the HttpWorkerRequest. This allows you to bypass the ASP.NET AddHeader method, which has a fair amount of overhead. We specify that the handler should be cached for 2 hours here. The SendKnownResponseHeader method is not exactly the same as AddHeader, but sometimes you can use it instead.

public void ProcessRequest(HttpContext context)
{
    IServiceProvider provider = (IServiceProvider)context;
    HttpWorkerRequest worker = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
    //
    // Set Cache-Control with HttpWorkerRequest.
    //
    worker.SendKnownResponseHeader(HttpWorkerRequest.HeaderCacheControl, "private, max-age=7200");
}

3. Gotchas with HttpWorkerRequest

The HttpWorkerRequest is not commonly used in simple or small ASP.NET projects, and it is much harder to use. For example, its settings can interact in different ways with your Web.config. Setting the Content-Length is very tricky to get right. Due to the complexity of the class, these are things you will have to hack through.

4. Performance of HttpWorkerRequest

Here we see a simple benchmark that compares setting two HTTP headers on a response. The first method uses the Response object, and the second method uses the HttpWorkerRequest object. Internally, the first version will call into the same methods as the second version. In other words, the result is obvious from the internal layout of the runtime.

=== HTTP header method versions benchmarked ===

public static void Set1(HttpContext context, string contentEncoding, string cacheControl)
{
    context.Response.AddHeader("Content-Encoding", contentEncoding);
    context.Response.AddHeader("Cache-Control", cacheControl);
}

public static void Set2(HttpContext context, string contentEncoding, string cacheControl)
{
    IServiceProvider provider = (IServiceProvider)context;
    HttpWorkerRequest worker = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
    worker.SendKnownResponseHeader(HttpWorkerRequest.HeaderContentEncoding, contentEncoding);
    worker.SendKnownResponseHeader(HttpWorkerRequest.HeaderCacheControl, cacheControl);
}

=== Calling code (1 million iterations) ===

Set1(context, "gzip", "private, max-age=7200");
Response.ClearHeaders();

Set2(context, "gzip", "private, max-age=7200");
Response.ClearHeaders();

=== Benchmark results ===

Set1 Response:          895 ms
     Note:              Uses AddHeader
Set2 HttpWorkerRequest: 488 ms
     Note:              Uses SendKnownResponseHeader

5. Intrinsic objects in ASP.NET

You can accomplish almost everything that HttpWorkerRequest lets you do with the Context, Request and Response instrinsic objects. However, when you use Request and Response, they execute complicated and slow logic. Eventually, these objects then use HttpWorkerRequest themselves.

Example of using referer. When you call the UrlReferer property on Request, the property does several string comparisons and then creates a new Uri object. This causes a heap allocation. If you check the UrlReferer on every request, this overhead can add up.

AppendHeader method. When you open the AppendHeader method in ASP.NET, you will find a lot of complex logic and error checking. Often you do not need all this overhead. Internally, the method also calls into the HttpWorkerRequest.

6. Resources

You have very likely seen the MSDN topic about this class, but it bears repeating. It states that usually "your code will not deal with HttpWorkerRequest directly." However, it adds that this may be necessary to implement if you are implementing your own hosting environment. [HttpWorkerRequest Class - MSDN]

An excellent blog resource. The most helpful resource on using this class directly is by Daniel Cazzulino. He shows how you can use GetKnownRequestHeader for very specific requirements relating to networks. [ASP.NET low-level fun - Daniel Cazzulino's Blog - weblogs.asp.net]

7. Real-world results with HttpWorkerRequest

The author modified his code to use HttpWorkerRequest in 4 places. The result is that each request is processed about 20 microseconds faster. These timings are real-world and use the accurate Stopwatch class on the requests.

8. Summary

Here we saw how you can use the 'secret' HttpWorkerRequest to develop web applications that are faster and have clearer code in some respects. This is considered a lower-level interface to ASP.NET, and it should be used with care and testing. For scalability and performance, the HttpWorkerRequest is superior. Using it reduces allocations and avoids lots of code execution.

原文地址:https://www.cnblogs.com/tuyile006/p/1542355.html