【发布时间】:2018-09-10 09:10:44
【问题描述】:
我有一个 asp.net MVC 5 应用程序,我尝试在 .cshtml 文件的不同位置重用嵌套的复杂视图模型类。重用的复杂视图模型命名为SchoolPersonViewModel,有很多属性,Phone 和Email 属性验证为“如果不提供电话,则必须提供电子邮件。如果提供电话,则电子邮件是可选输入”。我编写了一个自定义服务器和客户端验证,但它适用于服务器端。但客户端验证无法正常工作。例如,Email 文本框提示填写,即使关联的 Phone 文本框已填写。请参阅附件。例如请帮忙。提前谢谢你。
我知道问题来自错误:3 个电子邮件文本框有 3 个验证属性,其值与 data-val-emailrequired-stringphoneprop="Phone" 相同。运行时的 Phone 值会导致歧义
(这是唯一性缺失)对于 jQuery 验证机,但我不知道如何解决它。请参阅下面的渲染属性。请帮忙。提前谢谢你。
关于我的代码的详细信息:
在我的cshtml 视图中,我调用视图模型复杂类 (SchoolPersonViewModel) 3 次:一次为Student,一次为Father,一次为Mother。
C# MVC 模型类
public class SchoolPersonViewModel
{
[DisplayName("Phone")]
public string Phone { get; set; }
[DisplayName("Email")]
[EmailRequired(StringPhonePropertyName = "Phone", ErrorMessage = "Email is required if Phone is not provided")]
public string Email { get; set; }
.... // other properties
}
public class StudentEnrollViewModel
{
public SchoolPersonViewModel Student { get; set; }
public SchoolPersonViewModel Father { get; set; }
public SchoolPersonViewModel Mother { get; set; }
}
验证属性
// If Phone is not input then Email is required -- server and client side validation
public class EmailRequiredAttribute : ValidationAttribute, IClientValidatable
{
public string StringPhonePropertyName { get; set; }
protected override ValidationResult IsValid(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext)
{
var phone = ValidatorCommon.GetValue<string>(validationContext.ObjectInstance, StringPhonePropertyName);
var email = (string)value;
if (!string.IsNullOrWhiteSpace(phone) || (string.IsNullOrWhiteSpace(phone) && !string.IsNullOrWhiteSpace(email)))
{
return ValidationResult.Success;
}
if (string.IsNullOrWhiteSpace(phone) && string.IsNullOrWhiteSpace(email))
{
return new ValidationResult(FormatErrorMessage(validationContext.DisplayName));
}
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var modelClientValidationRule = new ModelClientValidationRule
{
ValidationType = "emailrequired",
ErrorMessage = FormatErrorMessage(metadata.DisplayName)
};
modelClientValidationRule.ValidationParameters.Add("stringphoneprop", StringPhonePropertyName);
yield return modelClientValidationRule;
}
}
容器视图模型和 jQuery 验证代码:
@model ExpandoObjectSerializeDeserialize.Web.Models.StudentEnrollViewModel
....
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
....
@Html.EditorFor(m => m.Student)
....
@Html.EditorFor(m => m.Father)
....
@Html.EditorFor(m => m.Mother)
<input type="submit" value="Create" class="btn btn-default" />
}
@section scripts {
<script type="text/javascript">
jQuery.validator.addMethod('emailrequired', function(value, element, params) {
var phoneTextboxId = $(element).attr('data-val-emailrequired-stringphoneprop');
var phoneTextboxValue = $('#' + phoneTextboxId).val();
// empty string is evaluated as ‘false’ and non-empty, non-null string is evaluated as ‘true’ in JavaScript
return phoneTextboxValue || value;
});
jQuery.validator.unobtrusive.adapters.add('emailrequired', {}, function(options) {
options.rules['emailrequired'] = true;
options.messages['emailrequired'] = options.message;
});
</script>
}
上面的视图在运行时渲染如下:
<div class="col-md-4">
<input class="form-control text-box single-line" id="Father_Phone" name="Father.Phone" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="Father.Phone" data-valmsg-replace="true"></span>
</div>
<div class="col-md-4">
<input class="form-control text-box single-line input-validation-error" data-val="true" data-val-emailrequired="Email is required if Phone is not provided" data-val-emailrequired-stringphoneprop="Phone" id="Student_Email" name="Student.Email" type="text" value="">
<span class="text-danger field-validation-error" data-valmsg-for="Student.Email" data-valmsg-replace="true"><span for="Student_Email" class="">Email is required if Phone is not provided</span></span>
</div>
<div class="col-md-4">
<input class="form-control text-box single-line" id="Mother_Phone" name="Mother.Phone" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="Mother.Phone" data-valmsg-replace="true"></span>
</div>
<div class="col-md-4">
<input class="form-control text-box single-line input-validation-error" data-val="true" data-val-emailrequired="Email is required if Phone is not provided" data-val-emailrequired-stringphoneprop="Phone" id="Father_Email" name="Father.Email" type="text" value="">
<span class="text-danger field-validation-error" data-valmsg-for="Father.Email" data-valmsg-replace="true"><span for="Father_Email" class="">Email is required if Phone is not provided</span></span>
</div>
<div class="col-md-4">
<input class="form-control text-box single-line" id="Mother_Phone" name="Mother.Phone" type="text" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="Mother.Phone" data-valmsg-replace="true"></span>
</div>
<div class="col-md-4">
<input class="form-control text-box single-line input-validation-error" data-val="true" data-val-emailrequired="Email is required if Phone is not provided" data-val-emailrequired-stringphoneprop="Phone" id="Mother_Email" name="Mother.Email" type="text" value="">
<span class="text-danger field-validation-error" data-valmsg-for="Mother.Email" data-valmsg-replace="true"><span for="Mother_Email" class="">Email is required if Phone is not provided</span></span>
</div>
【问题讨论】:
标签: jquery asp.net-mvc asp.net-mvc-4 asp.net-mvc-3 unobtrusive-validation