是否可以从 ValidationAttribute 中的不同模型访问属性

Is it possible to access properties from a different model in a ValidationAttribute

我有一个网络 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 吗?

据我所知 - 没有办法做到这一点,例如 A 本身并不知道它属于 parent.
但还有另一种方法。您可以将 ConditionallyValidatedAttribute 应用于 属性 XY,而不是将其应用于整个 AB parent ].这样做,您可以访问 IsValid 方法中的整个 AImportantInformation。类似的东西:

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;
    }
}

对于这个问题,我遇到了两种解决方案。第一个是 Roman 的(在 class 层次结构中向上移动属性)。第二个是不使用需要来自多个 classes 的信息的验证属性。这是它的样子:

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);
    }
  }
}