处理不同文化验证的最佳方法是什么
What is the best way to handle validation with different culture
我正在尝试构建多语言 MVC 应用程序。我的应用程序中有一个表格,我有一个字段可以输入费用。我能够使用西班牙文化创建记录。
但是在尝试更新记录时我得到 jquery 验证错误。我收到一条默认错误消息:
The field must be numeric.
在我的视图模型中,我设置了以下属性。
[LocalizedDisplayName("Label_Cost")]
[RegularExpression("^[^<>,<|>]+$", ErrorMessage = null, ErrorMessageResourceName = "Error_Message_Html_Tags_Prevented", ErrorMessageResourceType = typeof(Resources))]
[Range(0, 9999.99, ErrorMessage = null, ErrorMessageResourceName = "Error_Message_Cost_Not_Valid", ErrorMessageResourceType = typeof(Resources))]
public decimal? Cost { get; set; }
我在 Gobal.asax 文件中设置了以下内容
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
try
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
CultureInfo ci = new CultureInfo(culutureCode);
System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
System.Threading.Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(ci.Name);
}
catch(Exception ex)
{
// Code
}
}
并且上述方法在服务器端按预期工作以改变区域性。但是客户端验证在非英语文化中中断,因为 javascript 只识别十进制文字。我想知道使用特定于文化的验证来扩展 mvc 客户端验证的最佳方法。
编辑
参考 Mike 的 url,我对 Js 包进行了以下更改。 js包如下
public static void RegisterBundles(BundleCollection bundles)
{
BundleTable.EnableOptimizations = true;
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
"~/Scripts/globalize.js",
"~/Scripts/globalize/currency.js",
"~/Scripts/globalize/date.js",
"~/Scripts/globalize/message.js",
"~/Scripts/globalize/number.js",
"~/Scripts/globalize/plural.js",
"~/Scripts/globalize/relative-time.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisationEN").Include(
"~/Scripts/GlobalisationCulture/globalize.culture.en-AU.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisationES").Include(
"~/Scripts/GlobalisationCulture/globalize.culture.es-AR.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryuiEN").Include(
"~/Scripts/jquery-ui-1.10.3.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryuiES").Include(
"~/Scripts/jquery-ui-1.10.3.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate.js",
"~/Scripts/jquery.validate.unobtrusive.js",
"~/Scripts/jquery.unobtrusive-ajax.js",
"~/Scripts/jquery.validate.globalize.js"));
}
在布局页面我实现了如下
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
if (culutureCode.Equals("en-AU", StringComparison.OrdinalIgnoreCase))
{
culutureCode = "EN";
}
else if (culutureCode.Equals("es-AR", StringComparison.OrdinalIgnoreCase))
{
culutureCode = "ES";
}
else
{
culutureCode = "EN";
}
@Scripts.Render("~/bundles/jquery",
"~/bundles/globalisation",
string.Format("~/bundles/globalisation{0}", culutureCode),
"~/bundles/jqueryval",
string.Format("~/bundles/jqueryui{0}", culutureCode))
您已在 RegisterBundles 中添加了捆绑包,但未在布局页面中使用它们。您还在 RegisterBundles 中添加了冗余的 jqueryui 文件。 像这样更新 你的 RegisterBundles 方法:
public static void RegisterBundles(BundleCollection bundles)
{
BundleTable.EnableOptimizations = true;
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
"~/Scripts/globalize.js",
"~/Scripts/globalize/currency.js",
"~/Scripts/globalize/date.js",
"~/Scripts/globalize/message.js",
"~/Scripts/globalize/number.js",
"~/Scripts/globalize/plural.js",
"~/Scripts/globalize/relative-time.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisationEN").Include(
"~/Scripts/GlobalisationCulture/globalize.culture.en-AU.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisationES").Include(
"~/Scripts/GlobalisationCulture/globalize.culture.es-AR.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
"~/Scripts/jquery-ui-1.10.3.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate.js",
"~/Scripts/jquery.validate.unobtrusive.js",
"~/Scripts/jquery.unobtrusive-ajax.js",
"~/Scripts/jquery.validate.globalize.js"));
}
然后更新布局页面,如下所示:
@section Scripts
{
@Scripts.Render("~/bundles/jquery",
"~/bundles/globalisation",
"~/bundles/globalisationEN",
"~/bundles/globalisationES",
"~/bundles/jqueryval",
"~/bundles/jqueryui"))
<script type="text/javascript">
$.validator.methods.number = function (value, element) {
return this.optional(element) ||
!isNaN(Globalize.parseFloat(value));
}
$(document).ready(function () {
Globalize.culture('es-AR'); //set spanish culture
});
</script>
}
希望这会有所帮助:)
有 2 个 jQuery 全球化插件。
旧版本 v0.0.1 包含一个脚本 globalize.js
并且它有一个子文件夹 cultures
,您可以在其中找到所有脚本文化,例如:
- globalize.culture.en-AU.js
- globalize.culture.es-AR.js
这些脚本允许您添加任意数量的文化,因此以这种方式构建您的包将是完美的:
bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
"~/Scripts/globalize.js",
"~/Scripts/cultures/globalize.culture.en-AU.js",
"~/Scripts/cultures/globalize.culture.es-AR.js"
));
Globalize
将有一组本地化脚本,您可以简单地使用这些脚本进行设置:
Globalize.culture('en-AU');
或
Globalize.culture('es-AR');
它可以使用某种接近度来确定您要使用的最接近的文化。
如果你已经加载了你的包 globalize.culture.es-AR.js
你可以设置 Globalize.culture('es');
并且 Globalize
将能够确定你想要使用 'es-AR' 文化;当然,如果您添加了 globalize.culture.es.js
,加载程序将选择最后一个。
jQuery Globalize(稳定版)的新版本是 v1.0.0,它的工作方式完全不同。
它仍然有名为 globalize.js
的主脚本文件,但您必须添加更多脚本才能使其正常工作。
有人构建了一个 tool,它会根据您要使用的模块类型(数字、日期、货币)准确地告诉您需要什么脚本。
如果您选择使用 v1.0.0,您会看到该工具会建议包含基本脚本(仅限数字):
- cldr.js
- cldr/event.js
- cldr/supplemental.js
- globalize.js
- globalize/number.js
加上一些 CLDR JSON 脚本:
- cldr/supplemental/likelySubtags.json
- cldr/main/{locale}/numbers.json
- cldr/supplemental/numberingSystems.json
您可以在 core package and the numbers 包中找到这些文件。
如果你想验证日期,这是 package。
更多信息 here.
这些都是 json 文件,您不能将它们捆绑在一起。您可以在 运行 时间内加载它们,执行如下操作:
Application.loadCulture = function (culture) {
$.when(
$.get(Application.CldrFetch + '/' + culture + '/' + encodeURIComponent("likelySubtags.json")),
$.get(Application.CldrFetch + '/' + culture + '/' + "numberingSystems.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "plurals.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "ordinals.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "currencyData.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "timeData.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "weekData.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "ca-gregorian.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "timeZoneNames.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "numbers.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "currencies.json")
)
.then(function () {
// Normalize $.get results, we only need the JSON, not the request statuses.
return [].slice.apply(arguments, [0]).map(function (result) {
return result[0];
});
}).then(Globalize.load).then(function () {
Globalize.locale(culture);
});
};
无论如何;假设您想坚持使用旧的 v0.0.1,它仍然是最好的。
您的捆绑包将包含全球化脚本和文化脚本:
bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
"~/Scripts/globalize.js",
"~/Scripts/cultures/globalize.culture.en-AU.js",
"~/Scripts/cultures/globalize.culture.es-AR.js"
));
jQuery validation 提供了一些您可能想要考虑的其他附加扩展:
- 附加-methods.js
- localization/messages_es_AR.js(文化的错误信息)
我看到您正在 Application_AcquireRequestState
中设置您的文化。有人建议最好在 Application_BeginRequest
中执行此操作,因为它在管道中的处理较早:
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
string cultureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
CultureInfo ci = new CultureInfo(cultureCode);
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureCode);
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
}
您似乎正在使用此 jQuery plugin 进行验证。我通常会做的是,一旦我加载脚本,配置区域性并设置自定义验证:
Globalize.culture(this.culture);
$.validator.methods.number = function (value, element) {
return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value));
};
$.validator.methods.date = function (value, element) {
return (this.optional(element) || Globalize.parseDate(value));
};
jQuery.extend(jQuery.validator.methods, {
range: function (value, element, param) {
var val = Globalize.parseFloat(value);
return this.optional(element) || (val >= param[0] && val <= param[1]);
}
});
您缺少的一件事是小数模型活页夹:
using System;
using System.Web.Mvc;
using System.Globalization;
public class DecimalModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
ModelState modelState = new ModelState { Value = valueResult };
object actualValue = null;
try
{
//Check if this is a nullable decimal and a null or empty string has been passed
var isNullableAndNull = (bindingContext.ModelMetadata.IsNullableValueType && string.IsNullOrEmpty(valueResult.AttemptedValue));
//If not nullable and null then we should try and parse the decimal
if (!isNullableAndNull)
{
actualValue = decimal.Parse(valueResult.AttemptedValue, NumberStyles.Any, CultureInfo.CurrentCulture);
}
}
catch (FormatException e)
{
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
可以在你的Global.asaxApplication_Start
中设置:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
这几乎就是您需要的一切。
这种方法只有一个恼人的问题。
假设您正在使用文化 en-AU
并在数字字段中输入一个值:10,4。
此数字在 es-AR
中完全有效,但在 en-AU
文化中应该无效。
jQuery Globalize 无论如何都会认为它有效,因为它会在此处将其转换为 104:
$.validator.methods.number = function (value, element) {
return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value));
};
Globalize.parseFloat('10,4')
对于文化 en-AU 会将数字转换为 104。
如果你对 Globalize.parseFloat('10.4')
文化 es-AR 做同样的事情,也会发生同样的事情;它会再次变成 104。
您可以检查此行为 运行宁此 fiddle。
,
和 .
都是有效符号,因为它们将用作小数分隔符和千位分隔符。
github 关于这个主题有几个未解决的问题,我想这很难解决,因为他们现在正在开发新版本,顺便说一句,同样的问题仍然存在。
您将在服务器端与我们的 decimal model binder:
面临同样的问题
decimal.Parse('10,4', NumberStyles.Any, CultureInfo.CurrentCulture);
其中 CultureInfo.CurrentCulture 是 'en-AU' 会再次产生相同的结果:104.
它可以在那里打个断点,看看它是如何转换值的。
我想这可能更容易修复,也许使用一些正则表达式。
如果您想使用 jQuery Validator v.0.1.1 或 jQuery Validator v.1.0.0 解决方案,我已经创建了两个存储库 here and here。
我正在尝试构建多语言 MVC 应用程序。我的应用程序中有一个表格,我有一个字段可以输入费用。我能够使用西班牙文化创建记录。
但是在尝试更新记录时我得到 jquery 验证错误。我收到一条默认错误消息:
The field must be numeric.
在我的视图模型中,我设置了以下属性。
[LocalizedDisplayName("Label_Cost")]
[RegularExpression("^[^<>,<|>]+$", ErrorMessage = null, ErrorMessageResourceName = "Error_Message_Html_Tags_Prevented", ErrorMessageResourceType = typeof(Resources))]
[Range(0, 9999.99, ErrorMessage = null, ErrorMessageResourceName = "Error_Message_Cost_Not_Valid", ErrorMessageResourceType = typeof(Resources))]
public decimal? Cost { get; set; }
我在 Gobal.asax 文件中设置了以下内容
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
try
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
CultureInfo ci = new CultureInfo(culutureCode);
System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
System.Threading.Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(ci.Name);
}
catch(Exception ex)
{
// Code
}
}
并且上述方法在服务器端按预期工作以改变区域性。但是客户端验证在非英语文化中中断,因为 javascript 只识别十进制文字。我想知道使用特定于文化的验证来扩展 mvc 客户端验证的最佳方法。
编辑
参考 Mike 的 url,我对 Js 包进行了以下更改。 js包如下
public static void RegisterBundles(BundleCollection bundles)
{
BundleTable.EnableOptimizations = true;
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
"~/Scripts/globalize.js",
"~/Scripts/globalize/currency.js",
"~/Scripts/globalize/date.js",
"~/Scripts/globalize/message.js",
"~/Scripts/globalize/number.js",
"~/Scripts/globalize/plural.js",
"~/Scripts/globalize/relative-time.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisationEN").Include(
"~/Scripts/GlobalisationCulture/globalize.culture.en-AU.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisationES").Include(
"~/Scripts/GlobalisationCulture/globalize.culture.es-AR.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryuiEN").Include(
"~/Scripts/jquery-ui-1.10.3.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryuiES").Include(
"~/Scripts/jquery-ui-1.10.3.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate.js",
"~/Scripts/jquery.validate.unobtrusive.js",
"~/Scripts/jquery.unobtrusive-ajax.js",
"~/Scripts/jquery.validate.globalize.js"));
}
在布局页面我实现了如下
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
if (culutureCode.Equals("en-AU", StringComparison.OrdinalIgnoreCase))
{
culutureCode = "EN";
}
else if (culutureCode.Equals("es-AR", StringComparison.OrdinalIgnoreCase))
{
culutureCode = "ES";
}
else
{
culutureCode = "EN";
}
@Scripts.Render("~/bundles/jquery",
"~/bundles/globalisation",
string.Format("~/bundles/globalisation{0}", culutureCode),
"~/bundles/jqueryval",
string.Format("~/bundles/jqueryui{0}", culutureCode))
您已在 RegisterBundles 中添加了捆绑包,但未在布局页面中使用它们。您还在 RegisterBundles 中添加了冗余的 jqueryui 文件。 像这样更新 你的 RegisterBundles 方法:
public static void RegisterBundles(BundleCollection bundles)
{
BundleTable.EnableOptimizations = true;
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
"~/Scripts/globalize.js",
"~/Scripts/globalize/currency.js",
"~/Scripts/globalize/date.js",
"~/Scripts/globalize/message.js",
"~/Scripts/globalize/number.js",
"~/Scripts/globalize/plural.js",
"~/Scripts/globalize/relative-time.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisationEN").Include(
"~/Scripts/GlobalisationCulture/globalize.culture.en-AU.js"));
bundles.Add(new ScriptBundle("~/bundles/globalisationES").Include(
"~/Scripts/GlobalisationCulture/globalize.culture.es-AR.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
"~/Scripts/jquery-ui-1.10.3.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate.js",
"~/Scripts/jquery.validate.unobtrusive.js",
"~/Scripts/jquery.unobtrusive-ajax.js",
"~/Scripts/jquery.validate.globalize.js"));
}
然后更新布局页面,如下所示:
@section Scripts
{
@Scripts.Render("~/bundles/jquery",
"~/bundles/globalisation",
"~/bundles/globalisationEN",
"~/bundles/globalisationES",
"~/bundles/jqueryval",
"~/bundles/jqueryui"))
<script type="text/javascript">
$.validator.methods.number = function (value, element) {
return this.optional(element) ||
!isNaN(Globalize.parseFloat(value));
}
$(document).ready(function () {
Globalize.culture('es-AR'); //set spanish culture
});
</script>
}
希望这会有所帮助:)
有 2 个 jQuery 全球化插件。
旧版本 v0.0.1 包含一个脚本 globalize.js
并且它有一个子文件夹 cultures
,您可以在其中找到所有脚本文化,例如:
- globalize.culture.en-AU.js
- globalize.culture.es-AR.js
这些脚本允许您添加任意数量的文化,因此以这种方式构建您的包将是完美的:
bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
"~/Scripts/globalize.js",
"~/Scripts/cultures/globalize.culture.en-AU.js",
"~/Scripts/cultures/globalize.culture.es-AR.js"
));
Globalize
将有一组本地化脚本,您可以简单地使用这些脚本进行设置:
Globalize.culture('en-AU');
或
Globalize.culture('es-AR');
它可以使用某种接近度来确定您要使用的最接近的文化。
如果你已经加载了你的包 globalize.culture.es-AR.js
你可以设置 Globalize.culture('es');
并且 Globalize
将能够确定你想要使用 'es-AR' 文化;当然,如果您添加了 globalize.culture.es.js
,加载程序将选择最后一个。
jQuery Globalize(稳定版)的新版本是 v1.0.0,它的工作方式完全不同。
它仍然有名为 globalize.js
的主脚本文件,但您必须添加更多脚本才能使其正常工作。
有人构建了一个 tool,它会根据您要使用的模块类型(数字、日期、货币)准确地告诉您需要什么脚本。
如果您选择使用 v1.0.0,您会看到该工具会建议包含基本脚本(仅限数字):
- cldr.js
- cldr/event.js
- cldr/supplemental.js
- globalize.js
- globalize/number.js
加上一些 CLDR JSON 脚本:
- cldr/supplemental/likelySubtags.json
- cldr/main/{locale}/numbers.json
- cldr/supplemental/numberingSystems.json
您可以在 core package and the numbers 包中找到这些文件。
如果你想验证日期,这是 package。
更多信息 here.
这些都是 json 文件,您不能将它们捆绑在一起。您可以在 运行 时间内加载它们,执行如下操作:
Application.loadCulture = function (culture) {
$.when(
$.get(Application.CldrFetch + '/' + culture + '/' + encodeURIComponent("likelySubtags.json")),
$.get(Application.CldrFetch + '/' + culture + '/' + "numberingSystems.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "plurals.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "ordinals.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "currencyData.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "timeData.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "weekData.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "ca-gregorian.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "timeZoneNames.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "numbers.json"),
$.get(Application.CldrFetch + '/' + culture + '/' + "currencies.json")
)
.then(function () {
// Normalize $.get results, we only need the JSON, not the request statuses.
return [].slice.apply(arguments, [0]).map(function (result) {
return result[0];
});
}).then(Globalize.load).then(function () {
Globalize.locale(culture);
});
};
无论如何;假设您想坚持使用旧的 v0.0.1,它仍然是最好的。
您的捆绑包将包含全球化脚本和文化脚本:
bundles.Add(new ScriptBundle("~/bundles/globalisation").Include(
"~/Scripts/globalize.js",
"~/Scripts/cultures/globalize.culture.en-AU.js",
"~/Scripts/cultures/globalize.culture.es-AR.js"
));
jQuery validation 提供了一些您可能想要考虑的其他附加扩展:
- 附加-methods.js
- localization/messages_es_AR.js(文化的错误信息)
我看到您正在 Application_AcquireRequestState
中设置您的文化。有人建议最好在 Application_BeginRequest
中执行此操作,因为它在管道中的处理较早:
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture");
string cultureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en";
CultureInfo ci = new CultureInfo(cultureCode);
System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureCode);
System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
}
您似乎正在使用此 jQuery plugin 进行验证。我通常会做的是,一旦我加载脚本,配置区域性并设置自定义验证:
Globalize.culture(this.culture);
$.validator.methods.number = function (value, element) {
return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value));
};
$.validator.methods.date = function (value, element) {
return (this.optional(element) || Globalize.parseDate(value));
};
jQuery.extend(jQuery.validator.methods, {
range: function (value, element, param) {
var val = Globalize.parseFloat(value);
return this.optional(element) || (val >= param[0] && val <= param[1]);
}
});
您缺少的一件事是小数模型活页夹:
using System;
using System.Web.Mvc;
using System.Globalization;
public class DecimalModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ValueProviderResult valueResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
ModelState modelState = new ModelState { Value = valueResult };
object actualValue = null;
try
{
//Check if this is a nullable decimal and a null or empty string has been passed
var isNullableAndNull = (bindingContext.ModelMetadata.IsNullableValueType && string.IsNullOrEmpty(valueResult.AttemptedValue));
//If not nullable and null then we should try and parse the decimal
if (!isNullableAndNull)
{
actualValue = decimal.Parse(valueResult.AttemptedValue, NumberStyles.Any, CultureInfo.CurrentCulture);
}
}
catch (FormatException e)
{
modelState.Errors.Add(e);
}
bindingContext.ModelState.Add(bindingContext.ModelName, modelState);
return actualValue;
}
}
可以在你的Global.asaxApplication_Start
中设置:
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder());
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());
这几乎就是您需要的一切。
这种方法只有一个恼人的问题。
假设您正在使用文化 en-AU
并在数字字段中输入一个值:10,4。
此数字在 es-AR
中完全有效,但在 en-AU
文化中应该无效。
jQuery Globalize 无论如何都会认为它有效,因为它会在此处将其转换为 104:
$.validator.methods.number = function (value, element) {
return this.optional(element) || jQuery.isNumeric(Globalize.parseFloat(value));
};
Globalize.parseFloat('10,4')
对于文化 en-AU 会将数字转换为 104。
如果你对 Globalize.parseFloat('10.4')
文化 es-AR 做同样的事情,也会发生同样的事情;它会再次变成 104。
您可以检查此行为 运行宁此 fiddle。
,
和 .
都是有效符号,因为它们将用作小数分隔符和千位分隔符。
github 关于这个主题有几个未解决的问题,我想这很难解决,因为他们现在正在开发新版本,顺便说一句,同样的问题仍然存在。
您将在服务器端与我们的 decimal model binder:
面临同样的问题decimal.Parse('10,4', NumberStyles.Any, CultureInfo.CurrentCulture);
其中 CultureInfo.CurrentCulture 是 'en-AU' 会再次产生相同的结果:104.
它可以在那里打个断点,看看它是如何转换值的。
我想这可能更容易修复,也许使用一些正则表达式。
如果您想使用 jQuery Validator v.0.1.1 或 jQuery Validator v.1.0.0 解决方案,我已经创建了两个存储库 here and here。