代码之家  ›  专栏  ›  技术社区  ›  Ben

是否可以访问其他属性的元数据以进行ASP.NET Core 2.1 MVC客户端验证?

  •  0
  • Ben  · 技术社区  · 8 年前

    我希望通过实现 IClientModelValidator 接口。具体来说,我正在创建一个 NotEqualTo (后来 EqualTo )将一个输入值与另一个输入值进行比较的验证属性。

    为了提供一个好的UX,我想在错误消息中使用两个输入的显示名称:“例如,密码不能与电子邮件相同”。

    这显然已经做了一百万次了,而且有很多例子,但是它们要么是用于MVC的早期版本,要么不使用其他属性的显示名称。

    下面是到目前为止我所拥有的。我已经设法通过 Display 服务器端的属性 IsValid(...) 方法,但我无法解决如何为客户端执行类似操作 AddValidation(...) 方法。

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class NotEqualToAttribute : ValidationAttribute, IClientModelValidator
    {
      private const string defaultErrorMessage = "{0} cannot be the same as {1}.";
    
      public string OtherProperty { get; private set; }
    
      public NotEqualToAttribute(string otherProperty) : base(defaultErrorMessage)
      {
        this.OtherProperty = otherProperty;
      }
    
      public override string FormatErrorMessage(string name) 
      {
        string.Format(base.ErrorMessageString, name, this.OtherProperty);
      }
    
      public void AddValidation(ClientModelValidationContext context)
      {
        context.Attributes.Add("data-val", "true");      
        context.Attributes.Add("data-val-notequalto", this.FormatErrorMessage(context.ModelMetadata.GetDisplayName());
        context.Attributes.Add("data-val-notequalto-otherproperty", this.otherProperty);
      }
    
      protected override ValidationResult IsValid(object value, ValidationContext validationContext)
      {
        if (value == null)
          return ValidationResult.Success;
    
        PropertyInfo otherProperty = validationContext.ObjectInstance.GetType().GetProperty(this.OtherProperty);
        object otherValue = otherProperty.GetValue(validationContext.ObjectInstance, null);
    
        if (!value.Equals(otherValue))
          return ValidationResult.Success;
    
        DisplayAttribute display = otherProperty.GetCustomAttribute<DisplayAttribute>();
        string otherName = display?.GetName() ?? this.OtherProperty;
    
        return new ValidationResult(string.Format(defaultErrorMessage, validationContext.DisplayName, otherName));
      }        
    }
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   Ben    8 年前

    通常情况下,我在休息后自己解决了这个问题,只需将它留在这里,以防它帮助其他人(或有更好的解决方案):

    public void AddValidation(ClientModelValidationContext context)
    {            
      context.Attributes.Add("data-val", "true");
    
      string otherName = 
        context.ModelMetadata.ContainerMetadata.Properties
          .Single(p => p.PropertyName == this.OtherProperty)
          .GetDisplayName();
    
      context.Attributes.Add("data-val-notequalto", 
        string.Format(defaultErrorMessage, context.ModelMetadata.GetDisplayName(), otherName)
      );
    }
    

    您可以通过以下方式获取其他属性的元数据: ClientModelValidationContext.ModelMetadata.ContainerMetadata.Properties