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

时间:2018-01-02 18:49:20

标签: c# jquery asp.net-mvc asp.net-core

更新07.01.2018

即使有人提出,这是一个jQuery问题而不是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" />

加载后的方框 - &gt;用逗号作为小数分隔符加载的值 enter image description here

点击提交按钮后的框 - &gt;相同值的验证错误

enter image description here

逗号后的框改为点 - &gt;没有验证错误 enter image description here

更新05.01.2018

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

enter image description here

更新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")); }
}

接受并处理下面显示的值没有任何错误。 enter image description here

更新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”。这表明模型绑定器存在问题。

3 个答案:

答案 0 :(得分:21)

  

即使有人提出,这是一个jQuery问题而不是MVC问题,我认为这是一个MVC问题。

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

MVC是服务器端代码,不在浏览器中运行。为了执行客户端验证,生成表单控件的MVC HtmlHelper方法在html中呈现一组data-val-*属性,用于描述要执行的验证,这些属性又由加载DOM时使用jquery.validate.unobtrusive.js插件,并使用这些插件向$.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+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value);
},

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

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

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

请注意,上述脚本需要位于jquery.validate.js脚本之后但未包含在$(document).ready()

  

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

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

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

客户端验证对date属性起作用的原因是1/26/2018插件包含US格式(jquery.validate.js)和ISO格式(MM/dd/yyyy)的日期规则。

如果您使用yyyy-MM-dd(忽略了@Html.TextBoxFor(m => m.Inbetriebnahmedatum)[DataType]属性),并在输入中输入[DisplayFormat],您还会看到客户端验证错误。

答案 1 :(得分:2)

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

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

尝试玩它

答案 2 :(得分:1)

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

一种技巧是使用.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;