我有一个网络api,其中包含一些嵌套模型,它们的绑定方式如下:
public class Class1 {
//This data is needed in Class2 and Class3 validation
public bool ImportantInformation {get; set;}
public Class2 A {get; set;}
public Class3 B {get; set;}
}
public class Class2 {
[ConditionallyValidatedAttribute]
public string X {get; set;}
}
public class Class3 {
[ConditionallyValidatedAttribute]
public string Y {get; set;}
}
ConditionallyValidatedAttribute
看起来像这样:
public sealed class ConditionallyValidatedAttribute : ValidationAttribute {
protected override ValidationResult IsValid(object value, ValidationContext vc) {
bool importantInformation = //How do I get Class1.ImportantInformation?
if(importantImformation && value == null) {
return new ValidationResult($"{vc.MemberName} is invalid");
}
return ValidationResult.Success;
}
}
我的问题是是否可以根据需要将ImportantInformation
注入ConditionallyValidatedAttribute
中?
答案 0 :(得分:1)
针对此问题,我遇到了两种解决方案。第一个是Roman的(将属性在类层次结构中向上移动)。第二个是不要使用需要来自多个类的信息的属性进行验证。外观如下:
public class MyController : ApiController {
public IHttpActionResult Post(Class1 class1) {
IHttpActionResult actionResult = ValidateSchema(class1);
if(actionResult != null) {
return actionResult;
}
//Do business stuff here
return Ok();
}
private IHttpActionResult ValidateSchema(Class1 class1) {
if(class1.ImportantInformation) {
if(class1.A.X == null) {
ModelState.AddModelError("A.X", "X is invalid");
}
if(class1.B.Y == null) {
ModelState.AddModelError("B.Y", "Y is invalid");
}
}
if(!ModelState.IsValid) {
return BadRequest(ModelState);
}
}
}
答案 1 :(得分:0)
据我所知-无法执行此操作,因为实例A
本身并不知道它属于parent
。
但是还有另一种方式。您可以将其应用于ConditionallyValidatedAttribute
内部的整个X
或Y
,而不是将A
应用于属性B
或parent
。这样,您就可以在A
方法内部访问整个ImportantInformation
和IsValid
。像这样:
public class Class1
{
public bool ImportantInformation {get; set;}
[ConditionallyValidatedAttribute] //-->Validation Attribute here
public Class2 A {get; set;}
public Class3 B {get; set;}
}
public class Class2
{
public string X {get; set;}
}
public sealed class ConditionallyValidatedAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext vc)
{
var importantInformation = bool.Parse(vc.ObjectType.GetProperty("ImportantInformation")?.GetValue(vc.ObjectInstance)?.ToString() ?? "false");
if (importantInformation && (!(value is Class2) || string.IsNullOrEmpty(((Class2)value).X)))
{
return new ValidationResult($"{vc.MemberName} is invalid");
}
return ValidationResult.Success;
}
}