HttpListener Series – 2 – Websiting   1 comment

The series index here.

One of the most common uses of IIS is to host websites through a file system folder where relative paths are used for resources. There isn’t much to it but some string prefix handling and some stream copying but I’ll provide a simple implementation of what it needs to be done to run a simple static website.

Let’s say we have a folder containing a website looking like this:


The content of the files is as follows…


    <title>HttpListener Demo HTML Page</title>
    <link rel="stylesheet" type="text/css" href="Files/Styles.css" />
        Here is the HTML page.</p>
    <input type="button" id="aButton" value="Click to Run Script" />
<script type="text/javascript" src="Files/Scripts.js"></script>


    font-size: 20px;
    font-weight: bold;

    border: 2px solid blue;
    font-style: italic;


document.getElementById("aButton").onclick = function () {
    alert("You clicked the button");

The implementation of this website hosting would be something like so:

string baseFolder = @"C:\WebSite\";

var listener = new HttpListener();

Console.WriteLine("Listening ...");

while (true)
    var context = listener.GetContext();

    Console.WriteLine("Request received for: " + context.Request.Url.AbsoluteUri);

    var baseUrl = "http://+/HLD/".Replace("+", context.Request.Url.Authority);
    var resourceRelativePath = context.Request.Url.AbsoluteUri.Substring(baseUrl.Length);
    var resourceFullPath = Path.Combine(baseFolder, resourceRelativePath);

    if (File.Exists(resourceFullPath))
        context.Response.StatusCode = 200;
        context.Response.StatusDescription = "OK";

        string contentType = "application/octet-stream"; // just to have a default
        switch (Path.GetExtension(resourceFullPath))
            case ".htm":
                contentType = "text/html";
            case ".css":
                contentType = "text/css";
            case ".js":
                contentType = "application/x-javascript";
        context.Response.ContentType = contentType;

        var fileStream = File.OpenRead(resourceFullPath);
        context.Response.ContentLength64 = fileStream.Length;
        fileStream.CopyTo(context.Response.OutputStream, 64*1024);
        context.Response.StatusCode = 404;
        context.Response.StatusDescription = "Not Found";
        var writer = new StreamWriter(context.Response.OutputStream);
        writer.Write(string.Format("<!DOCTYPE HTML><html><head><title>Resource Not Found</title></head><body><b>Error 404 - Resource Not Found</b> - There resource ('{0}') requested was not found.</body></html>",


A little bit of string comparison and we’re all done. Now you can access “http://localhost/HLD/Page.htm”.


  • The functionality of a default document can be easily be implemented by responding to an empty resourceRelativePath with a predefined document.
  • Response.ContentType must be set before beginning to send the resource stream, otherwise it will not be taken in account.
  • 64KB (64B * 1024) of buffering to copy the resource stream should be enough. Play with and find what it implies in the speed of the delivery and find your own buffer size.

Posted 2012/07/09 by Bigsby in Hands On

One response to “HttpListener Series – 2 – Websiting

Subscribe to comments with RSS.

  1. Pingback: HttpListener Series « Bigsby Spot

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: