I bumped into an issue while trying to get the open source ASP.NET MVC project NerdDinner running on my laptop. The Create
action in the DinnersController
just wouldn’t work. This was due to Latitude
and Longitude
values being set with a different decimal separator than my server expected. It got "0.0" instead of "0,0" which the Double.parse
function didn’t understand. A client-side JavaScript wrote these values into hidden fields, so it was a bit difficult for me to understand at first. I wrote a custom model binder to solve this for all fields of type double
at once.
As I’m still learning ASP.NET MVC, my solution may not be the optimal one.
Create a custom model binder that will only react differently to double
values.
using System; using System.Globalization; using System.Web.Mvc; namespace NerdDinner.Helpers { public class CustomModelBinder : DefaultModelBinder { public CustomModelBinder() : base() { } public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { object result = null; // Don't do this here! // It might do bindingContext.ModelState.AddModelError // and there is no RemoveModelError! // // result = base.BindModel(controllerContext, bindingContext); if (bindingContext.ModelType == typeof(double)) { string modelName = bindingContext.ModelName; string attemptedValue = bindingContext.ValueProvider[modelName].AttemptedValue; // Depending on cultureinfo the NumberDecimalSeparator can be "," or "." // Both "." and "," should be accepted, but aren't. string wantedSeperator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator; string alternateSeperator = (wantedSeperator == "," ? "." : ","); if (attemptedValue.IndexOf(wantedSeperator) == -1 && attemptedValue.IndexOf(alternateSeperator) != -1) { attemptedValue = attemptedValue.Replace(alternateSeperator, wantedSeperator); } try { result = double.Parse(attemptedValue, NumberStyles.Any); } catch (FormatException e) { bindingContext.ModelState.AddModelError(modelName, e); } } else { result = base.BindModel(controllerContext, bindingContext); } return result; } } }
Change the DefaultBinder
in Global.asax
.
void Application_Start() { //[SNIP] ModelBinders.Binders.DefaultBinder = new CustomModelBinder(); }