{"id":116,"date":"2009-07-30T12:52:55","date_gmt":"2009-07-30T10:52:55","guid":{"rendered":"http:\/\/www.crydust.be\/blog\/?p=116"},"modified":"2009-07-29T14:36:27","modified_gmt":"2009-07-29T12:36:27","slug":"custom-model-binder-to-avoid-decimal-separator-problems","status":"publish","type":"post","link":"http:\/\/www.crydust.be\/blog\/2009\/07\/30\/custom-model-binder-to-avoid-decimal-separator-problems\/","title":{"rendered":"Custom model binder to avoid decimal separator problems"},"content":{"rendered":"<p>I bumped into an issue while trying to get the open source ASP.NET MVC project <a href=\"http:\/\/nerddinner.codeplex.com\/\">NerdDinner<\/a> running on my laptop. The <code>Create<\/code> action in the <code>DinnersController<\/code> just wouldn&#8217;t work. This was due to <code>Latitude<\/code> and <code>Longitude<\/code> values being set with a different decimal separator than my server expected. It got &quot;0.0&quot; instead of &quot;0,0&quot; which the <code>Double.parse<\/code> function didn&#8217;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 <code>double<\/code> at once.<\/p>\n<p>As I&#8217;m still learning ASP.NET MVC, my solution may not be the optimal one.<\/p>\n<p><!--more--><\/p>\n<p>Create a custom model binder that will only react differently to <code>double<\/code> values.<\/p>\n<pre class=\"prettyprint\">\r\nusing System;\r\nusing System.Globalization;\r\nusing System.Web.Mvc;\r\n\r\nnamespace NerdDinner.Helpers {\r\n  public class CustomModelBinder : DefaultModelBinder {\r\n\r\n    public CustomModelBinder()\r\n      : base() {\r\n    }\r\n\r\n    public override object BindModel(ControllerContext controllerContext, \r\n      ModelBindingContext bindingContext) {\r\n      \r\n      object result = null;\r\n\r\n      \/\/ Don't do this here!\r\n      \/\/ It might do bindingContext.ModelState.AddModelError\r\n      \/\/ and there is no RemoveModelError!\r\n      \/\/ \r\n      \/\/ result = base.BindModel(controllerContext, bindingContext);\r\n\r\n      if (bindingContext.ModelType == typeof(double)) {\r\n\r\n        string modelName = bindingContext.ModelName;\r\n        string attemptedValue = bindingContext.ValueProvider[modelName].AttemptedValue;\r\n\r\n        \/\/ Depending on cultureinfo the NumberDecimalSeparator can be &quot;,&quot; or &quot;.&quot;\r\n        \/\/ Both &quot;.&quot; and &quot;,&quot; should be accepted, but aren't.\r\n        string wantedSeperator = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator;\r\n        string alternateSeperator = (wantedSeperator == &quot;,&quot; ? &quot;.&quot; : &quot;,&quot;);\r\n\r\n        if (attemptedValue.IndexOf(wantedSeperator) == -1 \r\n          &amp;&amp; attemptedValue.IndexOf(alternateSeperator) != -1) {\r\n          attemptedValue = attemptedValue.Replace(alternateSeperator, wantedSeperator);\r\n        }\r\n\r\n        try {\r\n          result = double.Parse(attemptedValue, NumberStyles.Any);\r\n        }\r\n        catch (FormatException e) {\r\n          bindingContext.ModelState.AddModelError(modelName, e);\r\n        }\r\n\r\n      }\r\n      else {\r\n        result = base.BindModel(controllerContext, bindingContext);\r\n      }\r\n\r\n      return result;\r\n    }\r\n  }\r\n}\r\n<\/pre>\n<p>Change the <code>DefaultBinder<\/code> in <code>Global.asax<\/code>.<\/p>\n<pre class=\"prettyprint\">\r\nvoid Application_Start() {\r\n  \/\/[SNIP]\r\n  ModelBinders.Binders.DefaultBinder = new CustomModelBinder();\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;t work. This was due to Latitude and Longitude values being set with &hellip; <a href=\"http:\/\/www.crydust.be\/blog\/2009\/07\/30\/custom-model-binder-to-avoid-decimal-separator-problems\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19],"tags":[],"class_list":["post-116","post","type-post","status-publish","format-standard","hentry","category-asp-net-mvc"],"_links":{"self":[{"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/posts\/116","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/comments?post=116"}],"version-history":[{"count":13,"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/posts\/116\/revisions"}],"predecessor-version":[{"id":130,"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/posts\/116\/revisions\/130"}],"wp:attachment":[{"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/media?parent=116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/categories?post=116"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.crydust.be\/blog\/wp-json\/wp\/v2\/tags?post=116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}