【问题标题】:Custom validation method that accesses other model properties访问其他模型属性的自定义验证方法
【发布时间】:2015-01-23 23:12:42
【问题描述】:

我正在尝试为我的一个实体创建自定义验证方法,因此我创建了一个继承自 ValidationAttribute 的类:

public class OneWheelchairPerTrainAttribute : ValidationAttribute
{
    public override bool IsValid(object value)
    {
        // This is where I need to access the other entity property
    }
}

我正在努力解决的是如何访问实体上的其他属性。这是我的实体:

public class Ticket
{
    public int Id { get; set; }

    [Required]
    public int TimetableId { get; set; }

    [Required]
    public bool Wheelchair { get; set; }

    public virtual Timetable Timetable { get; set; }
}

我正在编写的验证注释将应用于Wheelchair 属性,我需要从我的验证方法中访问TimetableId 属性。

【问题讨论】:

    标签: c# asp.net-mvc entity-framework validation


    【解决方案1】:

    另一种(在我看来,更好的)验证多个属性的方法是在class 级别上进行。

    这与您的答案不完全相同,但仍涉及多个属性验证。

    想象一下,你想让轮椅成为一个 id 或一个新对象,但你仍然想只允许一个:

    我的ExactlyOneRequired 属性示例:

    [AttributeUsage(AttributeTargets.Class)]
    public class ExactlyOneRequiredAttribute : ValidationAttribute
    {
        public string FirstPropertyName { get; set; }
        public string SecondPropertyName { get; set; }
    
        //Constructor to take in the property names that are supposed to be checked
        public ExactlyOneRequiredAttribute(string firstPropertyName, string secondPropertyName)
        {
            FirstPropertyName = firstPropertyName;
            SecondPropertyName = secondPropertyName;
        }
    
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null) 
               return new ValidationResult("Object must have a value;");
    
            var neededProperties = validationContext.ObjectType.GetProperties().Where(propertyInfo => propertyInfo.Name == FirstPropertyName || propertyInfo.Name == SecondPropertyName).Take(2).ToArray();
            var value1 = neededProperties[0].GetValue(value);
            var value2 = neededProperties[1].GetValue(value);
    
            if (value1 == null | value2 == null)
                return ValidationResult.Success;
    
            return FailedValidationResult();
        }
    
        public override string FormatErrorMessage(string name) => $"One of the fields: '{FirstPropertyName} or {SecondPropertyName}' is required, it is not allowed to set both.";
    
        private ValidationResult FailedValidationResult() => new ValidationResult(FormatErrorMessage(FirstPropertyName), new List<string> {FirstPropertyName, SecondPropertyName});
    }
    

    用法:

    [ExactlyOneRequired(nameof(WheelChairId), nameof(WheelChair))]
    public class Train
    {
        public int? WheelChairId { get; set; }
    
        public WheelChair WheelChair { get; set; }
    }
    

    您当然可以期望任意多的属性,并将其设置为 通用。我的观点是,字符串检查属性中的属性名称,注入属性名称是更清洁的方法,

    【讨论】:

      【解决方案2】:

      您可以使用IsValid overload 传递一个ValidationContext,如下所示:

      public class OneWheelchairPerTrainAttribute : ValidationAttribute
      {
        public override bool IsValid(object value, ValidationContext context)
        {
          Object instance = context.ObjectInstance;
          Type type = instance.GetType();
          // Here is your timetableId
          Object timeTableId = type.GetProperty("TimetableId ").GetValue(instance, null);
      
          //Do validation ...
         }
      }
      

      【讨论】:

      • 该方法没有公共覆盖。您必须使用“受保护的覆盖 ValidationResult IsValid...”
      猜你喜欢
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      • 1970-01-01
      • 2015-08-11
      • 1970-01-01
      • 2013-01-29
      相关资源
      最近更新 更多