Sunday, April 08, 2007

Porting a website from Rails to ASP.Net running on Mono

I've had a website I've been wanting to expand on for a long time (a college basketball site called Hoopd), which I originally implemented in Rails. I meant to do a lot more with it, though it's ended up just faithfully showing an RSS feed for a couple of years. Since that time I'm much more well versed in C# and never really ended up buying into the Ruby/Rails hype anyway.

So today I finally decided to give ASP.NET on Mono the college try. I've been running on a Redhat 9 box that would be tough to upgrade.

I'd like to outline what it entailed to get the small app running on Mono. Obviously, more complex ASP.NET sites will take a lot more work, but I thought I'd record the basics of what it took. For example, it has no database... yet. So there's a lot more learning to be done.


Getting Mono Running

I had attempted previously to get Mono running on this RedHat 9 box. To my delight, Mono 1.2 works right out of the box on RedHat 9 and Apache 2.0.x. However, xsp wasn't showing me any pages when I tried to get it to display a simple ASPX page.

I had to:

  • Get a new glibc (this is par for the course on Linux, right?)
  • Build and install a new APR library
  • Build and install mod_mono from scratch

At that point, xsp2 started to work on port 8080. Mod_mono was looking in the wrong place for mod-mono-server, so I linked it from /usr/local/bin/mod-mono-server to /usr/bin/mod-mono-server2. I didn't want to screw around with Apache configuration to get ASP.NET 2 functionality, so I just linked mod-mono to only use 2.0.

Getting the app to run

The actual coding of the ASP.NET app was very simple, and I won't outline it here. Suffice it to say, you can easily use Visual Studio 2005, precompile your applications, and run them in Mono.

That is, unless you have a bug in Mono itself. Those are painful to debug. I had one of these bugs today.

The first problem I ran into when trying to debug is that Mono has no support for App_Code directories. App_Code is a new structure in ASP.NET 2.0 that allows you to stash all of the business logic, whatever, into a separate directory than the web pages and their related code. As a result, I had to put <@ Assembly Src="App_Code/mydir/blahblahblah.cs" @> directives into my ASPX page to get Mono to compile them. Fortunately, I have only about 8 or 10 C# files right now, so this wasn't that difficult... but it wasn't fun either.

After I accomplished that, it was time to start debugging, right? Well, you can't really debug a running ASP.NET application on Mono on Linux. And, the reason I went through this process of adding Assembly tags is because Mono refuses to print out line numbers in stack traces for my code. It prints them for the System.dll libraries just fine, as well as the webpage, but all of those CS files I painstakingly added to my ASPX file did not get line numbers in the stack trace.

So how do you debug? System.Console.Writeline, of course. Running XSP2 and using strategic writelines narrowed down the problem and I was able to work around it.

The problem is that Microsoft's XPathNodeIterator and Mono's XPathNodeIterator behave a little bit differently, it seems. Microsoft's has "Current" already connected once the iterator has been filled, whereas Mono seems to skip the very first item and have a null in there. It's really odd. I have to debug it more, but since this is just for a silly RSS feed it's not urgent right now. The important part is that to figure this out, it required System.Console.Writeline. Yuck.

To debug stuff in the future, I'm going to see if I can run Mono's standard library from the debugger in Visual Studio. But at least I'll run Mono on my Windows box to speed up the debugging turnaround time a little bit. Though, if I get into hairy CLR problems with Mono, I'm sure I'll reach my breaking point quickly with this and ditch it for a Microsoft hoster.

Performance

Microsoft's debugging server delivers about 2-3x as many requests as Mono's production server. Tracing what Mono was doing, it seemed like it spent a lot of time in Viewstate code, even though I flagged about every possible way that it should ignore Viewstate.

Security

Mod_mono automatically knows to block web.config and C# files. There are a couple holes I found though:

  • A user can load Master pages directly with Mod_mono/Apache, which is automatically blocked by IIS. It's kind of humorous because it just shows you a template, but to some, this might be a security risk.
  • The bin/ directory of precompiled applications is not blocked by default. Use .htaccess to block it if you're using precompiled DLLs.

In conclusion, this was a successful experiment and I'm going to try to build out that site on mono as I had hoped I could. I'm glad to see Mono supporting an older version of Linux so well, and that I was able to get an existing app ported from another framework to ASP.NET running on Mono so quickly!

No comments: