Memmexx Web Server Walkthrough
The Memmexx web server is a .Net dll that provides web
server functionality for any .Net program. It is open-source, and thus can be modified to suit the
needs of the developer. One only
need to reference its dll or include the Memmexx web server code in a solution.
This document walks the programmer through the task of
creating a simple web server with some CGI functionality. More documentation will exist when the
author gets over his Wii addiction.
;)
The Memmexx web server is untested in Mono. The programmer prefers Stereo for its
more lifelike representation of music.
A sample of the walkthrough is present in this
distribution. The reader must read
the last part of the walkthrough to learn how to configure the web server.
The Memmexx web server is released under the BSD license:
Copyright (c) 2007, Andrew Rondeau
All rights reserved.
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the following
conditions
are met:
Redistributions of source code must retain the above
copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above
copyright
notice, this list of conditions and the following disclaimer in
the
documentation and/or other materials provided with the distribution.
Neither the name of the Andrew Rondeau nor the names of its
contributors
may be used to endorse or promote products derived from this software
without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The Memmexx web server was created by Andrew Rondeau. You can contact him at http://www.andrewrondeau.com.
This is the only documentation that currently exists for the
Memmexx web server.
This documentation assumes familiarity with C#, .Net, and
Visual Studio. While a new C#
programmer might be able to follow this document; a programmer should have some
C# experience before using the Memmexx Web Server.
Some familiarity with web technologies is assumed. Specifically, the programmer should
understand basic HTML and forms.
Please be aware that the Memmexx web server is not
guaranteed to correctly conform to any standard, or to be free of defects. It is tested with daily use from Safari
and Internet Explorer 7. It has
not had any load testing.
We will create a web server that runs in the console. In Visual Studio, navigate to File
-> New -> Project. Select
Visual C# -> Windows -> Console Application.

In the Solution Explorer, right-click on References and
select ?Add Reference?.

On the ?Browse? tab, select Memmexx.WebServer.dll.

Before we can start writing some simple web server code, we
must shave a few yaks.
Add a ?using Memmexx.WebServer;? to Program.cs.

Add a class named WalkthroughWebServer.


Add a ?using Memmexx.WebServer?, inherit from the ?Session?
class, and implement an empty CloseSession() method.

The Memmexx web server provides some simple session
management functionality, through Cookies. (It is also possible to pass session IDs through get
arguments, but that won?t be documented until after I beat Zelda on the Wii!)
What happens is that when a web browser opens up a page
served by the Memmexx web server, a new Session object is created. (In this walkthrough, we will use
WalkthroughWebServer.) For each
subsequent request, the session cookie is used to find the appropriate Session
object.
Session objects expire after 15 minutes of inactivity. When this happens, CloseSession() is
called, and the object is eligible for garbage collection.
It is important to remember the following:
? Each
unique user has a unique session object.
? The
session is identified by a cookie stored in the user?s web browser.
? Session
objects are closed and garbage collected after 15 minutes of inactivity.
What happens if there is a request for an expired (or
non-existent) session? Nothing! A new one is created! For complex web applications, the
programmer must use care to trap errors that can occur when a session expires. (There is a section at the end to
describe how the Memmexx web server supports error handling.)
Now that we have created an empty implementation of the
Session class, we need to do the following tasks:
Our web server will be rather, uhm, basic, at this point.
To do this, we will create a WebServer object and then call
its RunServer() method.

Run the program.
(Push F5)
Navigate to ?localhost? in Internet Explorer.
The program?s console output will show some debugging
information.

You will see a pending request. This is okay; the Memmexx web server will keep a connection alive if the browser supports such behavior.
In the browser, there will be an error. There is no index.html to serve! This situation will soon be remedied.

We will now create some static and dynamic content.
First, stop the program.
In the solution explorer, right-click on the ?Walkthrough?
project and select Add -> New Item

Select ?HTML Page? and name the file ?Index.html?

(Note: the default extension is .htm. Make sure that .html is used.)
Put some text on the web page:

We will now point the web server to the directory where the ?index.html? file resides. Typically, Visual Studio runs the executable in a subdirectory of a subdirectory of where the project resides, thus we will use ?..\..?. In the event of an error, this directory can be hardcoded to wherever you put the project.
To do this, modify the constructor for the WebServer class in Program.cs.

Run the program and refresh the web browser. (Point it to localhost) Note: Due to some funny behavior in Internet Explorer, Refresh might not work. If it doesn?t work, click inside the address box and hit enter; or restart Internet Explorer.

We will add a form that adds two numbers.
In Index.html, add a form that has two text boxes and a
submit button. In this example, we
will name the text boxes ?num1? and ?num2?. The action of the form is ?Add.420?, and the method is
?get?.

Save the page and refresh the web browser. There is no need to restart the
program.

You might have noticed that if you click on ?Submit Query?, there is an error. This is because the dynamic code isn?t added to the web server yet!
Stop the web server.
Add a function to WalkthroughWebServer that takes no arguments and returns an object of type WebResults. It must have an attribute named [WebCallable].
This is an important point that must be emphasized: The Memmexx web server allows the Session class to have methods that are directly called as the result of a Form. All functions that can be called directly from a Form must meet the following requirements:
The extension of the form?s action must be .420. (In this case, the action is ?Add.420?.)
Here is a simple version of Add(). (There is no error handling; this will be left as an exercise for the reader.)
[WebCallable]
public WebResults Add()
{
// Convert the get parameters (which are strings) into numbers
float num1 = int.Parse(SafeGetParameters["num1"]);
float num2 = int.Parse(SafeGetParameters["num2"]);
float sum = num1 + num2;
// This type of WebResults object automatically creates a page to display from Strings
return WebResults.FromString.CreateFromTitleAndBodyText(
this,
"Results of addition",
sum.ToString());
}

Start the program.
There is no need to refresh the browser, because there are no html
changes.
yields 
Some additional notes:
A powerful feature of web development tools like ASP and PHP
is their ability to call dynamic code from within HTML. The Memmexx web server allows an HTML
page to call functions as well.
Add the following to Index.html:
@#_MyDymanicFunction_These are the arguments!_#@

Function calls are worth explaining:
Just like Add(), a function named MyDymanicFunction must be
added to the WalkthroughWebServer class.
This function follows similar rules:
Here is a sample of MyDynamicFunction:
[WebCallable]
public string MyDymanicFunction(string arguments)
{
return
"<em>MyDymanicFunction was called with</em><font size=\"+1\"> \""
+ arguments + "\" </font><em>as the argument</em>";
}
Note this function in the debugger:

(The arguments variable contains the arguments that we put
into index.html.)
Function calls can be recursive; that is, a function can
return a function call encoded in the @#_..._..._#@ format, and it will be
called. (This is an advanced topic
that the programmer will hopefully someday show, hopefully after he?s done
collecting all the yak hair stuck in his teeth.)
The Memmexx web server allows a web page to access
properties of objects used inside of objects available to a [WebCallable]
function.
For this example, we will create a small class and two
functions:
public class ActiveParseExample
{
public ActiveParseExample(int num, string str)
{
_Num = num;
_String = str;
}
public int Num
{
get { return _Num; }
}
private int _Num;
public string String
{
get { return _String; }
}
private string _String;
}
[WebCallable]
public string ActiveParseEnumeration(string arguments)
{
ActiveParseExample[] apes = new ActiveParseExample[] {
new ActiveParseExample(1, "one"),
new ActiveParseExample(2, "two"),
new ActiveParseExample(3, "three")};
// Use a StringBuilder to build the response
StringBuilder toReturn = new StringBuilder();
foreach (ActiveParseExample ape in apes)
{
string part = ReplaceVarsWithValues(arguments, ape);
toReturn.Append(part);
}
return toReturn.ToString();
}
[WebCallable]
public string ActiveParseSingle(string arguments)
{
return ReplaceVarsWithValues(arguments, new ActiveParseExample(0, "single"));
}
We will also add the following to index.html:
<p><em>Example of auto-replace in an enumeration:</em><br />
@#_ActiveParseEnumeration_Num: [_Num_], String: [_String_]<br />_#@</p>
<p><em>Example of auto-replace for a single value:</em><br />
@#_ActiveParseSingle_Num: [_Num_], String: [_String_]<br />_#@</p>

ReplaceVarsWithValues() is a function in the base session class. It takes a string and an object as arguments. Wherever the string has a property name in [_..._] format, it replaces it with the value of the property. (If the property isn?t a string, it calls ToString()). Thus, all instances of [_Num_] are replaced with the ActiveParseExample object?s value for the Num property.
Start the program and refresh the web browser:

A note on recursion:
The will replace [(_foo_)] with [_foo_], and [((_bar_))]
with [(_bar_)].
The Memmexx web server supports two kinds of methods for
gracefully handling errors that can occur at runtime. Some errors may occur if a request assumes that the session
is in a certain state. (This may
happen when a session expires.)
Other errors may occur due to security violations. Memmexx?s methods for handling errors
work through exceptions, and are as follows:
For all other exceptions, the Memmexx web server informs the user that an error occurred and displays NO INFORMATION from the exception object. This is because some lower-level exceptions often contain information that is helpful to hackers. If more useful debugging information is desired, the Memmexx web server will display debugging information when built in Debug mode. One can either include the Memmexx.WebServer project in the solution, or build it from source code. (Building the Memmexx web server is not documented here.) DO NOT USE THE DEBUG VERSION OF THE MEMMEXX WEB SERVER IN A PRODUCTION ENVIRONMENT ON THE PUBLIC INTERNET. YOU HAVE BEEN WARNED!!!
These examples assume some savvy-ness with web programming. In both cases, we?ve added function calls to Index.html. The functions check for the presence of Get arguments, which are hard-coded into the hyperlink.
Add the following function to the WalkthroughWebServer
class:
[WebCallable]
public string WebResultsOverrideExample(string arguments)
{
// We will use a Get parameter to indicate that this exception should be thrown
if (SafeGetParameters.ContainsKey("WebResultsOverrideExample"))
{
WebResults webResults = WebResults.FromString.CreateFromTitleAndBodyText(
this,
"Example of WebResultsOverride",
"Example of WebResultsOverride");
throw new WebResultsOverrideException(
webResults,
"This is an example of using the WebResultsOverrideException");
}
// Otherwise, return nothing
return "";
}
Add the following to Index.html:
@#_WebResultsOverrideExample__#@<a href="index.html?WebResultsOverrideExample=1">Test WebResultsOverrideExample()</a><br />
To test, click on the new link.
Add the following function to the WalkthroughWebServer
class:
[WebCallable]
public string SafeExceptionExample(string arguments)
{
// We will use a Get parameter to indicate that this exception should be thrown
if (SafeGetParameters.ContainsKey("SafeExceptionExample"))
throw new SafeException("SafeException example");
// Otherwise, return nothing
return "";
}
Add the following to Index.html:
@#_SafeExceptionExample__#@<a href="index.html?SafeExceptionExample=1">Test SafeExceptionExample()</a><br />
To test, click on the new link.