Creating my own HTTP webserver for desktop apps

Posted on December 7, 2013

0


What triggered this

I have been looking for solutions for a simple stand-alone Web server for a while: allowing me to distribute run the same C# .NET solutions I create for the Web as “desktop applications” anyone can download and run without any additional hassles (like installing a web server that is not standard part of most Windows installations).

Having done my first HTTP Server in Node.js the week before, I thought: this is it. My HTML is not dependent on Server Side rendering.

So this (creating my own Server) is all I need to do to get this problem (of not having a simple solution to run my web-based solutions on local machines without IIS installed) out of the way.

Single Page Applications, jQuery and HTML5

Most of what you see as “HTML5” is still HTML4 or DHTML. Basically granting JavaScript access to the Document Object Model (DOM) of HTML: allowing for manipulation of that very DOM by adding and removing elements at choice.

With jQuery (originally developed by John Resig) one of the biggest issues (that caused me to step away from web development in JavaScript/HTML) was solved: the JavaScript incompatabilities between browsers.

Offering a solid and thoroughly tested and properly updated solution (to find, access and manipulate objects in the HTML DOM) , jQuery opened a lot of new roads leading to more stable and more sustainable HTML applications.

Built on top of jQuery (which became the leading library among several others at that time) are frameworks like Underscore.js, Knockout.js and Backbone.js allowing you to build “templated” sites in which the main communication between client and server is reduced to data (mostly in JSON shape).

The stuff I build in this context are Single Page Applications, using HTML without any Server Side parsing and JavaScript / JSON to get and display/render the data.

The server

The simple Server I created basically uses TCP sockets: one to listen to a specific port on my machine. The others to deal with the specific connections requested by the clients that access the “Server Socket”.

It is written in C# as that is my platform of choice. I am thinking of a port in Java, (i.e. to run on Android) but the priorities are low for that specific project.

Simple Server setup

Simple Server setup

So what should this simple server do?

  1. Serve simple text files — Like HTML, JavaScript and CSS.
  2. Serve binary files — Like images and offer the possibility of “file downloads”.
  3. Handle POST and GET calls — transparently. So while the parameters are offered in different ways, the Request-object containing them Server side should just present them in the exact same way.
  4. Allow for complex (server side) actions — Like accessing databases and (pre) processing data.
  5. Be an alternative for IIS — Which is the default (Internet Information) server Microsoft provides
  6. Handle .NET MVC4 type calls — In the same way as IIS does
  7. Offer SSL — To make sure the data between the browser and server is save
  8. Allow for (easy) Server to Server communication — To allow for distributed systems and delegation of tasks to solutions like Node.js.

What it does not do

  1. Parse code inside the HTML — As I focus on HTML5 applications made from Server Agnostic code I do not want to (or need to or have to) parse code placed inside the HTML.
  2. Deal with (a lot of) concurrent users — As the user will start this server on the desktop and will only run local processes on a local browser.

Handling .NET MCV4 type calls

Hyperlinks in a .NET MVC web application no longer refer to pages. Instead they refer to a class in your DLL and one specific method in that Class.

For instance:

http://YourServer.com/people/getPerson

Refers to the MVC4 Controller class PeopleController and the method getPerson inside that controller.

Any parameter added (or value posted) will be translated by the .NET MVC framework to values you can address by the variable-names in the method definition itself. For instance with:

public string getPerson( Guid personID )

the .NET framework will try and resolve the call

http://YourServer.com/people/getPerson/?personID=<someGuid>

into <PeopleController >myPeopleController.getPerson( personID ) where the string-value personID sent in the request is parsed to a Guid.

Intended for JSON / AJAX Web Services

As stated before, I did not implement the processing of code inside HTML pages. Nor did I implement the ASP csHTML parser that allows you to use and bind HTML code with and within the ASP.NET framework.

Looking at the MVC4 framework, this might not be an issue what so ever. Probably the MVC framework itself takes care of this.

I simply did not bother for the current use of my Simple Server.

Reflection and Command mapping

The easiest solution I found to achieve the .NET MVC4 type of calls was by:

  1. Use reflection—  On the Public methods in the “Controllers”
  2. Inject each reference in a Command — To allow for strong-typing and encapsulate and abstract the actual actions required to deal with references gained by reflection in C#
  3. Map each Command — To a logical name that contains the “path” and the Method name as is the case in .NET MVC

The mapping part you will use in your application looks like this:

PeopleController myController = new PeopleController();
server.mapDelegateMethods("/people", myController);

The Server is the object we instantiated to accept incoming HTTP requests on a specific port.

Each method is mapped with “/” + method.Name as the structure. So: myController.getPerson will be mapped as “/people/getPerson”.

As .NET MVC accepts both /people/getPerson and people/getPerson/ we also map this Command with a slash at the end, like this: “/people/getPerson/”.

In principle, Microsoft solutions are case-insensitive. Meaning that “People” is the same as “people”. To gain this as an extra result, the path in the mapping and the path given in the requests can be cast to lowercase or uppercase.

Handling incoming requests

When a requests comes in to this simple Server, we:

  1. Parse — The request header and the body/ POST or GET abstracted away. Data is data.
  2. Check — What kind of request it is. An image? A file? Something we mapped?
  3. Execute — Then we execute the associated action, which might be either:
    1. Load a file — From the hard drive. Which can be an image, a CSS file, a HTML file or some binary like a ZIP or PDF.
    2. Save a file — If our Server code contains this option
    3. Delegate — To a mapped Command
  4. Return — The result from the execution.

Adaption of the core: run anywhere without drastic changes

As the application I am creating is both a MVC4 application to be run on a regular Webserver AND a DLL to be run in a custom Executable, I set out to create a solution that allows me to do both without any drastic changes in my original (Web-based) project.

Layering

Layering

The layering of the application can be separated in three parts:

  1. The Presentation Layer — Taking care of the presentation of the data and feedback from the Business Logic
  2. The Communication Layer — Taking care of communication between the Presentation Layer and the Business Layer
  3. The Business Layer — Taking care of the actual processing of requests and data sent from the Presentation Layer

Implementing the alpha version: Minimizing changes

Front end: no .NET code

By mimicking a normal Web Server as much as possible and implementing the same structure used in .NET MVC4 I can keep the HTML/JavaScript front end as is. Except from removing any and all dependencies on .NET from the HTML, the Presentation Layer does not require any changes.

This did require some refactoring. But as the application is a full-blown HTML5 Single Page Application, this did not had any real impact.

Instead of including “modules” with HTML into the main page, I now dynamically load them via jQuery and JavaScript.

No need to change hyperlinks / API calls

As my Simple Server mimics the .NET MVC structure, with proper mapping, all .NET MVC API calls simply work on the Simple Server as well. (Which is completely awesome.)

Refactoring the Controllers in my Communication Layer

To make my C# code work for both Servers I had to refactor my MVC4 Controllers. A lot of stuff was happening right there, making the code dependent on the platform it would run on. I extracted all actual actions and interactions (with the database) from the Controller code and placed them into separate classes.

This abstracted the actual processes from the technology that was using those processes to generate the results.

Writing adapters for IIS and My own Simple Server

The next step was to rewrite my MVC4 Controller to become an Adapter to the real Handler and create an exact copy of that Controller (all methods included) but then with a single HTTPRequest object as input (instead of the concrete variables).

No changes to the business logic

Using the new Separation of Concerns in which the “Controller” used in the MVC4 application and the Simple Server applicaton, the Business Logic itself remained unchanged.

Uploading files from the client

One last step to cover was the possibility to upload files via the browser to the Server.

In the application (used to manage financial transactions) you, the user, have to be able to upload your bank statements and have them processed by the Server so that you can start marking the financial transactions and see how you did over several periods in time.

The first pre-baked code I used simply bunked out 50% of the time: unable to deal with the data in a proper and stable way.

After spending half a day trying to find the cause, I simply switched to another solution using the C# StreamReader and StreamWriter: receiving the uploaded data 100% of all times.

Running the HTML5 application

Running the HTML5 application from my own Simple Server was one of the most exiting parts of this week. To know it is hypothetically possible is one thing, but to actually make it work (step by step) is another.

Moving from… to..:

  1. Handling simple file requests — Like “get HTML file with name <something>.html” and “get JavaScript File with name <something else>.js”
  2. Seeing Entity Framework work — Within a different environment and without any other change than assuring the references in the config-files had the same name and pointed at the right database
  3. Creating the first mappings for MVC4 type requests — And seeing actual data coming back from my own Server into the browser
  4. Refactoring the MVC4 Controllers — To run both in IIS and on my Simple Server
  5. Using reflection in C# to automate the mapping — So that I only have to state the Controller path and the concrete object that will deal with the requests

Each step was a little victory.

The trouble with SSL

I tried SSL for a while, but with the older version of my Simple Server, processes within that Server would suddenly go haywire, causing the application to go to maximum CPU usage.

This might be solved by some changes I made later (adding a small pause after executing certain processes being one of them).

To do

Later, either when I feel like doing this, or when needed, I will check and try to (re)implement the following:

  1. Server side processing — Of C# code in the HTML, unlocking the full potential of the MVC4 platform and allowing for any MVC4 application to run locally (as a “desktop application”) (and without installing IIS)
  2. SSL — This went wrong, causing the server to use maximum CPU power. Somehow the process do not get closed properly or some other things go wrong.
  3. Server side HTTP requests — To connect to other servers and services. While this is a relatively easy process, it is handy to have it as a standard part of the framework. One concrete use I have in mind is data-synchronization between separate Servers, sending and requesting data.
  4. Contact the original programmer of the base server — To notify him of this proect
  5. Make it public — To put my code up in GitHub so others can enjoy it as well.
Advertisements
Posted in: C# MVC4