我正在编写一个自定义属性,以便在另一个属性具有指定值时要求viewmodel中的属性.
我用这篇文章作为参考:RequiredIf Conditional Validation Attribute
但是一直遇到IClientModelValidator的.NET Core修订版的问题.具体来说,服务器端验证按预期工作,ModelState.IsValid返回false,ModelState错误包含我的自定义错误代码.在不同版本的验证器之间进行翻译时,我觉得我遗漏了一些东西.
public IEnumerableMetadata Metadata,ControllerContext context)
{
var rule = new ModelClientValidationRule
{
ErrorMessage = ErrorMessageString,ValidationType = "requiredif",};
rule.ValidationParameters["dependentproperty"] =
(context as ViewContext).ViewData.TemplateInfo.GetFullHtmlFieldId(PropertyName);
rule.ValidationParameters["desiredvalue"] = DesiredValue is bool
? DesiredValue.ToString().ToLower()
: DesiredValue;
yield return rule;
}
根据这里概述的IClientModelValidator的变化:https://github.com/aspnet/Announcements/issues/179我写了以下方法:
public void AddValidation(ClientModelValidationContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
MergeAttribute(context.Attributes,"data-val","true");
var errorMessage = FormatErrorMessage(context.ModelMetadata.GetDisplayName());
MergeAttribute(context.Attributes,"data-val-requiredif",errorMessage);
MergeAttribute(context.Attributes,"data-val-requiredif-dependentproperty",PropertyName);
var desiredValue = DesiredValue.ToString().ToLower();
MergeAttribute(context.Attributes,"data-val-requiredif-desiredvalue",desiredValue);
}
private bool MergeAttribute(
IDictionary
这些是按预期调用的,并且值已正确填充,但忽略了以下JS.让我怀疑我错过了两者之间的某些东西.
$.validator.addMethod("requiredif",function (value,element,parameters) {
var desiredvalue = parameters.desiredvalue;
desiredvalue = (desiredvalue == null ? "" : desiredvalue).toString();
var controlType = $("input[id$='" + parameters.dependentproperty + "']").attr("type");
var actualvalue = {}
if (controlType === "checkBox" || controlType === "radio") {
var control = $("input[id$='" + parameters.dependentproperty + "']:checked");
actualvalue = control.val();
} else {
actualvalue = $("#" + parameters.dependentproperty).val();
}
if ($.trim(desiredvalue).toLowerCase() === $.trim(actualvalue).toLocaleLowerCase()) {
var isValid = $.validator.methods.required.call(this,value,parameters);
return isValid;
}
return true;
});
$.validator.unobtrusive.adapters.add("requiredif",["dependentproperty","desiredvalue"],function (options) {
options.rules["requiredif"] = options.params;
options.messages["requiredif"] = options.message;
});
有任何想法吗?
编辑:只是为了消除服务器端正常工作的疑问,问题几乎肯定在客户端,这里是一个装饰字段生成的HTML片段:
requiredif="Profession Other Specification is required" data-val-requiredif-dependentproperty="ProfessionTypeId" data-val-requiredif-desiredvalue="10" id="ProfessionOther" name="ProfessionOther" value="" placeholder="Please Specify Other">
不幸的是,由于验证器对象已经创建并附加到没有我的自定义验证器的表单,它从未到达该函数.解决这个问题的关键是将我的两个JS函数移到jQuery ready函数之外,尽可能靠近我的主脚本顶部(就在我设置jQuery验证器默认值之后).我希望这有助于其他人!
我的项目是用TypeScript编写的,所以我的结构有点不同,但实际添加验证器的JavaScript保持不变.
这是我的“Sometimesrequired”验证器Typescript类的代码:
export class requiredSometimesValidator {
constructor() {
// validator code starts here
$.validator.addMethod("requiredsometimes",params) {
var $prop = $("#" + params);
// $prop not found; search for a control whose Id ends with "_params" (child view)
if ($prop.length === 0)
$prop = $("[id$='_" + params + "']");
if ($prop.length > 0) {
var ctrlState = $prop.val();
if (ctrlState === "Editablerequired" && (value === "" || value === "Undefined"))
return false;
}
return true;
});
$.validator.unobtrusive.adapters.add("requiredsometimes",["controlstate"],function (options) {
options.rules["requiredsometimes"] = options.params["controlstate"];
options.messages["requiredsometimes"] = options.message;
});
// validator code stops here
}
}
然后在我的boot-client.ts文件(为我的应用程序的JavaScript提供动力的主文件)中,我在文档之外实例化上面的验证器的新副本(因此调用构造函数,该构造函数将自定义验证器添加到内存中的验证器对象).准备:
export class Blueprint implements IBlueprint {
constructor() {
// this occurs prior to document.ready
this.initCustomValidation();
$(() => {
// document ready stuff here
});
}
private initCustomValidation = (): void => {
// structure allows for load of additional client-side validators
new requiredSometimesValidator();
}
}
作为一个不使用TypeScript的简单示例,您应该能够这样做: