访问其他模型属性的自定义验证方法
Custom validation method that accesses other model properties
我正在尝试为我的一个实体创建自定义验证方法,因此我创建了一个继承自 ValidationAttribute
:
的 class
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
属性。
您可以使用 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 ...
}
}
另一种(在我看来,更好的)验证多个属性的方法是在 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; }
}
您当然可以期望任意数量的属性,并根据需要将其设为 generic。我的观点是,不是 字符串检查 属性内的 属性 名称, 注入 属性 名称是 清洁工 干得漂亮,
我正在尝试为我的一个实体创建自定义验证方法,因此我创建了一个继承自 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
属性。
您可以使用 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 ...
}
}
另一种(在我看来,更好的)验证多个属性的方法是在 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; }
}
您当然可以期望任意数量的属性,并根据需要将其设为 generic。我的观点是,不是 字符串检查 属性内的 属性 名称, 注入 属性 名称是 清洁工 干得漂亮,