【问题标题】:Need to have conditional data annotation required validation of a field based on value of another field of sub model需要有条件数据注释需要根据子模型的另一个字段的值验证一个字段
【发布时间】:2019-05-04 16:56:32
【问题描述】:

需要根据驻留在子模型中的字段的值对字段进行数据注释所需的字段验证

当 PatientViewModel.PatientSettingViewModel.MiddleName 的值为 true 时,需要对 PatientViewModel.MiddleName 进行必填字段验证

public partial class PatientViewModel
{
     [DisplayName("Patient ID")]
     public string PatientId { get; set; }

     public PatientSettingViewModel patientSetting { get; set; }

     [RequiredIf("patientSetting.MiddleName", true, ErrorMessage = "Middle Name is Required")]
     [LettersOnly]
     [MaxLength(20, ErrorMessage = "Maximum length is 20.")]
     public string MiddleName { get; set; }
}

public class PatientSettingViewModel : BaseEntity
{
    [DisplayName("Middle Name")]
    public bool MiddleName { get; set; }
}

public class RequiredIfAttribute : ConditionalValidationAttribute
{
    protected override string ValidationName
    {
        get { return "requiredif"; }
    }
    public RequiredIfAttribute(string dependentProperty, object targetValue) : base(new RequiredAttribute(), dependentProperty, targetValue)
    {
    }
    protected override IDictionary<string, object> GetExtraValidationParameters()
    {
        return new Dictionary<string, object> { { "rule", "required" }        };
    }
}

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
public abstract class ConditionalValidationAttribute : ValidationAttribute, IClientValidatable
{
      protected readonly ValidationAttribute InnerAttribute;
      public string DependentProperty { get; set; }
      public object TargetValue { get; set; }
      protected abstract string ValidationName { get; }

      protected virtual IDictionary<string, object> GetExtraValidationParameters()
     {
    return new Dictionary<string, object>();
}

protected ConditionalValidationAttribute(ValidationAttribute innerAttribute, string dependentProperty, object targetValue)
{
    this.InnerAttribute = innerAttribute;
    this.DependentProperty = dependentProperty;
    this.TargetValue = targetValue;
}

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    // get a reference to the property this validation depends upon
    var containerType = validationContext.ObjectInstance.GetType();
    var field = containerType.GetProperty(this.DependentProperty);
    if (field != null)
    {
        // get the value of the dependent property
        var dependentvalue = field.GetValue(validationContext.ObjectInstance, null);

        // compare the value against the target value
        if ((dependentvalue == null && this.TargetValue == null) || (dependentvalue != null && dependentvalue.Equals(this.TargetValue)))
        {
            // match => means we should try validating this field
            if (!InnerAttribute.IsValid(value))
            {
                // validation failed - return an error
                return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
            }
        }
    }
    return ValidationResult.Success;
}

public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
    var rule = new ModelClientValidationRule()
    {
        ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
        ValidationType = ValidationName,
    };
    string depProp = BuildDependentPropertyId(metadata, context as ViewContext);
    // find the value on the control we depend on; if it's a bool, format it javascript style
    string targetValue = (this.TargetValue ?? "").ToString();
    if (this.TargetValue.GetType() == typeof(bool))
    {
        targetValue = targetValue.ToLower();
    }
    rule.ValidationParameters.Add("dependentproperty", depProp);
    rule.ValidationParameters.Add("targetvalue", targetValue);
    // Add the extra params, if any
    foreach (var param in GetExtraValidationParameters())
    {
        rule.ValidationParameters.Add(param);
    }
    yield return rule;
}

private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
{
    string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(this.DependentProperty);
    // This will have the name of the current field appended to the beginning, because the TemplateInfo's context has had this fieldname appended to it.
    var thisField = metadata.PropertyName + "_";
    if (depProp.StartsWith(thisField))
    {
        depProp = depProp.Substring(thisField.Length);
    }
    return depProp;
}

}

如果我将 bool 值放在同一模型中,我能够实现所需的输出,但我希望根据子模型的 bool 值进行有条件的要求验证。

【问题讨论】:

    标签: .net asp.net-mvc validation model data-annotations


    【解决方案1】:

    请使用 Fluent ValidationFull Proof 库进行模型和子模型验证。

    谢谢。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-28
      • 2013-01-05
      • 2019-03-25
      • 2017-05-24
      • 2019-10-22
      • 2011-07-21
      • 2011-09-20
      相关资源
      最近更新 更多