MVC/JQuery 验证不接受逗号作为小数分隔符

Posted

技术标签:

【中文标题】MVC/JQuery 验证不接受逗号作为小数分隔符【英文标题】:MVC/JQuery validation does not accept comma as decimal separator 【发布时间】:2018-01-02 18:49:20 【问题描述】:

更新 07.01.2018

尽管有人建议这是一个 jQuery 问题而不是 MS ASP MVC 问题,但我认为这是一个 MVC 问题。我已经在 asp.net core 2.0 MVC 中创建了整个应用程序并且错误仍然存​​在。对我来说,将它与 MVC 联系起来的事实是,我可以通过在模型中添加行 [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "0:yyyy-MM-dd")] 来解决日期验证问题。因此,MVC 对验证有影响。所以我认为 MVC 中有一些方法可以解决这个问题(参见post)。请发布 asp.net core 2.0 的答案。

原帖

在 MVC5 页面中,我在文本框中呈现 Double 属性。加载页面时,该值显示为“,”作为小数分隔符,这是正确的,因为该页面在德语系统上运行。如果我想保存表单,我会收到验证错误。如何解决?我知道关于这个话题有一些问题,但据我所知,它们中的大多数都已经过时了......我仍然在苦苦挣扎,没有任何设置或内置任何东西可以让来自不同国家的用户使用 MVC 应用程序。

型号:

[DisplayFormat(DataFormatString = "0:n2", ApplyFormatInEditMode = true)]
public Double Gewicht

    get  return gewicht; 
    set  gewicht = value; OnPropertyChanged(new PropertyChangedEventArgs("Gewicht")); 

CShtml

<div class="form-group">
    @Html.LabelFor(model => model.Gewicht, htmlAttributes: new  @class = "control-label col-md-3" )
    <div class="col-md-8">
        @Html.EditorFor(model => model.Gewicht, new  htmlAttributes = new  @class = "form-control col-md-1"  )
        @Html.ValidationMessageFor(model => model.Gewicht, "", new  @class = "text-danger" )
    </div>
</div>

Web.config

<globalization uiCulture="de-DE" culture="de-DE" />

加载后的框 --> 以逗号作为小数分隔符加载的值

单击提交按钮后的框 --> 相同值的验证错误

逗号后的方框改为点-->没有验证错误

更新 05.01.2018

我已经尝试了here 所示的解决方案,但不幸的是它对我不起作用。但是,我还发现,这些值不仅不被接受,而且还更改为混合了组分隔符和小数分隔符的数字(见图)。发生的情况是,22 的值更改为 22.5 并存储在数据库中。结果是,值 2,250.00 存储到数据库中。

更新 07.01.2018

同样有趣的是,日期字段完全可以接受德语格式。

房产

private DateTime? inbetriebnahmedatum;

[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "0:yyyy-MM-dd")]
public DateTime? Inbetriebnahmedatum

    get  return inbetriebnahmedatum; 
    set  inbetriebnahmedatum = value; OnPropertyChanged(new PropertyChangedEventArgs("Inbetriebnahmedatum")); 

下面显示的值被接受和处理,没有任何错误。

更新 07.01.2018 - 2

如果我从

更改 edit.cshtml 中的行
<input asp-for="Gewicht" class="form-control" />

<input name="Gewicht" id="Gewicht" type="number" class="form-control" value="@Model.Gewicht"/>

可以使用值“23,7”提交表单而不会出现验证错误。在控制器中,绑定模型属性显示的值为“237”,而IFormCollection 显示的值为“23.7”。这表明模型绑定器存在问题。

【问题讨论】:

我不认为这是相似的,因为我使用 [DisplayFormat(DataFormatString = "0:n2", ApplyFormatInEditMode = true)] 并且我对格式很好。我也希望有一种更“内置”的方法来解决这个问题,因为我无法想象 MVC 5 不允许以美国-美国以外的其他格式保存十进制值。 @Mister832 与 MVC5 无关。您看到的错误是由 jquery validate javascript 库产生的。您可以定义一个自定义验证器来处理逗号 谢谢,我更新了标题。我只是觉得它与基类中的数据注释有关。 如果您没有正确设置您的文化,也许可以使用您自己的模型粘合剂? ***.com/questions/793459/… 您可能对this plugin 感兴趣,它根据服务器文化显示和验证数字类型的输入 【参考方案1】:

尽管有人建议这是一个 jQuery 问题而不是 MVC 问题,但我认为这是一个 MVC 问题。

不,这是不正确的。您会看到客户端验证错误,因为默认情况下,jquery.validate.js(与 MicroSoft 无关的独立 3rd 方插件,MVC 用于客户端验证)根据小数分隔符 .(点)验证数字,不是,(逗号)。

MVC 是服务器端代码,不在浏览器中运行。为了执行客户端验证,生成表单控件的 MVC 的 HtmlHelper 方法在 html 中呈现一组 data-val-* 属性,用于描述要执行的验证,当 DOM 是加载,并使用这些规则将规则添加到$.validator

对于您的double 属性,它将添加一个data-val-number 属性(除了data-val-required 属性),这将添加定义为的number 规则

// http://docs.jquery.com/Plugins/Validation/Methods/number
number: function( value, element ) 
    return this.optional(element) || /^-?(?:\d+|\d1,3(?:,\d3)+)?(?:\.\d+)?$/.test(value);
,

其中小数分隔符是点,千位分隔符是逗号(估计是因为插件是在美国开发的,所以使用美国格式)。

您需要覆盖默认行为,您可以通过使用 jquery.globalize 等插件或包含以下脚本来执行此操作(注意正则表达式只是交换点和逗号)

$.validator.methods.number = function (value, element) 
    return this.optional(element) || /^-?(?:\d+|\d1,3(?:\.\d3)+)?(?:,\d+)?$/.test(value);

注意,上面的脚本需要在jquery.validate.js 脚本之后,但不能包含在$(document).ready()

对我来说,它与 MVC 的联系在于,我可以通过将行 [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "0:yyyy-MM-dd")] 添加到模型来解决日期验证问题。

实际上是您的[DataType(DataType.Date)] 属性与[DisplayFormat] 属性一起影响生成的html。 [DataType] 属性生成&lt;input type="date" ... /&gt;,如果浏览器支持,它会依次呈现浏览器 HTML-5 日期选择器。根据规范,格式必须为yyyy-MM-dd(ISO 格式),因此也需要[DisplayFormat] 属性。

HTML-5 日期选择器在浏览器文化中呈现日期。您在输入为26.1.2018 的位置显示的图像是因为您的浏览器文化是de-DE,但如果我导航到您的网站,我会在输入中看到26/1/2018,因为我的文化是en-AU(澳大利亚),如果美国用户导航到您的网站,他们会看到1/26/2018

客户端验证适用于 date 属性的原因是 jquery.validate.js 插件包含美国格式 (MM/dd/yyyy) 和 ISO 格式 (yyyy-MM-dd) 的日期规则。

如果您要使用@Html.TextBoxFor(m =&gt; m.Inbetriebnahmedatum)(忽略您的[DataType][DisplayFormat] 属性),并在输入中输入26.1.2018,您还会看到客户端验证错误。

【讨论】:

【参考方案2】:

我认为问题在于 jquery 验证器 我用它来解决逗号/点错误

$.validator.methods.number = function (value, element) 
    return this.optional(element) || /^-?(?:\d+|\d1,3(?:[\s\.,]\d3)+)(?:[\.,]\d+)?$/.test(value);

试试看吧

【讨论】:

谢谢,但如前所述,其目的是使用具有开箱即用功能的整个东西。尽管这个“oneliner”看起来很酷,但当我仍然不得不摆弄这样的事情时,MVC 应用程序的意义何在?特别是,当您观看 MVA 视频时,他们会称赞“仅模型”方法使 Web 界面设计变得如此简单......【参考方案3】:

更强大的解决方案可能是将验证器方法包装在您自己的函数中,该函数将逗号分隔的数字转换为小数分隔的数字。

一个技巧是使用 .call 调用原始验证器函数,就好像“this”是开发人员认为的原始 this(例如,他们使用函数“this.optional”进行步骤验证)。

var originalNumber = $.validator.methods.number;
var wrappedNumber = function (value, element) 
    var fixedValue = parseFloat(value.toString().replace(",", "."));
    return originalNumber.call($.validator.prototype, fixedValue, element);     // Call function as if "this" is the original caller
;
$.validator.methods.number = wrappedNumber;

您可以为任何验证器使用此功能,例如步骤验证:

var originalStep = $.validator.methods.step;
var wrappedStep = function (value, element, param) 
    var fixedValue = parseFloat(value.toString().replace(",", "."));
    return originalStep.call($.validator.prototype, fixedValue, element, param);
;
$.validator.methods.step = wrappedStep;

【讨论】:

喜欢这个解决方案,但重要的是要指出parseFloat 不足以进行数字转换,例如parseFloat("50-ba") 返回5 感谢您的评论。与编程中的几乎任何事情一样,答案是“视情况而定”。我们采用了一种不同的方法,为 模拟 但对于丹麦语言环境,通过将输入限制为 0-9 和一个带有 js 的 "," 字符.

以上是关于MVC/JQuery 验证不接受逗号作为小数分隔符的主要内容,如果未能解决你的问题,请参考以下文章

用逗号作为小数分隔符的数字的 Google 表单正则表达式

在数据库查询中使用逗号作为小数分隔符

Dygraphs,逗号作为小数分隔符

以逗号作为小数分隔符的数据框

如何禁止逗号作为小数分隔符

逗号作为小数分隔符空格作为千​​位分隔符C# [重复]