覆盖默认值"该字段必须是数字"和自定义模型绑定器未触发

时间:2017-10-21 02:10:59

标签: c# asp.net-mvc validation razor asp.net-mvc-5

我有十进制价格的字段,例如20,00并且想要编写我自己的验证消息而不是默认"字段价格必须是数字"。正如我很快就明白的那样,由于数字中的逗号,我得到验证错误,视图将其解释为字符串。所以我也应该解决这个问题。

我找到了@DarinDimitrov编写的this解决方案,我编写自定义模型绑定器

public class PriceModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var displayFormat = bindingContext.ModelMetadata.DisplayFormatString;
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);

        if (!string.IsNullOrEmpty(displayFormat) && value != null)
        {
            decimal price;
            if (decimal.TryParse(value.AttemptedValue, NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out price))
            {
                return price;
            }
            bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Неверный формат числа");
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}

我也在Global.asax

中添加它
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    ModelBinders.Binders.Add(typeof(decimal), new PriceModelBinder());
}

此外,我在<globalization culture="ru-RU" uiCulture="ru-RU" />中添加了web.config <system.web>。当我放置一个断点并尝试从视图中添加实体,但没有任何变化时,我得到相同的默认错误字符串。此外,断点并没有被抓住。

经过一番搜索,我发现模型绑定器只在POST方法调用时才有效,但我的方法已经是POST,因为我添加了实体。我尝试添加check in controller ModelState.IsValid,但它没有效果,因为表单没有发送到服务器。 在这里我的想法结束了,也许有人可以提供帮助。我写下模型,视图和控制器的部分内容。

public class ServiceDto
{
    //other properties
    [Display(Name = "Цена"), DataType(DataType.Currency, ErrorMessage = "Неверный формат числа")]
    [Required(ErrorMessage = "Цена услуги обязательна")]
    public decimal Price { get; set; }
}

@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })

public class OperatorController : Controller
{
    [HttpPost]
    public ActionResult CreateService(ServiceDto serviceDto)
    {
        //mapping here
        _unitOfWork.Services.Create(service);
        _unitOfWork.Save();
        return RedirectToAction("Index");
    }
}

更新

我添加了这个js脚本来查看所有其他脚本,但没有任何改变。

<script src="/Scripts/jquery-1.10.2.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
<script src="/Scripts/bootstrap.js"></script>
<script src="/Scripts/respond.js"></script>
<script type="text/javascript">
    $.validator.methods.number = function (value, element) {
        return this.optional(element) || /^-?(?:d+|d{1,3}(?:[s.,]d{3})+)(?:[.,]d+)?$/.test(value);
    };
</script>

也许这个脚本没有被执行?对不起,我主要使用后端,如果问题与js有关,那对我来说就是黑暗的森林。

1 个答案:

答案 0 :(得分:2)

正如Stephen Muecke所说,默认情况下jquery.validate.js使用小数点作为数字输入的分隔符(这是符合JS数字格式的标准)。要在俄罗斯文化中包含小数点逗号,您需要覆盖jquery.validator.methods.numberjquery.validator.methods.range行为,如下所示:

// taken from Lenard Gunda (see reference section)
$.validator.methods.number = function (value, element) {
    // notice additional backslashes to escape formats
    return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:[\s\.,]\d{3})+)(?:[\.,]\d+)?$/.test(value);
}

$.validator.methods.range = function (value, element, param) {
    var globalizedValue = value.replace(",", ".");
    return this.optional(element) || (globalizedValue >= param[0] && globalizedValue <= param[1]);
}

如果您使用的是Globalize插件,则可以使用该插件中的parseFloat替换正则表达式:

Globalize.culture('ru-RU');

function parseNumber(value) {
    return Globalize.parseFloat(value);
}

$.validator.methods.number = function (value, element) {
    return this.optional(element) || $.isNumeric(parseNumber(value));
}

$.validator.methods.range = function (value, element, param) {
    var globalizedValue = parseNumber(value);
    return this.optional(element) || (globalizedValue >= param[0] && globalizedValue <= param[1]);
}

参考文献:

jQuery validate and the comma decimal separator

Issue with Decimals, Commas and Client-Side Validation

jQuery Validation Plugin: validate decimal number with comma as decimal separator