Now that we have a listener for HTTP requests, and a hosted MVC application, it’s time to connect them, which turns out to be more complex than it sounds.

The way in which requests should be handed to the HttpRuntime is through a call to the static ProcessRequest method:

public static void ProcessRequest(HttpWorkerRequest wr)

The problem is: HttpWorkerRequest is abstract and has over 70 methods that should be implemented to be able to pass every possible request to the ASP.NET pipeline (the HttpRuntime will call into those methods to find details about the request).

So whatever host calls into the HttpRuntime will have to provide its own implementation of HttpWorkerRequest for wrapping its http requests.

We can check those who did by searching derived types:

httpworkerrequest

All except the SimpleWorkerRequest are IIS specific implementations, which tightly integrate with the proprietary and native code IIS engine. The SimpleWorkerRequest itself is an implementation which when used to wrap HTTP requests allows you to send simple requests into the ASP.NET pipeline. However, that’s about it: the concept of streams, certificates (security),  completely misses, so it’s not much more than a proof of concept: it won’t enable you to unleash the full power of the ASP.NET engine.

So we’re out of luck, we have to make our own implementation. An (incomplete) example can be found in an old msdn magazine.

Wrapping the request and sending it into the pipeline then looks like this:

private void ProcessRequest(HttpListenerContext context)
{
   _log.DebugFormat("Processing request");
   var wr = new HttpListenerWorkerRequest(context, VPath, PPath);
   HttpContext.Current = new HttpContext(wr);

   HttpRuntime.ProcessRequest(wr);
   _log.DebugFormat("Finished processing request");
}

But it fails at runtime…

It turns out we run into another problem: since the request is received in the default AppDomain, and processed in the ASP.NET AppDomain, we have to pass either the HttpListenerContext – like we did above – or our implementation of the HttpWorkerRequest between AppDomains. No matter how you do this (MarshalByRefObject, WCF), it requires serialization. And guess what ? None of these is easily serializable, for one because they contain the request and response streams…

At this point I decided it would save me a lot of work if I moved the Listener we created into the ASP.NET AppDomain as well, and do away with the serialization mess.

So ultimately, I ended up with a factory method which:

  1. creates a new appdomain and hosts my implementation of HttpApplication
  2. sets up a HttpListener in this new AppDomain
  3. wraps the HttpListenerContext in a custom implementation of HttpWorkerRequest
  4. sends it into the HttpRuntime

And finally…it works…I managed to have a fully functioning MVC application hosted in-process with my main application.

There are some loose ends to tie up though, like serving static files. I may touch on that in a follow up.

Ruurd Keizer

Author Ruurd Keizer

Quantumphysics PhD disguised as software architect, developer, and cloud native platform greasemonkey. Analytic, pragmatic, result oriented, never forgetting the bottom line. Interested in the whole picture: from businessvalue down to the bare metal.

More posts by Ruurd Keizer
23 May 2013

Leave a Reply