Answered by:
Decimal Validation in ASP.NET MVC (jQuery)

Question
-
User-1326558348 posted
I am struggeling with the (german) decimal seperator ',' at Validation of my ASP.NET MVC (NOT Core) Application. I read a lot posts like
- Decimal numbers with comma fail validation in German or Turkish
- MVC/JQuery validation does not accept comma as decimal separator
and tried to solve my problem with this solutions. I spend hours trying to make globalize.js work but I struggled with many diffrent errors.
Then I tried to simply ovveride the validation method of the validator, like it is described in this post accepted answer:
The Model
public class AnnualProject { ... [Display(ResourceType = typeof(Ressources.lang.Projects), Name = "Budget")] [DisplayFormat(DataFormatString = "{0:N}", ApplyFormatInEditMode = true)] public float Budget { get; set; } ... }
The View
@model DOOR2020.Models.ViewModels.AnnualProjectViewModel <script type="text/javascript" src="~/Scripts/jquery.validate.js"></script> <script type="text/javascript"> $.validator.methods.number = function (value, element) { console.log('validate'); return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)?(?:,\d+)?$/.test(value); } </script> ... <div class="form-group"> @Html.LabelFor(model => model.Project.Budget, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Project.Budget, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Project.Budget, "", new { @class = "text-danger" }) </div> </div>
I also tried to add the references via Bundles - But that didn't work as well
By adding the
console.log('validate');
I found out, that this line isn't called.Can someone tell me what I did wrong and how to solve my Issue?
Monday, September 7, 2020 1:41 PM
Answers
-
User1686398519 posted
Hi schnickalodeon,
-
By adding the
console.log('validate');
I found out, that this line isn't called.- Two files are needed to implement MVC client side validation: jquery.validate.min.js and jquery.validate.unobtrusive.min.js. You seem to only use jquery.validate.js.
- In addition, the two files mentioned above must be quoted after the jquery file.
- According to your needs, I made an example for you to refer to.
- For the Index view in the example:
- I used the _Layout view, and the _Layout view has already referenced the jquery file. In addition, there is @RenderSection("scripts", required: false) on the _Layout view, so in my example, I put the js code and the referenced js file inside "@section scripts{}".
- If you have not referenced the _Layout view, you may need to reference the jquery file on the Index view.
- About the comma decimal separator:
- You need to set Culture in web.config and customize a FloatModelBinder.
- Reference link:comma decimal seperator in asp.net mvc 5 [duplicate]
- For the Index view in the example:
Model
public class AnnualProjectViewModel { public AnnualProject Project { get; set; } } public class AnnualProject { [DisplayFormat(DataFormatString = "{0:N}", ApplyFormatInEditMode = true)] public float Budget { get; set; } }
BudgetController
public class BudgetController : Controller { public ActionResult Index() { return View(); } [HttpPost] public ActionResult test(AnnualProjectViewModel test) { if (ModelState.IsValid) { } return View(test); } }
Index
@model DailyMVCDemo.Models.AnnualProjectViewModel @using (Html.BeginForm("test", "Budget", FormMethod.Post)) { <div class="form-group"> @Html.LabelFor(model => model.Project.Budget, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Project.Budget, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Project.Budget, "", new { @class = "text-danger" }) </div> </div> <button type="submit">submit</button> } @section scripts{ <script src="~/Scripts/jquery.validate.min.js"></script> <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script> <script type="text/javascript"> $.validator.methods.number = function (value, element) { console.log('validate'); return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)?(?:,\d+)?$/.test(value); } </script> }
test
@model DailyMVCDemo.Models.AnnualProjectViewModel @Html.TextBoxFor(model => model.Project.Budget,new { @class = "form-control" })
web.config
<system.web> <compilation debug="true" targetFramework="4.7.2" /> <httpRuntime targetFramework="4.7.2" /> <globalization uiCulture="de" culture="de-DE" /> </system.web>
FloatModelBinder
public class FloatModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); return valueProviderResult == null ? base.BindModel(controllerContext, bindingContext) :float.Parse(valueProviderResult.AttemptedValue, new CultureInfo("de-DE")); } }
Global.asax
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); ModelBinders.Binders.Add(typeof(float), new FloatModelBinder()); ModelBinders.Binders.Add(typeof(float?), new FloatModelBinder()); }
Here is the result.
Best Regards,
YihuiSun
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, September 8, 2020 4:01 AM -
All replies
-
User1686398519 posted
Hi schnickalodeon,
-
By adding the
console.log('validate');
I found out, that this line isn't called.- Two files are needed to implement MVC client side validation: jquery.validate.min.js and jquery.validate.unobtrusive.min.js. You seem to only use jquery.validate.js.
- In addition, the two files mentioned above must be quoted after the jquery file.
- According to your needs, I made an example for you to refer to.
- For the Index view in the example:
- I used the _Layout view, and the _Layout view has already referenced the jquery file. In addition, there is @RenderSection("scripts", required: false) on the _Layout view, so in my example, I put the js code and the referenced js file inside "@section scripts{}".
- If you have not referenced the _Layout view, you may need to reference the jquery file on the Index view.
- About the comma decimal separator:
- You need to set Culture in web.config and customize a FloatModelBinder.
- Reference link:comma decimal seperator in asp.net mvc 5 [duplicate]
- For the Index view in the example:
Model
public class AnnualProjectViewModel { public AnnualProject Project { get; set; } } public class AnnualProject { [DisplayFormat(DataFormatString = "{0:N}", ApplyFormatInEditMode = true)] public float Budget { get; set; } }
BudgetController
public class BudgetController : Controller { public ActionResult Index() { return View(); } [HttpPost] public ActionResult test(AnnualProjectViewModel test) { if (ModelState.IsValid) { } return View(test); } }
Index
@model DailyMVCDemo.Models.AnnualProjectViewModel @using (Html.BeginForm("test", "Budget", FormMethod.Post)) { <div class="form-group"> @Html.LabelFor(model => model.Project.Budget, htmlAttributes: new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.Project.Budget, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.Project.Budget, "", new { @class = "text-danger" }) </div> </div> <button type="submit">submit</button> } @section scripts{ <script src="~/Scripts/jquery.validate.min.js"></script> <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script> <script type="text/javascript"> $.validator.methods.number = function (value, element) { console.log('validate'); return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:\.\d{3})+)?(?:,\d+)?$/.test(value); } </script> }
test
@model DailyMVCDemo.Models.AnnualProjectViewModel @Html.TextBoxFor(model => model.Project.Budget,new { @class = "form-control" })
web.config
<system.web> <compilation debug="true" targetFramework="4.7.2" /> <httpRuntime targetFramework="4.7.2" /> <globalization uiCulture="de" culture="de-DE" /> </system.web>
FloatModelBinder
public class FloatModelBinder : DefaultModelBinder { public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) { var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); return valueProviderResult == null ? base.BindModel(controllerContext, bindingContext) :float.Parse(valueProviderResult.AttemptedValue, new CultureInfo("de-DE")); } }
Global.asax
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); ModelBinders.Binders.Add(typeof(float), new FloatModelBinder()); ModelBinders.Binders.Add(typeof(float?), new FloatModelBinder()); }
Here is the result.
Best Regards,
YihuiSun
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, September 8, 2020 4:01 AM -
-
User-1326558348 posted
Thank you very much!!!! After so many hours of research I can now continue.
Thank you :)
Tuesday, September 8, 2020 9:39 AM