ASP.NET 范围函数的 MVC 客户端验证问题
ASP.NET MVC client side validation issue for range function
我有一个 ASP.NET MVC5 应用程序,这是我的视图模型:
[RegularExpression("[0-9]+(,[0-9]+)*"]
[Range(1, double.MaxValue, ErrorMessage = "value is not correct")]
[Required]
[DisplayFormat(DataFormatString = "{0:0,0}", ApplyFormatInEditMode = true, HtmlEncode = true)]
public double? Amount { get; set; }
我的观点:
<div class="col-sm-8">
@Html.EditorFor(m => m.Amount, new { @class = "form-control font-num numbers", maxlength = "10" })
@Html.ValidationMessageFor(m => m.Amount, "", new { @class = "text-danger" })
</div>
唯一值得注意的是我在我看来每三位数字使用逗号分隔符来格式化数字。
例如:123456789 => 123,456,789
我知道我应该使用自定义模型联编程序进行服务器端验证,并覆盖 jquery.validate.js 文件中 range() 和 number() 函数的默认实现。
所以我做了如下操作:
public class DoubleModelBinder : IModelBinder
{
/// <summary>
/// Binds the value to the model.
/// </summary>
/// <param name="controllerContext">The current controller context.</param>
/// <param name="bindingContext">The binding context.</param>
/// <returns>The new model.</returns>
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var culture = GetUserCulture(controllerContext);
string value = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName)
.ConvertTo(typeof(string)) as string;
double result = 0;
double.TryParse(value, NumberStyles.Any, culture, out result);
return result;
}
/// <summary>
/// Gets the culture used for formatting, based on the user's input language.
/// </summary>
/// <param name="context">The controller context.</param>
/// <returns>An instance of <see cref="CultureInfo" />.</returns>
public CultureInfo GetUserCulture(ControllerContext context)
{
var request = context.HttpContext.Request;
if (request.UserLanguages == null || request.UserLanguages.Length == 0)
return CultureInfo.CurrentUICulture;
return new CultureInfo(request.UserLanguages[0]);
}
}
对于客户端验证:
$.validator.methods.range = function (value, element, param) {
var globalizedValue = value.replace(",", "");
return this.optional(element) || (globalizedValue >= param[0] && globalizedValue <= param[1]);}
$.validator.methods.number = function (value, element) {
return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:[\s\.,]\d{3})+)(?:[\.,]\d+)?$/.test(value);}
服务器端验证工作正常,但客户端验证工作不正常,我总是得到“值不正确”错误验证。如果我忽略 [Range(1, double.MaxValue, ErrorMessage = "value is not correct")] 属性,效果很好,但用户可以为此字段输入零。我的客户端验证有什么问题?
在花了很多时间跟踪 range() 函数之后,我终于发现我应该使用:
var globalizedValue = value.replace(new RegExp(",", "g"), "");
而不是
var globalizedValue = value.replace(",", "");
因为我有多个逗号(例如:123,456,789)并且默认的 .replace() 行为是仅替换第一个匹配项。
我的错误是我用 this blog, while my issue was different. I use comma as a separator every three digits, not as the decimal separator. So I have more than one comma and default replace() method is not suitable. In fact, RegExp(",", "g") 中的解决方案替换了所有出现的地方。
我有一个 ASP.NET MVC5 应用程序,这是我的视图模型:
[RegularExpression("[0-9]+(,[0-9]+)*"]
[Range(1, double.MaxValue, ErrorMessage = "value is not correct")]
[Required]
[DisplayFormat(DataFormatString = "{0:0,0}", ApplyFormatInEditMode = true, HtmlEncode = true)]
public double? Amount { get; set; }
我的观点:
<div class="col-sm-8">
@Html.EditorFor(m => m.Amount, new { @class = "form-control font-num numbers", maxlength = "10" })
@Html.ValidationMessageFor(m => m.Amount, "", new { @class = "text-danger" })
</div>
唯一值得注意的是我在我看来每三位数字使用逗号分隔符来格式化数字。
例如:123456789 => 123,456,789
我知道我应该使用自定义模型联编程序进行服务器端验证,并覆盖 jquery.validate.js 文件中 range() 和 number() 函数的默认实现。
所以我做了如下操作:
public class DoubleModelBinder : IModelBinder
{
/// <summary>
/// Binds the value to the model.
/// </summary>
/// <param name="controllerContext">The current controller context.</param>
/// <param name="bindingContext">The binding context.</param>
/// <returns>The new model.</returns>
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var culture = GetUserCulture(controllerContext);
string value = bindingContext.ValueProvider
.GetValue(bindingContext.ModelName)
.ConvertTo(typeof(string)) as string;
double result = 0;
double.TryParse(value, NumberStyles.Any, culture, out result);
return result;
}
/// <summary>
/// Gets the culture used for formatting, based on the user's input language.
/// </summary>
/// <param name="context">The controller context.</param>
/// <returns>An instance of <see cref="CultureInfo" />.</returns>
public CultureInfo GetUserCulture(ControllerContext context)
{
var request = context.HttpContext.Request;
if (request.UserLanguages == null || request.UserLanguages.Length == 0)
return CultureInfo.CurrentUICulture;
return new CultureInfo(request.UserLanguages[0]);
}
}
对于客户端验证:
$.validator.methods.range = function (value, element, param) {
var globalizedValue = value.replace(",", "");
return this.optional(element) || (globalizedValue >= param[0] && globalizedValue <= param[1]);}
$.validator.methods.number = function (value, element) {
return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:[\s\.,]\d{3})+)(?:[\.,]\d+)?$/.test(value);}
服务器端验证工作正常,但客户端验证工作不正常,我总是得到“值不正确”错误验证。如果我忽略 [Range(1, double.MaxValue, ErrorMessage = "value is not correct")] 属性,效果很好,但用户可以为此字段输入零。我的客户端验证有什么问题?
在花了很多时间跟踪 range() 函数之后,我终于发现我应该使用:
var globalizedValue = value.replace(new RegExp(",", "g"), "");
而不是
var globalizedValue = value.replace(",", "");
因为我有多个逗号(例如:123,456,789)并且默认的 .replace() 行为是仅替换第一个匹配项。
我的错误是我用 this blog, while my issue was different. I use comma as a separator every three digits, not as the decimal separator. So I have more than one comma and default replace() method is not suitable. In fact, RegExp(",", "g") 中的解决方案替换了所有出现的地方。