对需要其他属性值的属性进行验证
本文关键字:属性 验证 其他 | 更新日期: 2023-09-27 18:17:03
所以我已经检查了这个答案asp.net MVC 4动态验证的属性取决于另一个属性的当前值,它不包括我的问题。
我使用服务器端验证。我有一个要求……
只有在指定了其他属性时才需要该值
MVC绑定每个属性,并在绑定时调用该属性上的每个验证器。如果我依赖于多个属性,当我检查validationContext.ObjectInstance.[MY_DEPENDENT_PROPERTY]
时,有可能那些依赖的属性还没有被绑定。
我需要的是一个验证属性,在绑定之后验证 -如果存在的话。
所以这里有一个简单的例子来解释我的情况(不打算被执行,因为它很可能会很好,因为这个问题与绑定顺序有关)
我的模型public class Address
{
[Required]
public string ResidentialAddress { get; set; }
public bool PostalIsTheSameAsResidential { get; set; }
// will only be required if PostalIsTheSameAsResidential is false.
// see the static method below and RequiredIfAttribute
[RequiredIf(typeof(Address), nameof(PostalRequiredIfNotSameAsResidential)]
public string PostalAddress { get; set; }
public static bool PostalRequiredIfNotSameAsResidential(Address model)
{
return !model.PostalIsTheSameAsResidential;
}
}
我的验证器本质上,这里发生的事情是调用模型上的静态方法来查看它是否应该验证。
public sealed class RequiredIfAttribute : RequiredAttribute
{
private readonly MethodInfo _validationMethod;
public override bool RequiresValidationContext => true;
public RequiredIfAttribute(Type type, string methodName)
{
this._validationMethod = type.GetMethod(methodName);
if (this._validationMethod == null)
{
throw new MethodAccessException($"The validation method '{methodName}' does not exist on type '{type}");
}
}
public override bool IsValid(object value)
{
throw new NotSupportedException();
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
ValidationResult result = ValidationResult.Success;
var parameters = this._validationMethod.GetParameters();
var returnType = this._validationMethod.ReturnType;
if (returnType == typeof(bool) && parameters.Length == 1 && parameters[0].ParameterType == validationContext.ObjectType)
{
if ((bool)_validationMethod.Invoke(null, new object[] { validationContext.ObjectInstance }))
{
if (!base.IsValid(value))
{
string[] memberNames;
if (validationContext.MemberName == null)
{
memberNames = null;
}
else
{
memberNames = new string[1];
memberNames[0] = validationContext.MemberName;
}
result = new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName), memberNames);
}
}
return result;
}
var expectedFuncType = typeof(Func<,>).MakeGenericType(validationContext.ObjectType, typeof(bool));
throw new MethodAccessException($"The validation method '{this._validationMethod}' does not have the correct definition. Expected '{expectedFuncType}'");
}
}
所以这个问题,我有是我从RequiredAttribute
继承。MVC内部对这个属性的处理方式与其他属性不同。
当模型绑定器循环遍历属性时,它获得RequiredAttribute
s并同时执行它们…
// System.Web.Mvc.DefaultModelBinder.SetProperty
....
ModelValidator modelValidator = (from v in ModelValidatorProviders.Providers.GetValidators(modelMetadata, controllerContext)
where v.IsRequired
select v).FirstOrDefault<ModelValidator>();
if (modelValidator != null)
{
foreach (ModelValidationResult current in modelValidator.Validate(bindingContext.Model))
{
bindingContext.ModelState.AddModelError(key, current.Message);
}
}
....
v.IsRequired
实际上解析为一行,该行测试当前属性是否为RequiredAttribute
,并将在当前不完整的模型状态下验证它。
通过继承ValidationAttribute
,它在模型建立后运行验证并解决了我的问题。
感谢@StephenMuecke给我的提示