My TechEd HttpListener WebServer Demo

Published Sunday, September 4, 2005 11:03 PM

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.

by Glav

Comments

# Mike Blake-Knox said on Wednesday, September 7, 2005 5:19 PM

Great! I'm just totally amazed at how simple your application is!

I'm hoping to use httpListener as a lightweight way to communicate with an xmlHttp (ajax) client.

How does one send multiple responses for a single POST to the client?

Mike

# Paul Glavich said on Wednesday, September 7, 2005 7:58 PM

You can't really send multiple responses to one POST unless you batch up the responses in one response. HTTP is request/response and XMLHTTP does not change that so you can only repond to a single request. You wont be able to issue multiple responses after one request.

AJAX/XMLHTTP simply makes multiple requests in the background (asynchronously) so it can look like you are getting multiple responses from one request, but its not the case.

# Gope said on Friday, August 11, 2006 8:52 AM

Hello Paul, amazing stuff. I would really like to download your sample, but the link to the zip seems to be no longer valid. Is it still downloadable somewhere?

# Glav said on Friday, August 11, 2006 9:36 AM

Sorry about the missing link. You can now download this sample from here http://www.theglavs.com/DownloadItem.aspx?FileID=51

# Glav said on Friday, August 11, 2006 9:42 AM

The new location for the sample code is here http://www.theglavs.com/DownloadItem.aspx?FileID=51

# HSD said on Thursday, October 26, 2006 10:16 AM

Knock Knock... Is anyone there?

# Glav said on Thursday, October 26, 2006 8:36 PM

Yes there is someone home, although a lot of the comments get lost in the enourmous amounts of SPAM I get from the blog.

If you want to contact me, please use the contact form or send mail to "glav AT aspalliance DOT com"

# fredrik said on Thursday, November 2, 2006 8:58 AM

I have written an aspx website and want a winform to host it. Is that possible to do with your httplistener sample? my default.aspx render in my browser but any buttons etc donĀ“t work :(

# Glav said on Thursday, November 2, 2006 5:16 PM

Yes its possible to take the code and modify that to host ASPX pages in a windows forms app. However, processing of button events, Javascript issues and other things may cause problems. I haven't tried this, but the HttpListener provides the infrastructure for you to build it. To get a fully fledged web server though, you might want to look at the Cassini source code (dont have the URL handy - sorry). That is the web server that comes with VS.NET 2005.

# Martin Ramsey said on Monday, July 2, 2007 6:04 AM

Hi, just wondering if you have been able to debug into code behind ASPX pages, I can't seem to manage it, I know the code behind is executing cos dynamic content I generate there appears on the page but I can't find the process to attach to hit breakpoints ?

# Hans said on Monday, December 10, 2007 11:55 AM

Hi,

I've created a (very simple) ASP.NET web application with a single *.aspx page and an *.aspx.cs CodeBehind file: With a click on an HTML form button, a text control value is written into a label below using a click handler and a server roundtrip. Pretty nifty, I know...

Now I want to run this mini app using the HttpListener example from above, but it doesn't work. The *.aspx page gets published but obviously the actual server operation/click handler is not executed, the label stays blank. And after the server roundtrip the text control is empty again, no session seems to be managed although the corresponding hidden form values are there.

Can you point me into a direction, what may be different when the web application runs fine with the ASP.NET development server launched by Visual Studio? What to look for to have a real web application hosted by an own HttpListener based approach - any ideas?

Thanks in advance + greetings,

Hans

# Mike said on Tuesday, June 10, 2008 11:24 AM

Same question as Hans. I need CodeBehind to work on the ASPX page, with access to classes that are part of the main program that launched the listener, or even part of the listener itself... But no luck. It only works if the entire C# code is self-contained in the ASPX page.

# matt said on Friday, August 14, 2009 6:28 PM

Is it possible to use this listener with custom HttpHandlers for specific or custom file extensions. I'm trying to figure out a way to create tests for a pixel tracking application that uses custom HttpHandlers mappted to a custom extensions (e.g. *.ibmx).

# Glav said on Saturday, August 15, 2009 3:46 AM

Matt, I guess it maybe possible but I would say its the rong approach. Abstracting the dependencies so that you can effectively test it would be a better appraoch.

Leave a Comment

(required) 
(required) 
(optional)
(required) 

This Blog

Syndication