Razor分页具有模型绑定和至少一个选项的多个复选框必须选中"服务器/客户端验证"



我希望有多个带有验证的复选框,其中至少选择了一个。理想情况下,这些复选框应该绑定到我的页面模型。

当我采取不同的方法时,我似乎总是遇到不同的问题。在下面的方法中,客户端验证有效,但模型绑定不起作用(因此服务器验证不起作用(。如果我忽略客户端验证(删除javascript和="ProductLines"输入的隐藏asp(,那么我就可以获得服务器端验证和模型绑定。理想情况下,我希望模型绑定和客户端/服务器端验证能够正常工作。

我感到惊讶的是,用剃须刀片不容易做到这一点。但是,也许你能帮忙?否则,我将来可能会更好地使用客户端和服务器端框架。我尽量避免这种情况,因为对于更简单的应用程序来说,这似乎有些过头了。

复选框类别:

public class Checkbox
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}

验证属性

public class OneCheckboxMustBeChecked : ValidationAttribute, IClientModelValidator
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var checkboxOptions = validationContext.ObjectInstance as List<Checkbox>;

foreach (var option in checkboxOptions)
{
if (option.IsSelected)
{
return ValidationResult.Success;
}
}
return new ValidationResult(GetErrorMessage());
}
public void AddValidation(ClientModelValidationContext context)
{
MergeAttribute(context.Attributes, "data-val", "true");
MergeAttribute(context.Attributes, "data-val-OneCheckboxMustBeChecked", GetErrorMessage());
}
private string GetErrorMessage()
{
return "A checkbox option must be selected";
}
private bool MergeAttribute(IDictionary<string, string> attributes, string key, string value)
{
if (attributes.ContainsKey(key))
{
return false;
}
attributes.Add(key, value);
return true;
}

}

页面模型(cshtml.cs(:

[BindProperty]
[Required]
[DisplayName("Product Lines:")]
[OneCheckboxMustBeChecked]
public List<Checkbox> ProductLines { get; set; }

cshtml

<div class="form-row row">
<label class="col-form-label pt-0" asp-for="ProductLines"></label>
<input type="hidden" asp-for="ProductLines" />
<div id="ProductLineCheckBoxes">
@for (int i = 0; i < Model.ProductLines.Count; i++)
{
<div class="form-check form-check-inline">
<input type="hidden" asp-for="@Model.ProductLines[i].Id" />
<input type="hidden" asp-for="@Model.ProductLines[i].Name" />
<input asp-for="@Model.ProductLines[i].IsSelected" class="form-check-input" />
<label class="form-check-label" asp-for="@Model.ProductLines[i].IsSelected">
@Model.ProductLines[i].Name
</label>
</div>
}
</div>
<span class="text-danger" asp-validation-for="ProductLines"></span>
</div>

无干扰Jquery验证

//This is used to include hidden input tags into our unobtrusive jquery validation. 
//hidden input fields are not included in validation by default
$.validator.setDefaults({
ignore: ""
});
$.validator.addMethod('OneCheckboxMustBeChecked',
function(value, element) {
var checked = $(element.nextElementSibling).find('input:checked');
if (checked.length === 0) {
return false;
}
return true;
});
$.validator.unobtrusive.adapters.add('OneCheckboxMustBeChecked',
[],
function (options) {
options.rules['OneCheckboxMustBeChecked'] = [];
options.messages['OneCheckboxMustBeChecked'] = options.message;
});

当我采取不同的方法。以下方法,客户端验证工作,但模型绑定不起作用(因此服务器验证不起作用(。如果我忽略客户端验证(删除javascript和隐藏的asp for=";ProductLines";输入(,然后我可以让服务器端验证和模型绑定工作。理想地,我想要模型绑定和客户端/服务器端验证工作

根据您的代码,我已经重现了这个问题。该问题与隐藏文件有关:

<input type="hidden" asp-for="ProductLines" />

如果添加上述代码,则会将客户端验证方法添加到隐藏字段中,执行Unobtrusive Jquery validation方法。验证成功后,如果在IsValid方法中设置调试器,则可以看到参数的值为null。

如果删除上述代码,由于网页不包含ProductLines元素,客户端验证属性(如"data val"或"data val OneCheckboxMustBeChecked"(不会添加到元素中。因此不会执行Unobtrusive Jquery Validation。

为了解决这个问题,在OneCheckboxMustBeChecked方法中,在验证成功后,删除";ProductLines";隐藏文件。

$.validator.addMethod('OneCheckboxMustBeChecked',
function(value, element) {
var checked = $(element.nextElementSibling).find('input:checked');
if (checked.length === 0) {
return false;
}

//remove the hidden files
$("input[name='ProductLines']").remove();
return true;
});

最新更新