Reputation: 15360
I would like to do complex validation on my form that contains a list of objects.
My form contains a list of, let's say, MyObjects. MyObject consists of a double amount and a MyDate which is just a wrapper around DateTime.
public class MyObject
{
public MyDate Date { get; set; } //MyDate is wrapper around DateTime
public double Price { get; set; }
}
The form...
<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" />
Here is my Action
public ActionResult Index(IList<MyObject> myList)
{
//stuff
}
I want to allow the user to enter in 100,000,000 for a Price and for the custom model binder to strip the ',' so it can convert to a double. Likewise, I need to convert the 05/11/2009 to a MyDate object. I thought about creating a MyObjectModelBinder but dont know what to do from there.
ModelBinders.Binders[typeof(MyObject)] = new MyObjectModelBinder();
Any help appreciated.
Upvotes: 0
Views: 2421
Reputation: 1038780
Here's a sample implementation of a custom model binder:
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;
}
}
Upvotes: 2
Reputation: 19573
You're definitely going down the right path. When I did this, I made an intermediate view model that took Price as a string, because of the commas. I then converted from the view model (or presentation model) to a controller model. The controller model had a very simple constructor that accepted a view model and could Convert.ToDecimal("12,345,678.90")
the price value.
Upvotes: 0