Serializing models for RouteValueDictionary and later model binding

(tl;dr : The bits, serializing to IDictionary<string, object> for RouteValueDictionary)

We have several spots in our ASP.NET MVC 2 app that need to serialize an object into a RouteValueDictionary so that, in a subsequent request, it can be inflated, resurrected by the model binding infrastructure.

We wrote extension method called ToHttpDictionary and we used it like this:

<%= Url.Action("index", "something", new RouteValueDictionary(Model.ToHttpDictionary())) %>

or like this:

RedirectToAction("index", new RouteValueDictionary(form.ToHttpDictionary()))

(and no, we do not use those raw helper method, we wrap them with a strong-typed, smarter one  = ) )

The goal is to transfer this example object, that we might accept as an action parameter:

var spec = new SearchSpecification
{
    FirstName = "John",
    LastName = "Doe"
};

Into the arguments for another request:

http://example.com/search?FirstName=John&LastName=Doe

That’s a lot easier than creating a form and a bunch of hidden fields just to store parameters for a GET request, or using that kludge anonymous type business.  It also makes working with RedirectResult extremely easy, skipping all the nasty TempData stuff you might be tempted to use.

At first we just needed some small, flat objects to be “un bound”, but then once we needed prefixes, the ability to skip properties, support for custom unbinders, and to handle arrays we decided to pull it into its own library and put it on CodePlex.

public static IDictionary<string, object> ToHttpDictionary<T>
    (this T model, params Expression<Func<T, object>>[] propertiesToSkip)
{
    SpecificValueUnbinderFactory.CustomUnbinders =
        () => new ISpecificValueUnbinder[]
        {
            new EnumerationValueUnbinder(),
            new PersistentObjectValueUnbinder()
        };

    return new Unbinder().Unbind(x => x.Source(model).SkipProperties(propertiesToSkip));
}

Custom value unbinders are the analog to custom model binders.  For example, I’ve seen model binders that take the Id of an Entity from the request and hydrate a full Entity object from persistence.  In that case we need an unbinder (sorry, I really can’t think of a better name for the concept) to serialize the Entity as the Id property.  That would look something like this:

public class PersistentObjectValueUnbinder : ISpecificValueUnbinder
{
    public string UnbindValue(object value)
    {
        return ((PersistentObject)value).Id.ToString();
    }

    public bool AppropriatelyUnbinds(object value)
    {
        return value is PersistentObject;
    }
}

And you’d plug it in to the factory function like in the above example.

It’s just a simple helper function, but the technique has been useful.

About these ads
This entry was posted in ASP.NET MVC. Bookmark the permalink.

6 Responses to Serializing models for RouteValueDictionary and later model binding

  1. Pingback: Dew Drop – March 18, 2010 | Alvin Ashcraft's Morning Dew

  2. Adam says:

    Hey,

    This is great. I still can’t believe its not built into Asp.net MVC yet.
    Was just about to write my own one when I saw this.

    Thanks
    Adam

  3. dotnetchris says:

    I came across unbinder and ergo your blog after seeing you post on https://groups.google.com/d/topic/mvccontrib-discuss/-SXUz265__0/discussion as I was trying to figure out what I needed to do to make PassParametersDuringRedirect not be wonky, which clearly is to just not use it and instead pass stuff through the routes.

    After some poking around it, I tweaked a few lines that could benefit being added, in the class Unbinder

    Line 60: var modifiedPrefix = string.IsNullOrWhiteSpace(prefix) ? name : prefix + “.” + name;

    Line 77: var prefixFormatString = string.IsNullOrWhiteSpace(prefix) ? “[{0}]” : prefix + “[{0}]“;

    Line 92: if (string.IsNullOrEmpty(prefix)) throw new ArgumentNullException(“prefix”, “prefix is required to unbind simple values”);

    After looking at unbinder it looks like I could have uses for it, is your code published to public domain or what license do you release your source under?

  4. federico says:

    Great IDEA. It is not a copy paste programming resource, it is OOD resource.

  5. Thanks a bunch for sharing this with all folks you really recognise what you
    are talking approximately! Bookmarked. Please
    additionally talk over with my website =).
    We may have a link trade arrangement among us

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s