My TechEd HttpListener WebServer Demo
On Friday, the last day of TechEd, the very last session was a session called the GrokTalk session where Dave Glover, myself, Darren Neimke, Greg Low, Phillip Beadle,Bill Chesnut (aka Biztalk Bill), Mitch Denny and Adam Cogan all delivered a short 8-10 minute presentation on one of our favourite .Net V2 features.
My 8-10 minutes of fame was on the HttpListener class that is available in the .Net V2 framework. It is basically a managed wrapper around the HTTP.SYS kernel mode networking component that is used by IIS6 to provide HTTP Web serving features. I demonstrated how you can use this object to write a complete web server that processes HTML, ASPX, and ASMX/WebService files with only around 50 lines of code.
I have had some interest in this code so I thought I would briefly explain it and provide a link where you can download the entire code. So without further waffling, you can download the code and the small directory sample of web server files I used from here (http://www.theglavs.com/glavtech/downloads/techedhttplistenerdemo.zip).
By way of explanation, the code currently sets up an ApplicationHost using the C:\HttpListenerWebHost directory. There are 2 projects provided in the sample. 1 is the SimpleAppHost (which takes care of creating the new AppDomain, and providing the code to process the pages themselves). The other is the code to initialise the HttpListener and pass requests to the newly created host for processing. You should note that there is a 'post' build step to copy the SimpleHost.dll to the C:\HttpListenerWebHost\Bin directory so that it can be easily accessed by the HttpRuntime.
So the steps are:
1. Initialise the Host
_host = SimpleAppHost.SimpleHost.InitialiseHost();
this in turn calls
SimpleHost theHost = (SimpleHost)ApplicationHost.CreateApplicationHost(typeof(SimpleHost), "/", @"c:\HttpListenerWebHost");
2. Initialise the HttpListener
private static void InitialiseListener()
{
_listener = new HttpListener();
_listener.AuthenticationSchemes = AuthenticationSchemes.Basic;
string prefix = string.Format("http://+:{0}/", PORT_NUMBER);
_listener.Prefixes.Add(prefix);
_listener.Start();
}
3. Wait/Listen for a request (done in a separate thread) or a key press on the console
private static void ListeningThread()
{
while (_keepAppRunning)
{
HttpListenerContext context = _listener.GetContext();
4. Send the request to the Host for processing
htmlOutput = _host.ProcessRequest(ctxt.Request.Url.LocalPath.Replace("/",""),ctxt.Request.Url.Query.Replace("?",""));
5. Close the listener if a key pressed or "quit=true" is passed as a URL argument.
6. if Step 5 not true, go to Step 3.
Looks to easy to be true huh? Well its actually not much more than that. The actual code to process al the file types I have listed above is nothing more than a few lines of code as shown below:
public string ProcessRequest(string page, string query)
{
// Process the request and send back the string output
using (System.IO.StringWriter sw = new System.IO.StringWriter())
{
HttpRuntime.ProcessRequest(new SimpleWorkerRequest(page, query, sw));
return sw.ToString();
}
}
This will serve up the pages themselves ie. full server side processing of ASPX pages, as well as ASMX pages, generation of WSDL files etc.