Saturday, May 31, 2008

Mixins are a language idea similar to multiple inheritance, but rather than extending a class a mixin works by defining an interface plus various functionality associated with that interface. It avoids the pathologies of multiple inheritance and is a flexible way of providing add-on functionality.

In C# we can create a mixin with a combination of an interface plus extension methods. LINQ is the canonical example of this with two core interfaces IEnumerable<T> and IQueriable<T> and a collection of extension methods on those interfaces.

It's easy to create your own mixins. For example, say I want to provide location functionality to various entities. I can define an interface like this:

Thursday, May 29, 2008

I've just spent this morning upgrading Suteki Shop to the latest version of the MVC Framework; CTP 3. There are some nice touches in it, but not an awful lot has changed, especially if, like me, you've been using the Code Plex source that was recently made available. Scott Guthrie details most of the major changes with this release on his blog.

Action Result

Still, it wasn't all plain sailing, there have been a lot of API changes since the last code drop. The names of the new controller action return values have changed as have the properties on the Controller base class which return them. I had to do a global find and replace for those. I'd written some nice test helper extension methods around ActionResult which had to be upgraded.

View data changes

The changes to view data caused a lot of churn as well. Now, instead of two separate kinds of view data; dictionary and strongly typed, there's a single class ViewDataDictionary<T> that supports both, with a new Model property having the type of the type parameter. This means that every invocation of ViewData in your View has to change to ViewData.Model. Currently I factor all my view data into a strongly typed hierarchy that I can pass through to various html helpers I've written, but with the new style view data there might be an opportunity for some nice refactorings.

Select rendering changes

Anther change which brings up some nice possibilities is the separation of the DropDownList html helper extension (renamed from 'Select') from the actual building of the select list itself in a SelectList class that you can pass from the controller along with all its data. Providing select lists from an IoC container might be a nice way to factor the loading of lookup data out from the controller.

One thing caught me out though. They've changed the order of the 'value' and 'text' parameters from the old Select helper method. I got some nasty runtime errors because of this.

'Hidden' extension method changes

Another nasty was the Hidden html helper extension method that renders an '<input type="hidden">' tag. It now takes a string as its value parameter instead of an object. For some reason the aspnet compiler doesn't seem to catch this change and so my forms were failing at runtime with the value parameter as an empty string.

MVCContrib

Probably the biggest investment of time this morning was changing the MVCContrib code to work with CTP 3. No, I didn't upgrade the entire thing; I just ripped out anything I wasn't using and upgraded the rest. It wasn't too bad in the end which must be tribute to the quality of the code. Once Jeremy and co have got the whole thing working with CTP 3, I'll move back to the main branch.

It's really fun working with the MVC Framework. The pace of development has been swift and it's nice that the team don't have to bake in the API at this stage which has allowed them to progressively factor the framework with feedback from the community. Sure it means that you have to spend half a day changing your code to work with a new release every so often, but if that means the design can evolve rapidly, I'm all for it.

Monday, May 26, 2008

The default build process for aspx files is a problem in web site development. By default they only build on request, so nasty compile time errors can lay hidden until you actually hit the problem page when looking at the site. This is a real pain; when I hit F6, I want everything to build.

I've only recently come across the command line tool aspnet_compiler. It simply pre-compiles all the aspx pages in your web application. You can run it as a post build event which means all your aspx templates get built each time:

Now when you build, you get aspx errors reported too. Clicking on the errors takes you to the correct place in the aspx file, just like with regular .cs code:

Now is this common knowledge that I've just somehow missed out on. It seems strange that I had to work out this trick by myself?

I recently wrote about how nice it is to use the MetaWeblog API to allow tools like Live Writer update content on bespoke software like my Suteki Shop eCommerce application (which is now morphing into a generic CMS). The one thing I didn't like was the step that requires the user to enter the API their site exposes and it's endpoint:

A little more digging around the Live Writer docs and various blogs led me to discover Really Simple Discovery (RSD). It's an XML schema for describing the APIs that your software exposes by Daniel Berlinger.

In the head of your homepage you have a link to the location of your rsd.xml file:

As you can see it simply contains the web site engine name (suteki shop), the URL of the engine's homepage and the URL of this instance's homepage. Then follows a list of APIs that the engine supports. In my case it's a single entry for MetaWeblog that shows the XML RPC endpoint.

In the case of Suteki Shop, since it's an MVC Framework based application the rsd.xml file itself is generated from a view that simply inserts the current application URL where, in this case, "http://localhost:63638" appears.

Wednesday, May 21, 2008

I've just added the MetaWeblog API to the Content Management System (CMS) of Suteki Shop. It's most excellent. It means that an administrator can manage the content of the web site using a slick WSYWIG tool like Windows Live Writer. I simply ripped the code for the API from Subtext, a really nice open source blogging application. It took me most of today to get it working, but it'll be a major win for my users who I can't expect to write HTML straight into a web based admin interface.

It's really easy to set up. Simply open up Live Writer and add a new account saying you want to use 'Another weblog service':

Then enter the URL of the application, here I'm just giving it the URL of the Visual Studio Development Web Server. You also need to enter an admin username (email) and password.

The last step is to tell Live Writer that Suteki Shop uses the Metaweblog API and point it to the XmlRpc endpoint that hosts the API.

After that it's all set up and you can write a post, including images in live writer:

When you click the 'Publish' button the content magically appears with a new menu item on the Suteki Shop site:

You can find my subtext's implementation of the MetaWeblog API the usual place:

Sunday, May 18, 2008

If you install the MVC Framework CTP2 you may notice that it doesn't come with a nested master page template, but don't worry it very easy to create your own from the existing Web Forms template. Here's how:

First add a standard (web forms) nested master page:

Next, in the code behind file 'myNested.master.cs' inherit from System.Web.Mvc.ViewMasterPage:

Thursday, May 15, 2008

Scaffolding is an idea from Ruby on Rails. It's a way of providing a simple default implementation of common views of data in a web application. After coding a couple of Controllers for the simple administration of lookup data in Suteki Shop, I got really bored of the repetitive coding and decided to write a simple scaffolding controller. Using an IoC Container and the IRepository pattern makes this really easy. To create a new scaffolding controller simply write:

public class CountryController : ScaffoldController<Country>
{
}

And here's a screen-shot of the two country views, Index and Edit.

It's clever enough to work out which properties are foreign keys and get the correct lookup table to populate the 'Post Zone' combo box. It also uses my generic ordering implementation to allow you to reorder the items (that's the little green up and down arrows in the list of countries). Unfortunately, I haven't got around to auto generating the views yet, so you still have to write those.

All the code can be found in Suteki Shop as usual. But just to show how it's really quite simple, here's the full code of the ScaffoldController:

I've been putting some thought into validation in the context of an MVC Framework application. Recently I wrote about using Extension Method Validators as a neat way of expressing validation rules in your domain entities. These validators throw a ValidationException when they trigger.

Now in a user interface we would really like to see all the validation failures for a form. So we need to collect the exceptions as they occur and then continue processing. Here's a neat little Validator class that's simply a collection of Action delegates that executes them when its Validate method is called:

Since the 'property' variable is an empty string, each call to IsRequired() will throw a ValidationException. The message of each of these exceptions gets captured and then a single ValidationException will be called with the concatenated messages.

Here's a minor bug that really foxed me until I managed to google the answer. With the latest MVC Framework code from CodePlex the routing has changed. It's now much more flexible, but one side effect is that it only kicks in if the requested resource can't be found on disk. So if you have a placeholder (blank) Default.aspx page in the root of your project as in previous versions of the MVC Framework, it actually gets rendered. Unfortunately you need that Default.aspx page for cassini (the Visual Studio development web server) to work. The work-around is to put a Response.Redirect in the code-behind of the Default.aspx placeholder:

Code Rant

Notepad, thoughts out loud, learning in public, misunderstandings, mistakes. undiluted opinions. I'm Mike Hadlow, an itinerant developer. I live (and try to work in) Brighton on the south coast of England.

All code is published under an MIT licence. You are free to take it and use it for any purpose without attribution. There is no warranty whatsoever.