使用日期时间输入控件全球化验证问题
globalize validation problem with datetime input control
我正在尝试使用 cldr-data 和全球化功能来验证我在 ASP.NET Core MVC Web 项目中的输入。
出现问题是因为它似乎可以根据 navigator.language
属性 加载正确的 cldr 数据文件(我知道这并不总是准确的,但在这种情况下应该有效。我的OS 设置为 en-US,浏览器显示三种语言 "de",第一个显示 navigator.languages
)
虽然逗号分隔符被正确识别(它接受 ,
并拒绝 .
作为日期输入,但我不明白为什么日期被标记为无效。
日期以正确的 de
dd.mm.yyyy
格式显示
创建表单还会显示格式正确的输入字段
使用 .
作为逗号分隔符引发无效
使用日期时间选择器给我一个无效的日期
Opera/Chrome
边缘
Firefox
设置
_ValidationScriptsPartial.cshtml
<environment include="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
<!-- cldr scripts (needed for globalize) -->
<script src="~/lib/cldrjs/dist/cldr.js"></script>
<script src="~/lib/cldrjs/dist/cldr/event.js"></script>
<script src="~/lib/cldrjs/dist/cldr/supplemental.js"></script>
<!-- globalize scripts -->
<script src="~/lib/globalize/dist/globalize.js"></script>
<script src="~/lib/globalize/dist/globalize/number.js"></script>
<script src="~/lib/globalize/dist/globalize/date.js"></script>
<script src="~/lib/jquery-validation-globalize/jquery.validate.globalize.js"></script>
</environment>
<environment exclude="Development">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha256-F6h55Qw6sweK+t7SiOJX+2bpSAa3b/fnlrVCJvmEj1A=">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha256-9GycpJnliUjJDVDqP0UEu/bsm9U+3dnQUH8+3W10vkY=">
</script>
</environment>
<script type="text/javascript">
function setGlobalization() {
debugger;
var url = "@Url.Action("GetBrowserLanguage", "Movies")";
$.ajax({
cache: false,
type: 'GET',
url: url,
data: { navigatorlanguage: navigator.language }
}).done(function (result) {
debugger;
$.when(
$.get("/lib/cldr-data/supplemental/likelySubtags.json"),
$.get("/lib/cldr-data/main/" + result.language + "/numbers.json"),
$.get("/lib/cldr-data/supplemental/numberingSystems.json"),
$.get("/lib/cldr-data/main/" + result.language + "/ca-gregorian.json"),
$.get("/lib/cldr-data/main/" + result.language + "/timeZoneNames.json"),
$.get("/lib/cldr-data/supplemental/timeData.json"),
$.get("/lib/cldr-data/supplemental/weekData.json")
).then(function () {
debugger;
// 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 () {
debugger;
Globalize.locale(result.language);
});
}).fail(function (result) {
alert("Server error(setGlobalization): " + result.statusText + " Please refresh and try again");
});
}
document.addEventListener('DOMContentLoaded', function () {
setGlobalization();
}, false);
</script>
Create.cshtml
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseData" class="control-label"></label>
<input asp-for="ReleaseData" class="form-control" />
<span asp-validation-for="ReleaseData" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
MoviesController.cs
public ActionResult GetBrowserLanguage(string navigatorlanguage)
{
try
{
string localePattern = "lib\cldr-data\main\{0}";
var cultureToUse = "es-ES"; //Default regionalisation to use
string defaultLanguage = "es";
if (navigatorlanguage.StartsWith("es", StringComparison.InvariantCultureIgnoreCase))
cultureToUse = "es";
if (navigatorlanguage.StartsWith("de", StringComparison.InvariantCultureIgnoreCase))
cultureToUse = "de";
if (navigatorlanguage.StartsWith("en", StringComparison.InvariantCultureIgnoreCase))
cultureToUse = "en-US-POSIX";
if (!System.IO.Directory.Exists(System.IO.Path.Combine(_hostingEnvironment.WebRootPath, string.Format(localePattern, cultureToUse))))
cultureToUse = defaultLanguage;
return Json(new
{
error = false,
exception = false,
language = cultureToUse
});
}
catch (Exception ex)
{
return Json(new
{
error = true,
exception = true,
statusText = ex.Message
});
}
}
Movie.cs
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseData { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
完整存储库
我在尝试设置为西班牙文化时遇到了同样的问题,我找到的唯一临时解决方案是替换 jquery.validate.globalize.js
中的 validator.methods.date 函数
$.validator.methods.date = function (value, element) {
var fecha = new Date(value);
var dia = fecha.getDate() + 1;
var mes = fecha.getMonth() + 1;
var anio = fecha.getFullYear();
if (dia < 10) {
dia = '0' + dia;
};
if (mes < 10) {
mes = '0' + mes;
};
var newValue = dia + '/' + mes + '/' + anio;
var val = Globalize.parseDate(newValue, $.validator.methods.dateGlobalizeOptions.dateParseFormat);
return this.optional(element) || (val instanceof Date);
};
也许这不是最好的解决方案,但这是我实现日期验证的唯一方法。
我正在尝试使用 cldr-data 和全球化功能来验证我在 ASP.NET Core MVC Web 项目中的输入。
出现问题是因为它似乎可以根据 navigator.language
属性 加载正确的 cldr 数据文件(我知道这并不总是准确的,但在这种情况下应该有效。我的OS 设置为 en-US,浏览器显示三种语言 "de",第一个显示 navigator.languages
)
虽然逗号分隔符被正确识别(它接受 ,
并拒绝 .
作为日期输入,但我不明白为什么日期被标记为无效。
日期以正确的 de
dd.mm.yyyy
格式显示
创建表单还会显示格式正确的输入字段
使用 .
作为逗号分隔符引发无效
使用日期时间选择器给我一个无效的日期
Opera/Chrome
边缘
Firefox
设置
_ValidationScriptsPartial.cshtml
<environment include="Development">
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
<!-- cldr scripts (needed for globalize) -->
<script src="~/lib/cldrjs/dist/cldr.js"></script>
<script src="~/lib/cldrjs/dist/cldr/event.js"></script>
<script src="~/lib/cldrjs/dist/cldr/supplemental.js"></script>
<!-- globalize scripts -->
<script src="~/lib/globalize/dist/globalize.js"></script>
<script src="~/lib/globalize/dist/globalize/number.js"></script>
<script src="~/lib/globalize/dist/globalize/date.js"></script>
<script src="~/lib/jquery-validation-globalize/jquery.validate.globalize.js"></script>
</environment>
<environment exclude="Development">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.17.0/jquery.validate.min.js"
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator"
crossorigin="anonymous"
integrity="sha256-F6h55Qw6sweK+t7SiOJX+2bpSAa3b/fnlrVCJvmEj1A=">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"
crossorigin="anonymous"
integrity="sha256-9GycpJnliUjJDVDqP0UEu/bsm9U+3dnQUH8+3W10vkY=">
</script>
</environment>
<script type="text/javascript">
function setGlobalization() {
debugger;
var url = "@Url.Action("GetBrowserLanguage", "Movies")";
$.ajax({
cache: false,
type: 'GET',
url: url,
data: { navigatorlanguage: navigator.language }
}).done(function (result) {
debugger;
$.when(
$.get("/lib/cldr-data/supplemental/likelySubtags.json"),
$.get("/lib/cldr-data/main/" + result.language + "/numbers.json"),
$.get("/lib/cldr-data/supplemental/numberingSystems.json"),
$.get("/lib/cldr-data/main/" + result.language + "/ca-gregorian.json"),
$.get("/lib/cldr-data/main/" + result.language + "/timeZoneNames.json"),
$.get("/lib/cldr-data/supplemental/timeData.json"),
$.get("/lib/cldr-data/supplemental/weekData.json")
).then(function () {
debugger;
// 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 () {
debugger;
Globalize.locale(result.language);
});
}).fail(function (result) {
alert("Server error(setGlobalization): " + result.statusText + " Please refresh and try again");
});
}
document.addEventListener('DOMContentLoaded', function () {
setGlobalization();
}, false);
</script>
Create.cshtml
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ReleaseData" class="control-label"></label>
<input asp-for="ReleaseData" class="form-control" />
<span asp-validation-for="ReleaseData" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Genre" class="control-label"></label>
<input asp-for="Genre" class="form-control" />
<span asp-validation-for="Genre" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Price" class="control-label"></label>
<input asp-for="Price" class="form-control" />
<span asp-validation-for="Price" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
MoviesController.cs
public ActionResult GetBrowserLanguage(string navigatorlanguage)
{
try
{
string localePattern = "lib\cldr-data\main\{0}";
var cultureToUse = "es-ES"; //Default regionalisation to use
string defaultLanguage = "es";
if (navigatorlanguage.StartsWith("es", StringComparison.InvariantCultureIgnoreCase))
cultureToUse = "es";
if (navigatorlanguage.StartsWith("de", StringComparison.InvariantCultureIgnoreCase))
cultureToUse = "de";
if (navigatorlanguage.StartsWith("en", StringComparison.InvariantCultureIgnoreCase))
cultureToUse = "en-US-POSIX";
if (!System.IO.Directory.Exists(System.IO.Path.Combine(_hostingEnvironment.WebRootPath, string.Format(localePattern, cultureToUse))))
cultureToUse = defaultLanguage;
return Json(new
{
error = false,
exception = false,
language = cultureToUse
});
}
catch (Exception ex)
{
return Json(new
{
error = true,
exception = true,
statusText = ex.Message
});
}
}
Movie.cs
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseData { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
}
完整存储库
我在尝试设置为西班牙文化时遇到了同样的问题,我找到的唯一临时解决方案是替换 jquery.validate.globalize.js
中的 validator.methods.date 函数$.validator.methods.date = function (value, element) {
var fecha = new Date(value);
var dia = fecha.getDate() + 1;
var mes = fecha.getMonth() + 1;
var anio = fecha.getFullYear();
if (dia < 10) {
dia = '0' + dia;
};
if (mes < 10) {
mes = '0' + mes;
};
var newValue = dia + '/' + mes + '/' + anio;
var val = Globalize.parseDate(newValue, $.validator.methods.dateGlobalizeOptions.dateParseFormat);
return this.optional(element) || (val instanceof Date);
};
也许这不是最好的解决方案,但这是我实现日期验证的唯一方法。