Programming · Summer of Code 2007

Make any .NET app a Web Server

While researching of my SOC project (FastCGI ASP.NET server), I stumbled across a neat little trick. In 4 lines of code, you can run an ASP.NET webserver from any .NET application:

XSPWebSource source = new XSPWebSource (System.Net.IPAddress.Any, 8080);
server = new ApplicationServer (source);
server.AddApplicationsFromCommandLine ("/:/path/to/asp.net/application");
server.Start (true);

Presto, you’ve got an ASP.NET server running on your computer. The only caveat is that the pages are running in a different AppDomain (aka a different universe) so you can’t access your static classes from an ASP.NET page and have to do DBUS style transactions to get any information.

Fortunately, there are two internal object types capable of crossing the boundary between between this world to the next: ISerializable and MarshalByRefObject. ISerializable being a traveler, moving from one domain to the other, but remembering nothing except what it contains within itself, and MarshalByRefObject having a foot in both worlds, sending ISerializable messages from one to the other.

The gateway between domains is someDomain.SetData(string name, object data) and someDomain.GetData (string name).

An example of ISerializable:

someDomain.SetData ("cowSay", Cow.Say ());

...

someDomain.GetData ("cowSay") == "Moo!"

MarshalByRefObject on the other hand is a bit more useful:

public class AnimalNoises : MarshalByRefObject {
   public string CowSay () {return Cow.Say ();}
}

someDomain.SetData ("animalNoises", new AnimalNoises ());

...

(someDomain.GetData ("animalNoises") as AnimalNoises).CowSay () == "Moo!"

So, now it’s possible to send information from one domain to another. To get the domain for the ASP.NET pages, you call:

AppDomain myDomain = server.GetApplicationForPath (null, -1, "/", true).AppHost.Domain;

You access the object in the ASP.NET page via:

AnimalNoises noises = AppDomain.CurrentDomain.GetData ("animalNoises") as AnimalNoises;

Finally, to avoid countless errors, you need to A) include the path to the calling application in MONO_PATH so it can be used to create the AppDomain, and B) create a link to the DLL declaring AnimalNoises in the application root’s bin directory so the ASP.NET pages can be compiled against it.

Putting it all together, you can get something like this:

Banshee XSP Plugin

Instructions:

  1. Download XspPlugin.cs to ~/.config/banshee/plugins/
  2. Modify it so it points to your banshee config directory.
  3. gmcs XspPlugin.cs -target:library -r:Mono.WebServer2 -pkg:banshee
  4. mkdir ~/.config/banshee/plugins/xsp
  5. Download index.aspx to ~/.config/banshee/plugins/xsp/
  6. mkdir ~/.config/banshee/plugins/xsp/bin
  7. ln -s XspPlugin.dll xsp/bin/XspPlugin.dll
  8. MONO_PATH=/usr/lib/banshee banshee
  9. Visit http://localhost:8080

Now, combine with avahi-sharp, a good sound daemon, and several more sophistocated ASP.NET pages, and you’ve turned banshee into a household music server.

The same could be done for an F-Spot photo browser, a BitTorrent client, etc.

Enjoy,
Brian

P.S. There is probably a much easier way of doing this, but this worked for me.

Advertisements

3 thoughts on “Make any .NET app a Web Server

  1. I ever think about this, but I never try it. Now I know I will meet this problem: “you can’t access your static classes from an ASP.NET page and have to do DBUS style transactions to get any information.”

    It’s really interesting, thanks.

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s