0

I have a class like this

public class Position
{
     public string Title { get; set; }
     public IEnumerable<string> PhoneNumbers { get; set; }
}

I wanted to use a textarea to accept phone numbers as one per line. After that the model obviously doesn't bind correctly, so I found IModelBinder that can help with this, but I don't see how I can inject the transformed data back into the model.

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
     var phones = bindingContext.ValueProvider.GetValue("phones");
     var values = phones.AttemptedValue;

     var phoneList = ..... //split and stuff

     //now what? how to set it back?

Thank you

Madd0g
  • 3,841
  • 5
  • 37
  • 59

2 Answers2

0

Create a new instance of your model, populate its properties and return it. Thats it.

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
     var phones = bindingContext.ValueProvider.GetValue("phones");
     var values = phones.AttemptedValue;

     var phoneList = ..... //split and stuff
//IE
    Position position = new Postion();
    position.PhoneNumbers = phoneList;
    return position;
}
Adam Tuliper
  • 29,982
  • 4
  • 53
  • 71
  • Yep, problem with that is I want to customize only one field, while I have lots of others that are mapped correctly. – Madd0g Nov 22 '11 at 19:48
0

Create a new class PhoneNumberList and use that instead of IEnumerable<string> in your model. Then you can create a custom model binder for PhoneNumberList by copying the existing code. Binding your existing model type Position will be otherwise unaffected.

Alternatively (but a more complex solution) - you can preserve the existing definition of IEnumerable<string>. You would subclass the DefaultModelBinder and examine the PropertyMetadata of any IEnumerable<string> property. If it contains some identifying metadata that you have added (e.g. via an attribute) then it could perform your custom binding, otherwise it reverts to the base binding.

As an aside - you could also consider using bindingContext.ModelName instead of hard-coding the value provider key to "phones":

var phones = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
Rich Tebb
  • 6,806
  • 2
  • 23
  • 25
  • The more complex solution is basically what I was looking for - but I couldn't find an example of converting and re-saving as different type with BindProperty – Madd0g Nov 23 '11 at 12:32
  • You don't need to save as a different type, the property's type remains as IEnumerable - you just create a List in the binder and assign that. – Rich Tebb Nov 23 '11 at 13:04
  • So in my binder I should cast `bindingContext.Model` to my model and then take the value from Request.Form, transform and assign to the casted model? – Madd0g Nov 23 '11 at 14:15
  • Take a look at DefaultModelBinder.BindProperty - see http://stackoverflow.com/questions/2245643/what-is-the-difference-between-bindproperty-and-setproperty-on-imodelbinder for some background (sorry, I'm a bit busy to create an example just now). – Rich Tebb Nov 23 '11 at 17:57
  • Yep, looks like that poster does it exactly like I described, thank you! – Madd0g Nov 23 '11 at 18:23