MVC2 on Mono - Tips and Tricks for Windows Developers

So lately, I’ve been pretty wrapped up with kids and family so I haven’t had much time to post anything new.  However, I did start a new project, which I’ll detail out more as I go. It’s been quite the experience so far since I decided to build this one from the ground up using MySql and Linux/Mono.  I’ve never designed apps like that before. For one, I’ve had to learn a new set of design tools for MySql as opposed to my comfortable Sql Management Studio. And I’ve also had to very incrementally test different programming technologies and methods that were questionably supported in Linux/Mono.  The beauty of this is that no matter what I do to make it work for Mono, the app will always work on Windows, and there’s little development time lost if I have to fall back to its native platform.

So about this project…  Well it’s a simple project really: web based, MVC2 with a MySql database. So here’s a few technical issues I ran into while building the beginnings of this application.

Choosing a Data Framework

I know some of you purists would say stick to vanilla ADO.NET; it works every time, and you have no conversion problems. Well, that’s right, but I’m a lazy typist, and I really dig LINQ. So I tested several LINQ data frameworks on mono and found that Dblinq and SubSonic3 were the most functionally supported frameworks. I tested it with Linq to NHibernate, but it didn't work. SubSonic3, after a recent bug fix, now does work in Mono! 

MVC2 Works on Mono?

Yeah it does! Well mostly and only if you pull from the trunk code or the daily tarballs. Unfortunately, it does not work with the latest public release 2.6.4 and definitely not 2.4.4 which is the latest deployed version on Ubuntu 10.04. MVC2 now is officially supported by the Mono 2.8 release. MVC1 does work out of the box on older versions of Mono (2.6). So what do you have to do to get it working?  Until Mono 2.8 gets pushed into the packaging system, you'll need to learn a little bit about compiling Mono on your own and installing it, which sounds more painful that it really is. I wrote a script that works (most of the time) on Ubuntu.  There’s no guarantee that it will work for you of course. :)

Checkout one of my recent posts about manually getting Mono 2.8 installed.

Using MVC2 is the easy part. Just setup a new MVC2 project and ensure your reference options for the System.Web.Mvc and System.Web.Routing assemblies are set to Copy Local. Data annotations will not work, so you’ll need to rip out the model validation in the default MVC2 project; otherwise, the rest of it works like a charm.

xUnit and Dependency injection with Unity works too!

Yup, believe it or not, some of the components in the Enterprise Library do work in Mono including Unity, which works great for swapping out mock classes in test projects. I chose to use xUnit as my testing framework since it seemed to work pretty nicely in the SubSonic project. I also found a real nice breakdown of how they compare to other testing frameworks. The xunit command line runs on vanilla Ubuntu 10.04 (mono 2.4.4). However, my preferred method of running some of these tests is using the TestDriven.net runner on Windows/VS.

System Agnostic Gotchas

I’ve built and tested most of it on Windows. Which sometimes creates problems when deploying to non-Windows servers. Especially when it comes to I/O pathing.  As you go through and design it, you always have to build it in a platform agnostic manner. Duh right?  This includes simple things like case senstive paths, using the correct directory separators, etc. Typically as lazy Windows programmers (not all of us) :)  we would rather hard code the path separator like this.   string.Format(@“..\files\{0}”, filename);    But unfortunately that breaks Linux pathing. So by using Path.DirectorySeparator, it will automatically decide which is the correct character to use on either platform.
string.Format(“..{0}files{0}{1}”, Path.DirectorySeparator, filename);

The later versions of windows also support both slashes, so you could get away with using forward slashes in windows I/O on Vista and 7.

It can be advantageous (if working with a web application) to use System.Web.HttpContext.Current.Server.MapPath or System.Web.Hosting.HostingEnvironment.MapPath to get your native local path from a virtual one. So store your paths as virtual ones and let the framework convert it to a native/local one.

Image Rendering

Well, I haven’t completely dug into this, but I have briefly tested simple things like resizing images and writing them back out with Jpeg encoding. I have to say that the Mono built-in implementation of the GDI works just fine.  I even tested some other things like rendering speed as far as resizing a jpeg and writing it out. It seems using the System.Drawing as opposed to Mono’s GDK/Cairo actually works faster (only by observation; nothing official). I’ll have more detailed results on this as I get to that piece.

Wrap-Up

So if you’re interested in starting a new Mono project, I hope some of these tips will keep you out of trouble. Good Luck!