Archive for June 2009

Custom data binding with MonoRail 1.0

Yesterday I had a solution where I wanted to receive a domain entity as an action parameter, similar in concept  to the built-in ActiveRecord data-binding. In my situation though I wanted to use a slug to identify the entity. My URL’s look like this:

/news/slug-goes-here

which I want to result in calling into:

public class NewsController
{
    public void Index(NewsItem item)
    {
    }
}

The first step here is to setup routing to suit. We currently just use an XML file to hold our routing rules, so this route entry just looks like

 <rule> 
    <pattern>^/news/([^/]+)$</pattern>
    <replace>/news/index?item=$1</replace>
  </rule>

With this in place, our Index action will receive item as an argument. All that’s left to do is tell MonoRail how to bind the item argument to our NewsItem type. There are two approaches available here: you can derive a class From DataBinder and pass it to the SmartDispatchController contructor, or you can create a new attribute that implements IParameterBinder and attach it to the action’s parameter. Unfortunately in MonoRail 1.0 the DataBinder class from what I can tell is really only extensible via inheritance, so I have used the attribute approach.

MonoRail’s source is a real help here, since you can inspect DataBindAttribute.cs to see what the class should be doing. Here is the implementation I ended up with:

public class NewsItemAttribute : Attribute, IParameterBinder
	{
		public int CalculateParamPoints(SmartDispatcherController controller, ParameterInfo parameterInfo)
		{
                        CompositeNode node = controller.ObtainParamsNode(From);
                        IDataBinder binder = CreateBinder();
                        return binder.CanBindObject(typeof(string), prefix, node) ? 10 : 0;
		}
 
		public object Bind(SmartDispatcherController controller, ParameterInfo parameterInfo)
		{
                        IDataBinder binder = CreateBinder();
                        ConfigureValidator(controller, binder);
                        CompositeNode node = controller.ObtainParamsNode(From);
                        var slug = (string) binder.BindObject(typeof(string), prefix, exclude, allow, node);
			var instance = IoC.Resolve<INewsItemRepository>().GetBySlug(slug);
                        BindInstanceErrors(controller, binder, instance);
                        PopulateValidatorErrorSummary(controller, binder, instance);
                        return instance;
		}
	}

The only line of note here is the IoC.Resolve() call. To my knowledge you cant use DI with attributes, so we’re stuck with using the service locator approach. The rest of the code is straight from the DataBindAttribute source.

I’ve not yet gotten the chance to use ASP.NET MVC in a project, but from what I’ve read the ModelBinder facility appears a much cleaner approach to this problem than that possible with MonoRail 1.0.

Guide to iPhone Jailbreaking

My guide to iPhone jailbreaking has been belatedly published on AusGamers. With firmware 3.0 out in the next few days interest will likely be pretty low, but it was still fun to do some writing in English for a change.

Using Ubuntu 9.04 as a Xen dom0 host with NVidia driver

I guess this is a somewhat unusual setup, but I wanted my desktop to be usable as a Xen dom0 for testing and I need the nvidia driver for Xorg.

There’s two core problems here:

  • While Ubuntu provides the Xen hypervisor and associated utilities (imported straight from Debian’s repository), Ubuntu does not provide a Xen-enabled kernel.
  • The NVidia kernel module is not supported on Xen-enabled kernels.

I’m using the x64 version of Ubuntu, I dont see why i386 wouldn’t work either. This text assumes you already have a working Ubuntu 9.04 desktop with the proprietry Nvidia driver installed from Ubuntu repository.

Step 1: Install Xen using Debian kernel. The easiest way to get a suitable kernel is to use the Debian Lenny kernel. This blog post neatly summarises the steps required: download linux-image and linux-modules from Debian and install, add ubuntu-xen-desktop package, remove network-manager package, and configure /etc/network/interfaces to use DHCP. I found that GRUB was setup correctly without needing any effort on my behalf.

Step 2: Remove repository-provided Nvidia module and install Kernel headers. The Nvidia kernel module as supplied by Ubuntu does not function correctly under a Xen dom0, if used a black screen is simply displayed and /var/log/X0rg.0.log will show that Xorg has frozen during startup. If you simply reboot into the new Debian kernel, you will not even get that far though, as the DKMS build step of the nvidia module will fail due to the missing headers. To get around the black screen problem you need to install Nvidia driver straight from their website, using a few flags to configure it to work on Xen.

Before getting that far though, you need to remove the Ubuntu-supplied NVidia driver and install Debian’s kernel header packages. I was using the “nvidia-glx-180″ package, so execute “apt-get remove nvidia-glx-180 nvidia-180-kernel-source”. Next, find the header packages from Debian corresponding to the linux image you downloaded in Step 1. In my case I am using “linux-image-2.6.26-2-xen-amd64″ and I needed three .deb’s: “linux-headers-2.6.26-2-common-xen”, “linux-headers-2.6.26-2-xen-amd64″ and “linux-kbuild-2.6.26″. You also need gcc-4.1 installed to build the module.

Step 3: Install the NVidia driver from their website. I downloaded NVIDIA-Linux-x86_64-180.60-pkg2.run , since that is basically the same version that Ubuntu supplies. This page on NVnews.net has the magic incantation required: as root, you need to run

IGNORE_XEN_PRESENCE=y CC="gcc -DNV_VMAP_4_PRESENT -DNV_SIGNAL_STRUCT_RLIM" ./NVIDIA-Linux-x86_64-###.##-pkg2.run

Now reboot into the Xen kernel and the Ubuntu desktop should appear as per normal.

Installing Ubuntu 9.04 Netbook Remix on Asus eee

The good news is everything “just works” from the install, but there is one minor configuration issue that the installer misses. The eee has a feature called ‘Boot Booster’, which requires a small partition (8MB seems fine) on the SSD with a specific partition type (OxEF, which is EFI partition).

I normally would just install with the “Use entire disk” option, but to get this 8mb partition left over you need to choose the option to partition manually. Assuming you have a 16GB SSD:

  • Create a primary 15.5GB Ext3 partition, mounted as /
  • Create a primary 8MB partition, set to ‘do not use’
  • Use the remaining space (just under 0.5GB)  as a logical partition, set to ’swap area’.

The rest of the installation can then be completed normally. After rebooting into Ubuntu, open a Terminal and run “sudo cfdisk /dev/sda”. From here, you can change the type of the 8MB partition to EF, then write the changes to disk and reboot. You will see the Asus boot screen one more time, then Grub appears. To make sure the change worked, hit CTRL-ALT-DELETE at the Grub screen to restart. This time the BIOS screen should be skipped and Grub will re-appear.

Increasing the Windows XP IIS connection limit

Stefan passed on this handy blog post discussing the IIS connection limit in Windows XP. The default is 10 connections which I had always presumed could not be changed, but it can actually be increased to 40 connections – which is a bit more useful if you need to do any performance testing.