Model Binding to Custom Types with different localization
I have a custom binding of objects array into IEnumerable bookings in a controller action
HTML:
<input class='textBox' name='bookings[0].Date' type='text' value='0开发者_开发问答1/01/2001' />
<select name='bookings[0].StartTime' class='startTime'>
<option value="7">7:00</option>
<option value="7.5">7:30</option>
<option value="8">8:00</option>
<option value="8.5">8:30</option>
</select>
<select name='bookings[0].EndTime' class='endTime'>
<option value="7">7:00</option>
<option value="7.5">7:30</option>
<option value="8">8:00</option>
<option value="8.5">8:30</option>
</select>
....
<input class='textBox' name='bookings[5].Date' type='text' value='01/01/2001' />
<select name='bookings[5].StartTime' class='startTime'>
<select name='bookings[5].EndTime' class='endTime'>
Controller action:
public ActionResult CreateEvent(IEnumerable<BookingDetails> bookings)
{
....
}
And container class for binding
public class BookingDetails
{
public string Date { get; set; }
public float StartTime { get; set; }
public float EndTime { get; set; }
}
"bookings" collection of controller action parameter contains data absolutely properly if culture of the page is en-US but if it is "fr-FR" floating values for time come as 0. ex:
-- Date: 1/1/2001 - StartTime: 0 - EndTime: 10 -- Date: 1/1/2001 - StartTime: 11 - EndTime: 0
where 0 appears decimal value was selected: 8.5 or 12.5 for example. I can't have values with comma and period for different cultures because of sophisticated javascript calculation on the page which supports only period for floating numbers.
Does anybody know a workaround to send data to the controller with "invariant" culture type? Thanks
you can create a custom modelbinder for float values only like
public class DecimalModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
ValueProviderResult valueResult = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName);
ModelState modelState = new ModelState { Value = valueResult };
object actualValue = null;
try
{
actualValue = Convert.ToDecimal(valueResult.AttemptedValue,
CultureInfo.InvariantCulture);
}
catch (FormatException e)
{
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
and then you can register it in global.asax in Application_Start
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
For code sample and detail explanation have a look at phil haack's post. I have just changed the Culture to invariant culture when calling Convert.ToDecimal
精彩评论