2009-11-08 5 views
0

Я хотел бы сделать сложную проверку в моей форме, которая содержит список объектов.MVC Complex Model Binding

Моя форма содержит список, допустим, MyObjects. MyObject состоит из двойной суммы и MyDate, которая является всего лишь оберткой в ​​DateTime.

public class MyObject 
{ 
    public MyDate Date { get; set; } //MyDate is wrapper around DateTime 
    public double Price { get; set; } 
} 

Форма ...

<input type="text" name="myList[0].Date" value="05/11/2009" /> 
<input type="text" name="myList[0].Price" value="100,000,000" /> 

<input type="text" name="myList[1].Date" value="05/11/2009" /> 
<input type="text" name="myList[1].Price" value="2.23" /> 

Вот мое действие

public ActionResult Index(IList<MyObject> myList) 
{ 
    //stuff 
} 

Я хочу, чтобы позволить пользователю вводить в 100.000.000 для цен и для пользовательских модели связующего к разделите ',', чтобы он мог преобразовать в double. Аналогично, мне нужно преобразовать 05/11/2009 в объект MyDate. Я думал о создании MyObjectModelBinder, но не знаю, что делать дальше.

ModelBinders.Binders[typeof(MyObject)] = new MyObjectModelBinder(); 

Любая помощь оценивается.

ответ

2

Вот пример реализации пользовательской модели связующего:

public class MyObjectModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     // call the base method and let it bind whatever properties it can 
     var myObject = (MyObject)base.BindModel(controllerContext, bindingContext); 
     var prefix = bindingContext.ModelName; 
     if (bindingContext.ValueProvider.ContainsKey(prefix + ".Price")) 
     { 
      string priceStr = bindingContext.ValueProvider[prefix + ".Price"].AttemptedValue; 
      // priceStr = 100,000,000 or whatever the user entered 
      // TODO: Perform transformations on priceStr so that parsing works 
      // Note: Be carefull with cultures 
      double price; 
      if (double.TryParse(priceStr, out price)) 
      { 
       myObject.Price = price; 
      } 
     } 

     if (bindingContext.ValueProvider.ContainsKey(prefix + ".Date")) 
     { 
      string dateStr = bindingContext.ValueProvider[prefix + ".Date"].AttemptedValue; 
      myObject.Date = new MyDate(); 
      // TODO: Perform transformations on dateStr and set the values 
      // of myObject.Date properties 
     } 

     return myObject; 
    } 
} 
+0

Thankyou, я делал что-то подобное я. Если проверка не выполняется, я просто использую AddModelError для bindingContext? У меня также есть 5 других строковых свойств в MyObject. Есть ли лучший способ перебирать свойства, а не делать, если содержит префикс ключа + и т. Д.?? – David

+0

Да, если произошел сбой проверки, вы используете 'AddModelError' и' SetModelValue' в bindingContext. Что касается других свойств, вы можете сделать следующее: 'var myObject = (MyObject) base.BindModel (controllerContext, bindingContext);' и позволить связующему объекту по умолчанию создавать экземпляр и связывать все, что угодно, вместо того, MyObject' вручную. –

+0

Я обновил свой пост, чтобы отразить это. –

0

Вы определенно идете по правильному пути. Когда я это сделал, я сделал промежуточную модель представления, которая взяла Праву как строку из-за запятых. Затем я преобразовал из модели представления (или модели представления) в модель контроллера. Модель контроллера имела очень простой конструктор, который принял модель представления и мог Convert.ToDecimal("12,345,678.90") значение цены.