Alex Rivera | Logout

Asp.Net MVC 2 - Bind a model's property to a different named value

Asked 2010-11-30T16:55:52.120
51

Update (21st Sept 2016) - Thanks to Digbyswift for commenting that this solution still works in MVC5 also.

Update (30th April 2012) - Note to people stumbling across this question from searches etc - the accepted answer is not how I ended up doing this - but I left it accepted because it might have worked in some cases. My own answer contains the final solution I used, which is reusable and will apply to any project.

It's also confirmed to work in v3 and v4 of the MVC framework.

I have the following model type (the names of the class and its properties have been changed to protect their identities):

public class MyExampleModel
{
  public string[] LongPropertyName { get; set; }
}

This property is then bound to a bunch (>150) of check boxes, where each one's input name is of course LongPropertyName.

The form submits to url with an HTTP GET, and say the user selects three of those checkboxes - the url will have the query string ?LongPropertyName=a&LongPropertyName=b&LongPropertyName=c

Big problem then is that if I select all (or even just over half!) the checkboxes, I exceed the maximum query string length enforced by the request filter on IIS!

I do not want to extend that - so I want a way to trim down this query string (I know I can just switch to a POST - but even so I still want to minimize the amount of fluff in the data sent by the client).

What I want to do is have the LongPropertyName bound to simply 'L' so the query string would become ?L=a&L=b&L=c but without changing the property name in code.

The type in question already has a custom model binder (deriving from DefaultModelBinder), but it's attached to its base class - so I don't w

Edit
Report

1 Answer

86

In response to michaelalm's answer and request - here's what I've ended up doing. I've left the original answer ticked mainly out of courtesy since one of the solutions suggested by Nathan would have worked.

The output of this is a replacement for DefaultModelBinder class which you can either register globally (thereby allowing all model types to take advantage of aliasing) or selectively inherit for custom model binders.

It all starts, predictably with:

/// <summary>
/// Allows you to create aliases that can be used for model properties at
/// model binding time (i.e. when data comes in from a request).
/// 
/// The type needs to be using the DefaultModelBinderEx model binder in 
/// order for this to work.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class BindAliasAttribute : Attribute
{
  public BindAliasAttribute(string alias)
  {
    //ommitted: parameter checking
    Alias = alias;
  }
  public string Alias { get; private set; }
}

And then we get this class:

internal sealed class AliasedPropertyDescriptor : PropertyDescriptor
{
  public PropertyDescriptor Inner { get; private set; }

  public AliasedPropertyDescriptor(string alias, PropertyDescriptor inner)
    : base(alias, null)
  {
    Inner = inner;
  }

  public override bool CanResetValue(object component)
  {
    return Inner.CanResetValue(component);
  }

  public override Type ComponentType
  {
    get { return Inner.ComponentType; }
  }

  public override object GetValue(object component)
  {
    return Inner.GetValue(component);
  }

  public override bool IsReadOnly
  {
    get { return Inner.IsReadOnly; }
  }

  public override Type PropertyType
  {
    get { return Inner.PropertyType; }
  }

  public override void ResetValue(object component)
  {
    Inner.ResetValue(component);
  }

  public override void SetValue(object component, object va
answered 2010-11-30T16:58:56.083

Your Answer