我有两种不同的类型:
public class Person
{
public string Name { get; set; }
public bool IsActive { get; set; }
public Contact ContactDetails { get; set; }
}
public class Contact
{
[RequiredIfActive]
public string Email { get; set; }
}
我需要的是根据父模型字段的某些状态执行内部模型字段的条件声明性验证 - 在此特定示例中,如果Email
选项为IsActive
,则必须填充public class RequiredIfActiveAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
/* validationContext.ObjectInstance gives access to the current
Contact type, but is there any way of accessing Person type? */
启用。
我不想重新组织这些模型分类,同时我需要使用基于属性的方法。似乎从属性内部无法访问父模型的验证上下文。如何到达或注射它?
System.ComponentModel.DataAnnotations.ValidationAttribute
修改
我知道如何使用Fluent验证来实现条件验证,但我不是在询问(我不需要有关Fluent验证的支持)。但是,我想知道,如果存在从{{1}}内部访问父模型的任何方式。
答案 0 :(得分:1)
我的建议
转到工具=>库包管理器=>包管理器控制台并安装Fluent验证。
行动方法
[HttpGet]
public ActionResult Index()
{
var model = new Person
{
Name = "PKKG",
IsActive = true,
ContactDetails = new Contact { Email = "PKKG@stackoverflow.com" }
};
return View(model);
}
[HttpPost]
public ActionResult Index(Person p)
{
return View(p);
}
流利的验证规则
public class MyPersonModelValidator : AbstractValidator<Person>
{
public MyPersonModelValidator()
{
RuleFor(x => x.ContactDetails.Email)
.EmailAddress()
.WithMessage("Please enter valid email address")
.NotNull().When(i => i.IsActive)
.WithMessage("Please enter email");
}
}
查看模型
[Validator(typeof(MyPersonModelValidator))]
public class Person
{
[Display(Name = "Name")]
public string Name { get; set; }
[Display(Name = "IsActive")]
public bool IsActive { get; set; }
public Contact ContactDetails { get; set; }
}
public class Contact
{
[Display(Name = "Email")]
public string Email { get; set; }
}
查看强>
@{
var actionURL = Url.Action("Action", "Controller", new { area = "AreaName" },
Request.Url.Scheme);
}
@using (Html.BeginForm("Action", "Controller", FormMethod.Post,
new { @action = actionURL }))
@Html.EditorFor(i => i.Name);
@Html.ValidationMessageFor(i => i.Name);
@Html.EditorFor(i => i.IsActive);
@Html.ValidationMessageFor(i => i.IsActive);
@Html.EditorFor(i => i.ContactDetails.Email);
@Html.ValidationMessageFor(i => i.ContactDetails.Email);
<button type="submit">
OK</button>
}
答案 1 :(得分:1)
这不能通过Contact.Email
上的属性来完成,因为正如您已经发现的那样,父Person
在运行时无法从属性上下文中获得。要通过验证属性启用此方案,该属性必须装饰Person
类。对于System.ComponentModel.DataAnnotations
属性,您有两种选择:CustomValidationAttribute
或定位ValidationAttribute
的自定义Person
子类。
以下是使用CustomValidationAttribute
时两个类的外观:
[CustomValidation(typeof(Person), "ValidateContactEmail")]
public class Person
{
public string Name { get; set; }
public bool IsActive { get; set; }
public Contact ContactDetails { get; set; }
public static ValidationResult ValidateContactEmail(Person person, ValidationContext context)
{
var result = ValidationResult.Success;
if (person.IsActive)
{
if ((person.ContactDetails == null) || string.IsNullOrEmpty(person.ContactDetails.Email))
{
result = new ValidationResult("An e-mail address must be provided for an active person.", new string[] { "ContactDetails.Email" });
}
}
return result;
}
}
public class Contact
{
public string Email { get; set; }
}