如何为部分视图中的元素实现验证规则
How to implement validation rules for elements from a partial view
我们正在开发 .net core 3.1 MVC 应用程序(实际使用 MVVMC)。
我们已经实现了自定义验证属性。并希望在服务器和客户端检查它们。
该视图是标准视图,但用户可以向标准视图添加多个局部视图(通过按钮)。
在部分视图中,我们无法在输入字段中使用 'asp-for' 标签助手,因为可以多次添加相同的项目,我们需要能够在其中创建一个列表从那些额外的部分视图中选择的 ViewModel。这就是我们尝试自己构建标签的原因。
一旦通过 ajax 请求了部分视图,我们将再次调用验证器。服务器验证有效,客户端验证仅适用于主视图上的那些输入,不适用于部分视图上的输入。但是,刷新后或服务器在验证错误后将用户发回时,客户端验证开始工作(因为站点已完全刷新并且 jquery 验证考虑了部分视图的输入字段)。
请查找以下代码:
验证属性的实现
public class AllowedExtensionsAttribute: ValidationAttribute, IClientModelValidator
{
private readonly List<string> _extensions = new List<string>();
public AllowedExtensionsAttribute(string extensions)
{
_extensions.Add(extensions);
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
if (value is IFormFile file)
{
var extension = Path.GetExtension(file.FileName);
if (!_extensions.Contains(extension.ToLower()))
{
return new ValidationResult(ErrorMessage);
}
}
return ValidationResult.Success;
}
public void AddValidation(ClientModelValidationContext context)
{
context.Attributes.Add("data-val", "true");
context.Attributes.Add("data-val-extension", ErrorMessage);
}
}
MainViewModel
[AllowedExtensions(".pdf", ErrorMessage = "This data type is not allowed!")]
public IFormFile PdfDocumentOne { get; set; }
PartialViewModel
[AllowedExtensions(".pdf", ErrorMessage = "This data type is not allowed!")]
public IFormFile PdfDocumentTwo { get; set; }
主视图
<form method="post" asp-controller="Home" asp-action="MainView" enctype="multipart/form-data">
<div class="form-group top-buffer">
<div class="row">
<div class="col-2">
<label asp-for="PdfDocumentOne" class="control-label"></label>
</div>
<div class="col-3">
<input asp-for="PdfDocumentOne" class="form-control-file" accept="application/pdf" />
<span asp-validation-for="PdfDocumentOne" class="text-danger"></span>
</div>
</div>
</div>
<div id="container">
<div id="containerFull" class="form-group">
<div class="row">
<div class="col-2">
<label class="control-label">...</label>
</div>
<div class="col-10">
<div id="containerPartialView">
</div>
</div>
</div>
<div class="row">
<div class="col-2">
</div>
<div class="col-3">
<button id="AddPartialView" type="button" class="form-control">...</button>
</div>
</div>
</div>
</div>
...
<div class="form-group top-buffer">
<div class="row">
<div class="col-2">
<input type="submit" value="Submit" class="form-control" id="checkBtn" />
</div>
</div>
</div>
</form>
局部视图
<input id="Lists[@Model.ViewId].ViewId" name="Lists[@Model.ViewId].ViewId" class="partialViewModel" type="hidden" value="@Model.ViewId" />
<div id="Lists[@Model.ViewId].MainContainer" class="partialView">
<div class="form-group">
<div>
<div class="col-2">
<label asp-for="PdfDocumentTwo" class="control-label"></label>
</div>
<div class="col-3">
<input name="Lists[@Model.ViewId].PdfDocumentTwo" id="Lists[@Model.ViewId].PdfDocumentTwo " type="file" class="form-control-file" accept="application/pdf"
data-val="true" data-val-extension="This data type is not allowed!"/>
<span class="text-danger field-validation-valid" data-valmsg-for="Lists[@Model.ViewId].PdfDocumentTwo" data-valmsg-replace="true"></span>
</div>
</div>
</div>
...
</div>
Javascript
function AddPartialView() {
var i = $(".partialView").length;
$.ajax({
url: '/Home/AddPartialView?index=' + i,
success: function (data) {
$('#containerPartialView').append(data);
$().rules('remove','extension');
jQuery.validator.unobtrusive.adapters.addBool("extension");
},
error: function (a, b, c) {
console.log(a, b, c);
}
});
}
$('#AddPartialView').click(function () {
AddPartialView();
});
jQuery.validator.addMethod("extension",
function (value, element, param) {
var extension = value.split('.').pop().toLowerCase();
if ($.inArray(extension, ['pdf']) == -1) {
return false;
}
return true;
});
jQuery.validator.unobtrusive.adapters.addBool("extension");
家庭控制器
[HttpPost]
public IActionResult MainView(MainViewModel vm)
{
if (vm == null)
{
return RedirectToAction("Index");
}
DatabaseHelper.GetMainViewModel(vm);
if (!ModelState.IsValid)
{
@ViewData["StatusMessageNegative"] = "The entered data is not valid. Please scroll down to correct your data.";
return View(vm);
}
return RedirectToAction("UploadDocument", new { Id = vm.Id});
}
[HttpGet]
public ActionResult AddPartialView(int index)
{
PartialViewModel pvm = DatabaseHelper.GetPartialViewModel(index);
return PartialView("Partial", pvm);
}
在网上搜索后,我们发现了以下参数(data-ajax="true")。但是,我们不知道将它放在哪里或如何正确使用它。
您是否尝试过在加载局部视图后重新应用验证?
$.ajax({
url: '/Home/AddPartialView?index=' + i,
success: function (data) {
$('#containerPartialView').append(data);
$().rules('remove','extension');
jQuery.validator.unobtrusive.adapters.addBool("extension");
},
error: function (a, b, c) {
console.log(a, b, c);
}
}).then(function () {
$("form").each(function () { $.data($(this)[0], 'validator', false); });
$.validator.unobtrusive.parse("form");
});
我们正在开发 .net core 3.1 MVC 应用程序(实际使用 MVVMC)。
我们已经实现了自定义验证属性。并希望在服务器和客户端检查它们。
该视图是标准视图,但用户可以向标准视图添加多个局部视图(通过按钮)。
在部分视图中,我们无法在输入字段中使用 'asp-for' 标签助手,因为可以多次添加相同的项目,我们需要能够在其中创建一个列表从那些额外的部分视图中选择的 ViewModel。这就是我们尝试自己构建标签的原因。
一旦通过 ajax 请求了部分视图,我们将再次调用验证器。服务器验证有效,客户端验证仅适用于主视图上的那些输入,不适用于部分视图上的输入。但是,刷新后或服务器在验证错误后将用户发回时,客户端验证开始工作(因为站点已完全刷新并且 jquery 验证考虑了部分视图的输入字段)。
请查找以下代码:
验证属性的实现
public class AllowedExtensionsAttribute: ValidationAttribute, IClientModelValidator
{
private readonly List<string> _extensions = new List<string>();
public AllowedExtensionsAttribute(string extensions)
{
_extensions.Add(extensions);
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
if (value is IFormFile file)
{
var extension = Path.GetExtension(file.FileName);
if (!_extensions.Contains(extension.ToLower()))
{
return new ValidationResult(ErrorMessage);
}
}
return ValidationResult.Success;
}
public void AddValidation(ClientModelValidationContext context)
{
context.Attributes.Add("data-val", "true");
context.Attributes.Add("data-val-extension", ErrorMessage);
}
}
MainViewModel
[AllowedExtensions(".pdf", ErrorMessage = "This data type is not allowed!")]
public IFormFile PdfDocumentOne { get; set; }
PartialViewModel
[AllowedExtensions(".pdf", ErrorMessage = "This data type is not allowed!")]
public IFormFile PdfDocumentTwo { get; set; }
主视图
<form method="post" asp-controller="Home" asp-action="MainView" enctype="multipart/form-data">
<div class="form-group top-buffer">
<div class="row">
<div class="col-2">
<label asp-for="PdfDocumentOne" class="control-label"></label>
</div>
<div class="col-3">
<input asp-for="PdfDocumentOne" class="form-control-file" accept="application/pdf" />
<span asp-validation-for="PdfDocumentOne" class="text-danger"></span>
</div>
</div>
</div>
<div id="container">
<div id="containerFull" class="form-group">
<div class="row">
<div class="col-2">
<label class="control-label">...</label>
</div>
<div class="col-10">
<div id="containerPartialView">
</div>
</div>
</div>
<div class="row">
<div class="col-2">
</div>
<div class="col-3">
<button id="AddPartialView" type="button" class="form-control">...</button>
</div>
</div>
</div>
</div>
...
<div class="form-group top-buffer">
<div class="row">
<div class="col-2">
<input type="submit" value="Submit" class="form-control" id="checkBtn" />
</div>
</div>
</div>
</form>
局部视图
<input id="Lists[@Model.ViewId].ViewId" name="Lists[@Model.ViewId].ViewId" class="partialViewModel" type="hidden" value="@Model.ViewId" />
<div id="Lists[@Model.ViewId].MainContainer" class="partialView">
<div class="form-group">
<div>
<div class="col-2">
<label asp-for="PdfDocumentTwo" class="control-label"></label>
</div>
<div class="col-3">
<input name="Lists[@Model.ViewId].PdfDocumentTwo" id="Lists[@Model.ViewId].PdfDocumentTwo " type="file" class="form-control-file" accept="application/pdf"
data-val="true" data-val-extension="This data type is not allowed!"/>
<span class="text-danger field-validation-valid" data-valmsg-for="Lists[@Model.ViewId].PdfDocumentTwo" data-valmsg-replace="true"></span>
</div>
</div>
</div>
...
</div>
Javascript
function AddPartialView() {
var i = $(".partialView").length;
$.ajax({
url: '/Home/AddPartialView?index=' + i,
success: function (data) {
$('#containerPartialView').append(data);
$().rules('remove','extension');
jQuery.validator.unobtrusive.adapters.addBool("extension");
},
error: function (a, b, c) {
console.log(a, b, c);
}
});
}
$('#AddPartialView').click(function () {
AddPartialView();
});
jQuery.validator.addMethod("extension",
function (value, element, param) {
var extension = value.split('.').pop().toLowerCase();
if ($.inArray(extension, ['pdf']) == -1) {
return false;
}
return true;
});
jQuery.validator.unobtrusive.adapters.addBool("extension");
家庭控制器
[HttpPost]
public IActionResult MainView(MainViewModel vm)
{
if (vm == null)
{
return RedirectToAction("Index");
}
DatabaseHelper.GetMainViewModel(vm);
if (!ModelState.IsValid)
{
@ViewData["StatusMessageNegative"] = "The entered data is not valid. Please scroll down to correct your data.";
return View(vm);
}
return RedirectToAction("UploadDocument", new { Id = vm.Id});
}
[HttpGet]
public ActionResult AddPartialView(int index)
{
PartialViewModel pvm = DatabaseHelper.GetPartialViewModel(index);
return PartialView("Partial", pvm);
}
在网上搜索后,我们发现了以下参数(data-ajax="true")。但是,我们不知道将它放在哪里或如何正确使用它。
您是否尝试过在加载局部视图后重新应用验证?
$.ajax({
url: '/Home/AddPartialView?index=' + i,
success: function (data) {
$('#containerPartialView').append(data);
$().rules('remove','extension');
jQuery.validator.unobtrusive.adapters.addBool("extension");
},
error: function (a, b, c) {
console.log(a, b, c);
}
}).then(function () {
$("form").each(function () { $.data($(this)[0], 'validator', false); });
$.validator.unobtrusive.parse("form");
});