jQuery 文化验证在 ASP.NET Core 2.0 中






3.55/5 (4投票s)
开始使用 jQuery 验证并设置 ASP.NET Core 2.0 中的特定文化验证
引言
本文介绍了使用用户或自定义文化信息包含客户端验证所需的步骤。
背景
客户端验证有助于在验证已知会失败时防止不必要的服务器往返。
默认情况下,没有客户端验证时,模型绑定器在解析用户输入方面做得很好。例如,格式为 dd-mm-yyyy、dd-mm-yy、dd/mm/yy 或 dd.mm.yy 的日期都可以成功解析。但是,小数分隔符比较棘手。
尽管如此,我们还是希望使用客户端验证。通过简单地指定输入类型(例如 number、date 等),我们可以获得一些基本的浏览器验证,但如果没有手动将属性添加到标记中,我们就无法获得进一步的验证(例如 required)。
本文介绍了使用数据模型注解并考虑用户文化使 jQuery 验证正常工作的必要步骤。
使用代码
示例应用程序是一个新创建的 ASP.NET Core Web 应用程序,采用模型-视图-控制器 (MVC) 模式和 ASP.NET Core 2.0。
默认(主页)视图的内容被一个包含三种不同类型字段(文本、日期/时间和小数)的简单表单替换。此表单将发布回控制器,控制器会使用服务器端验证结果更新 `ViewBag` 变量。
`HomeViewModel` 使用 `Required`、`MinLength` 和 `Range` 等各种验证注解。
重现步骤
为了提供客户端验证,请将以下代码添加到 **视图** 中,最好是末尾。
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
此代码将渲染位于 `Shared` 文件夹中的 `_ValidationScriptsPartial.cshtml` 文件的内容。此视图目前仅添加 **jquery.validate**,这会导致客户端行为不理想 - 输入使用 DD/MM/YYYY 等默认值进行验证,并且使用点而不是逗号作为我所在文化的小数分隔符。
其结果是,如果我使用逗号,客户端验证就会失败;如果我使用点,服务器端验证就会失败。
要解决此问题,需要为正确的文化配置 **jQuery.Validation**。这可以通过从 https://github.com/unicode-cldr 下载所需的文化并将它们放置在正确的位置来完成。我将演示另一种自动下载数据的方法,但无论哪种方法最适合您,示例应用程序都显示了所需的文件结构。
从 Unicode 通用区域信息数据存储库 (CLDR) 项目下载
项目文件夹中有一个文件,即使在切换“显示所有文件”时,在 Visual Studio 中也看不到。此文件名为 `.bowerrc`,包含一个 JSON 结构的配置,在新项目中,它仅包含一个名为 `directory` 的元素,该元素设置为 `wwwroot/lib`。我们将此文件更改为以下内容。
{ "directory": "wwwroot/lib", "scripts": { "preinstall": "npm install cldr-data-downloader@0.2.x", "postinstall": "node ./node_modules/cldr-data-downloader/bin/download.js -i wwwroot/lib/cldr-data/index.json -o wwwroot/lib/cldr-data/" } }
这基本上告诉 Bower 安装 `cldr-data-downloader` 包并下载 `index.json` 文件中指定的文件。此文件不存在,因此除非我们安装 **cldr-data**,否则每次管理 Bower 包时都会出现错误。
要管理 Bower 包,请右键单击 `bower.json` 文件。浏览查找 `cldr-data` 并安装最新版本。这将首先安装 `cldr-data-downloader`(预安装),然后安装 `cldr-data`,最后下载特定文化的文件(后安装)。
但请注意,完整的文化集在磁盘上大约为 250MB。
安装其余包
一旦我们将 CLDR 数据本地化,需要安装的其余包是 **globalize** 和 **jquery-validation-globalize**。安装这些包后,`bower.json` 文件应该看起来如下。
{ "name": "asp.net", "private": true, "dependencies": { "bootstrap": "3.3.7", "jquery": "3.2.1", "jquery-validation": "1.17.0", "jquery-validation-unobtrusive": "3.2.6", "cldr-data": "29.0.0", "globalize": "v0.1.1", "jquery-validation-globalize": "1.0.0", "cldrjs": "0.5.0" }, "resolutions": { "globalize": "^1.0.0", "jquery": "3.2.1", "cldrjs": "0.5.0", "jquery-validation": "1.17.0" } }
包含全球化所需的脚本
如前所述,通过在 `Scripts` 部分包含 `_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>
获取用户文化
可以使用多种 机制 检测文化,例如从 **查询字符串**、**Cookie** 或 **Accept-Language HTTP 头**。
为了设置此本地化中间件,我们将以下代码添加到应用程序的 **startup.cs** 文件中。
var di = new DirectoryInfo(Path.Combine(env.WebRootPath, @"lib\cldr-data\main"));
var supportedCultures = di.GetDirectories().Where(x => x.Name != "root").Select(x => new CultureInfo(x.Name)).ToList();
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(supportedCultures.FirstOrDefault(x => x.Name == "en-GB")),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
总结
目前,我们还没有指定要使用的文化,并且会收到错误 **E_DEFAULT_LOCALE_NOT_DEFINED: Default locale has not been defined**。为了指定文化,我们调用 `Globalize.locale(...)` 并传入要使用的文化。文化名称必须与 `wwwroot\lib\cldr-data\main` 中的文件夹结构匹配,该文件夹包含下载的文化。
在 `_ValidationScriptsPartial.cshtml` 的末尾添加以下代码。
@inject Microsoft.AspNetCore.Hosting.IHostingEnvironment HostingEnvironment
@{
string GetDefaultLocale()
{
const string localePattern = "lib\\cldr-data\\main\\{0}";
var currentCulture = System.Globalization.CultureInfo.CurrentCulture;
var cultureToUse = "en-GB"; //Default regionalisation to use
if (System.IO.Directory.Exists(System.IO.Path.Combine(HostingEnvironment.WebRootPath, string.Format(localePattern, currentCulture.Name))))
cultureToUse = currentCulture.Name;
else if (System.IO.Directory.Exists(System.IO.Path.Combine(HostingEnvironment.WebRootPath, string.Format(localePattern, currentCulture.TwoLetterISOLanguageName))))
cultureToUse = currentCulture.TwoLetterISOLanguageName;
return cultureToUse;
}
}
<script type="text/javascript">
var culture = "@GetDefaultLocale()";
$.when(
$.get("/lib/cldr-data/supplemental/likelySubtags.json"),
$.get("/lib/cldr-data/main/" + culture + "/numbers.json"),
$.get("/lib/cldr-data/supplemental/numberingSystems.json"),
$.get("/lib/cldr-data/main/" + culture + "/ca-gregorian.json"),
$.get("/lib/cldr-data/main/" + culture +"/timeZoneNames.json"),
$.get("/lib/cldr-data/supplemental/timeData.json"),
$.get("/lib/cldr-data/supplemental/weekData.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);
});
</script>
测试
一旦所有代码都组装完毕,您可以通过更改浏览器语言或在地址字段中将文化设置为查询字符串参数来测试其是否按预期工作。
关注点
jQuery.Validation 接受的格式与模型绑定器理解的格式之间存在一些差异。例如,某些日期格式在客户端被接受,但在服务器端无法解析,导致模型无效。使用日期时间选择器可以消除这些不一致。
示例应用程序
示例应用程序需要恢复所有包并从 CLDR 下载所有文化,因此在首次加载解决方案时需要一些时间。