ASP.NET HttpWorkerRequest

ASP.NET web programming framework

HttpWorkerRequest helps with performance. It is not commonly used, but provides big advantages in some cases to more common classes. You can use the powerful HttpWorkerRequest in a reliable way. It can benefit your ASP.NET program.

This ASP.NET article covers the HttpWorkerRequest type in depth. It has C# example code.

Example

Note

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.

Example that uses HttpWorkerRequest [C#]

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;
	}
    }
}
Hypertext transfer protocol (HTTP)

Description. 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.

Set 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.

Example that uses SendKnownResponseHeader [C#]

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");
}

Problems

Warning

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.

Performance

Performance optimization

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 [C#]

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) [C#]

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

Intrinsic objects

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

Uri type

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.

Uri Class

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.

Get HttpWorkerRequest

Programming tip

Next, let's look at a public static class that contains one method named Get, and this method accepts a reference to the current HttpContext and then returns the reference to the HttpWorkerRequest accessed through that reference. Unfortunately, the HttpWorkerRequest is considered a lower-level type and is used mainly for internal ASP.NET work, so this logic is required to access it.

Class that accesses HttpWorkerRequest [C#]

using System;
using System.Web;

/// <summary>
/// Contains logic for the worker request.
/// </summary>
public static class WorkerTool
{
    /// <summary>
    /// Cached type of worker request.
    /// </summary>
    static Type _workerType = typeof(HttpWorkerRequest);

    /// <summary>
    /// Get the worker request for this context in ASP.NET.
    /// This is encapsulated here because it is very implementation-specific.
    /// </summary>
    /// <param name="context">The context for the current request.</param>
    /// <returns>The worker request, useful for low-level ASP.NET processing.</returns>
    public static HttpWorkerRequest Get(HttpContext context)
    {
	IServiceProvider provider = context; // Cast to interface
	var worker = provider.GetService(_workerType) as HttpWorkerRequest; // Get worker
	return worker;
    }
}

Calling code snippet

var context = HttpContext.Current; // Get context
var worker = WorkerTool.Get(context); // Get worker
string url = worker.GetRawUrl(); // Use worker

WorkerTool.Get method implementation. The WorkerTool static class contains two members, one being a static Type pointer to the type of the HttpWorkerRequest, and the second being the casting logic and GetService call required for getting the worker. The Type pointer is stored in static memory to avoid having to use reflection more than necessary during request processing and this provides a performance benefit. The 'as' cast is used for slightly better performance than a regular cast.

As Cast Example

Why use HttpWorkerRequest?

Question and answer

The best reasons to use HttpWorkerRequest in your ASP.NET projects are for features that are not available through the Response and Request objects, and also performance. There are precise ways to get the Accept-Encoding headers with the HttpWorkerRequest that are not available elsewhere in the framework. Also, using HttpWorkerRequest avoids some overhead with collections that are otherwise required for headers.

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.

From: HttpWorkerRequest Class at MSDN.

Summary

The C# programming language

We saw how you can use the secret HttpWorkerRequest to develop C# 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.

ASP.NET Tutorials
.NET