0

I have a custom model binder that takes a comma separated list and cleans out any empty values, then passes it along to the default model binder. This worked in ASP.NET MVC Preview 2, but when I upgraded to RC2, the below won't compile because the interface of ValueProvider only has a GetValue() method, no [] accessor. Is what I'm doing below possible through some other mechanism in the binding context? I'd rather not have to create a full blown model binder for such a simple situation. The main goal is when the values are bound to a List<SomeEnum>, any empty values are skipped.

public class EnumListModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = bindingContext.ValueProvider[bindingContext.ModelName];
        string[] rawValues = (string[])result.RawValue;
        var newValues = new List<string>();
        foreach (string value in rawValues)
        {
            if (!String.IsNullOrEmpty(value))
            {
                newValues.Add(value);
            }
        }

        string newValuesAttempted = String.Join(",", newValues.ToArray());
        // overwrite the ValueProviderResult with the cleaned up csv list
        // this is the part I'm not sure how to implement using the interface
        bindingContext.ValueProvider[bindingContext.ModelName] = 
           new ValueProviderResult(newValues.ToArray(), newValuesAttempted, result.Culture);

        return System.Web.Mvc.ModelBinders.Binders.DefaultBinder.BindModel(controllerContext, bindingContext);
    }
}
JeremyWeir
  • 24,118
  • 10
  • 92
  • 107

2 Answers2

1

What, exactly, is wrong with using GetValue() instead of [] here? It does the same thing. But ValueProvider is an interface now, and interfaces can't have indexers. Hence, GetValue().

Change your code to:

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

I'm a little surprised that the cast on the next line ever worked, though. Seems highly dependent on what the user actually submits and what the particular property type is. That's unrelated to your question, though.

Craig Stuntz
  • 125,891
  • 12
  • 252
  • 273
  • That's not the part that the change to the interface doesn't allow me to do. It's 2nd to last line where I overwrite the result in the ValueProvider collection – JeremyWeir Feb 25 '10 at 17:17
  • As far as the cast, I only use this model binder for properties that I know the form data will comply – JeremyWeir Feb 25 '10 at 17:20
  • You would need to update the *specific source* of the value (e.g., controllerContext.HttpContext.Request.QueryString[something]. – Craig Stuntz Feb 25 '10 at 17:21
  • I get a NotSupportedException "Collection is read-only" when I try to update the Request collections – JeremyWeir Feb 26 '10 at 17:49
  • Then you'll have to give in and use the model binder the way it was intended: Return a bound value instead of fiddling with the collection and calling `base`. – Craig Stuntz Feb 26 '10 at 18:19
0

There wasn't much of a solution here now that the ValueProvider collection is readonly. Instead I ended up using a custom model binder

Is there a way to have the DefaultModelBinder ignore empty items when binding to a List<Enum>

Community
  • 1
  • 1
JeremyWeir
  • 24,118
  • 10
  • 92
  • 107