ASP.NET MVC – SortDirection model binder

I’ve recently been working on an ASP.NET MVC 3 project. Yesterday I started working with the WebGrid that comes built-in. One thing that didn’t sit right with me was that the WebGrid posts the sort direction to your controller as either “ASC” or “DESC”, yet in the API when setting up the WebGrid in a view (we’re using Razor) you specify the sort direction using the enum System.Web.UI.WebControls.SortDirection.

I initially tried simply changing the sort direction parameter to be of type SortDirection. This doesn’t work though because the values posted by the WebGrid aren’t string equivalents to the enum values (ie. “Ascending” and “Descending”). So, to fix this problem, I decided to build out a custom model binder. Model Binders in ASP.NET MVC are the pieces that map the data provided by the client (browser) to your controller action parameters.

So here’s the model binder that I came up with.

using System.Web.Mvc;
using System.Web.UI.WebControls;

public class SortDirectionModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (string.IsNullOrEmpty(bindingContext.ModelName))
        {
            return null;
        }

        var valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (valueResult == null)
        {
            return null;
        }

        if (valueResult.AttemptedValue.IsNullOrWhiteSpace() || valueResult.AttemptedValue == "ASC")
        {
            return SortDirection.Ascending;
        }
        else
        {
            return SortDirection.Descending;
        }
    }
}

In the model binder we simply grab the posted value and determine if we need to return SortDirection.Ascending or SortDirection.Descending. Once we have the model binder written, we need to let ASP.NET MVC know about it by adding it to the ModelBinders.Binders dictionary. I put this code in the Global.asax file like this:

public class MyApplication : HttpApplication
{
    protected void Application_Start()
    {
        ModelBinders.Binders[System.Web.UI.WebControls.SortDirection] = new SortDirectionModelBinder();
    }
}
Advertisements

Getting Started with AutoTest.Net

I recently came across a new tool called AutoTest.Net.  This is a great tool if you are a TDD/BDD practitioner.  Basically AutoTest.Net can sit in the background and watch your source tree.  Whenever you make changes to a file and save it, AutoTest will build your solution and run all unit tests that it finds.  When it has run the tests it will display the failed tests in the AutoTest window (there is also a console runner if you are a hardcore console user). 

This takes away some of the friction that comes with unit testing because now you don’t have to do the step of build and run tests during development.  Simply write a test and save.  AutoTest runs your tests and you see a failed test.  Now implement the code that should make the test and save again.  AutoTest again detects the change and does a build and test run.  This cycle becomes automatic quite quickly and I’m finding I really like not having to explicitly build and run tests. 

Features

AutoTest.Net sports a nice set of features.  You can see the full list of features on the main GitHub repo page (scroll down) but here’s a few.  It supports multiple test frameworks including MSTest, NUnit, MSpec, and XUnit.net (I believe other frameworks can be supported by writing a plugin).  It can also monitor your project in two different ways.  One is by watching for changes to all files in your project (ie. watching the source files).  The other is by watching only assemblies.  Using this second method it would only run tests when you recompile your code manually.  I’m not sure where this would be preferred but I might find a use for it yet.

Edit: Svein (the author of AutoTest.Net) commented that one other compelling feature is Growl/Snarl support. If you have either one installed you can get test pass/fail notifications through Growl/Snarl, which means you don’t have to flip back to the AutoTest window to check that status of your code. Nice!

This leads me to one other feature that I missed and that is that AutoTest.Net is cross-platform. It currently supports both the Microsoft .NET framework as well as Mono. This means you can develop on OS X or Linux.

Getting AutoTest.Net

So, to get started, download AutoTest.Net from GitHub.  The easiest way is to click the “Downloads” link on the main AutoTest.Net project page and click one of the AutoTest zipfile links (at this time AutoTest.Net-v1.1.zip is the latest). 

AutoTest.Net Download

Once downloaded, unzip to a directory that you’ll run it from.  I’ve put it in my “utilities” directory.  At this point you can start using AutoTest.Net by running AutoTest.WinForms.exe or AutoTest.Console.exe.  If you run the WinForms version, AutoTest will start by asking you what directory you’d like to monitor for changes.  Typically you would select the root directory of your .Net solution (where your .sln file resides).  Once you’ve selected a directory and clicked OK, you’re ready to start development.

image

The screenshot above is the main AutoTest.Net window.  You can see that it ran 1 build and executed a total of 13 unit tests.  The neat thing is that now as I continue to work, all I need to do to cause AutoTest.Net to recompile and re-run all tests is to make a code change and save the file.  This sounds like a small change in the regular flow of code, save, build, run tests.  However, once I worked with AutoTest.Net for a while it started to feel very natural and going back to the old flow will feel like adding friction.

Configuration

Alright, so we have AutoTest.Net running and that’s good.  As with most tools, it comes with a config file, AutoTest.config (which is shared between the WinForms and Console apps).  This config file is well-documented so for the most part you can just open it up and figure out what knobs you can adjust.

Overriding Options

One nice feature that AutoTest.Net has is that you can have a base configuration in the directory where the AutoTest binaries reside but then override it by dropping an AutoTest.config file in the root directory that you are monitoring.  This allows you to keep a sensible base config in your AutoTest application directory and then override per-project as needed.  Typically I’ve been setting the “watch” directory as the directory that my .sln file is in and so you’d drop the AutoTest.config file in the same directory as the .sln file. 

image

In the above screenshot I have the AutoTest.config file which overrides a few settings, one of which is the ignore file: _ignorefile.txt

IgnoreFile Option

One option that is useful is called the IgnoreFile.  This is well-documented in the config file but it didn’t click with me initially.  The IgnoreFile option specifies a file that contains a list of files and folders that AutoTest.Net should ignore when monitoring the configured directories for changes.  The config file mentions the .gitignore file as an similar example so if you are familiar with git, it should make sense.  The one piece that took me a while to figure out was where this ignore file should go.  I finally figured out that if you put it in the root of the monitored directory (ie. beside your .sln file), it will pick it up (see above screenshot). 

Wrapping up

AutoTest.Net is a great tool to help with the Red, Green, Refactor flow.  It removes some of the friction in my day-to-day work by eliminating the need to manually invoke a compile and test run. 

Lastly, the observant readers will have noticed that I said it builds and runs all tests any time it notices a file change.  Greg Young is working on a tool called Mighty Moose that builds on top of AutoTest.Net as an add-in to Visual Studio (I think there’s a standalone version too).  Mighty Moose ups the ante by figuring out what code changed and what tests would be affected by that change.  It then only runs the affected tests, significantly cutting down the test run time. 

>Lessons learned using an IoC Container

>

I am working on my first project that’s using an IoC container heavily.  Overall it’s been a very positive experience.  However, we have learned some things have caused us pain in testing, bug fixing, and general code maintenance.

Separate component registration from application start-up

This is a constant source of problem on our project.  If you don’t separate component registration from your component start-up path you often run into a chicken-and-egg problem.  You may be resolving a component that depends on other components that haven’t yet been registered.  This makes for a very brittle start-up path that is prone to breakage as you add dependencies to your components.  Now the container that is supposed to decouple things is causing you to micromanage your component registration and start-up. 

The solution is to split registration from component start-up.  This makes perfect sense to me now, but wasn’t so obvious when we started the project.  Lesson learned!

Be careful with a global service locator

We went quite a while without using a global service locator (essentially a singleton instance of the container) but eventually found that we needed it.  This might have been avoided with better design-fu but we couldn’t think of a better alternative at the time. 

What we found was that the global container made things difficult to test.  This became especially painful when we needed to push mock objects into our container and than manually clean up the registrations to replace them with the production components that other tests might expect.  I’d be interested in hearing if you have a way to solve this problem, and if so, how.

Use a Full-Featured Container

When we started the project we had intended to use Enterprise Library for some features.  EntLib has Unity integration so we settled on using Unity as our IoC container by default.  The container itself has served us extremely well.  What we’ve found lacking in the container though is it’s supporting infrastructure features.  A container like StructureMap comes with alot of nice features that aren’t core IoC features.  For example, it reduces the “ceremony” (as Jeremy D. Miller would say) of registering components by providing convention-based component registration.  StructureMap also provides detailed diagnostics that help you figure out what’s wrong with your component registrations if things don’t work.

That summarizes the biggest points that we’ve learned so far.  I’d be interested to hear some “gotchas” that you’ve learned from using an IoC container “in anger”. 

>Imaginet Webcast – Dependency Injection with StructureMap

>

I did a webcast today on StructureMap and Dependency Injection. Overall it went ok (except that I forgot to turn on the audio part of LiveMeeting for the first few minutes and had to restart). I’ve clipped that from the video so you won’t have to watch me walk through slides without audio.

You can grab the content using the following links:

Edit (June 25, 2008) – I’ve uploaded the presentation finally. Note that for the first few minutes I didn’t have my audio on. I restarted once I figured that out. It’s a bit raw, but after several attempts to re-encode the presentation I decided to give up and just publish it.

If you have any questions feel free to post them in a comment to this post.

>Imaginet Webcast Series

>

Several of my colleagues from Imaginet and I will be presenting a series of webcasts starting on May 14th. This series will be pretty broad in what is covered, but in most cases will be very technical (ie. low on Powerpoint, high on code). These webcasts will all start at 11:15 am EST and will be about 1/2 hour each.

If you’re looking through this schedule and you have other ideas on what you’d like to see, feel free to leave a comment and we’ll try to cover that topic in the future.

Here’s the schedule.

Topic Presenter Date
Customizing Team System Process Templates Steve Porter 14-May-08
Introduction to Software Factories Robert Regnier 21-May-08
Windows Communication Service Gateways
with C # 3.0 and
Linq-To-SQL
Dave Harris 28-May-08
Testing out the MVC: Routing Ryan Weppler 04-Jun-08
Customizing Software Factories Robert Regnier 11-Jun-08
Dependency Injection with StructureMap Jeremy Wiebe 18-Jun-08
Nhibernate: An Entry-Level Primer Dave Harris 25-Jun-08
Creating Real world applications with CSLA 3.5 David Maynard 02-Jul-08
MVC vs MVP smackdown Robert Regnier 09-Jul-08

>Common Log File System and System.IO.Log

>

I was poking around the MSDN documentation looking for some Trace information and I stumbled upon the System.IO.Log namespace. I haven’t had a chance to work with it yet (and at this point I’m not sure how usable it would be for general application development as it’s only available on Vista and Windows Server 2003 R2) but it looks intriguing.

DevX.Com has a nice introduction to it here.

I’m not sure that this will displace my favourite logging tool but competition is never a bad thing (although I have strong feelings about fragmentation, especially in the open source world, just for the sake of “having my own project” but that’s content for a different blog post).

Powered by ScribeFire.