是否可以从ValidationAttribute中的其他模型访问属性

时间:2019-12-30 20:59:33

标签: c# asp.net-web-api 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中?

2 个答案:

答案 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内部的整个XY,而不是将A应用于属性Bparent。这样,您就可以在A方法内部访问整个ImportantInformationIsValid。像这样:

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