【问题标题】:ASP MVC: Custom Validation AttributeASP MVC:自定义验证属性
【发布时间】:2010-04-27 11:34:32
【问题描述】:

我正在尝试编写自己的自定义验证属性,但遇到了一些问题。

我要写的属性是,当用户登录时,密码将与确认密码进行比较。

namespace Data.Attributes
{
public class ComparePassword : ValidationAttribute
{
    public string PasswordToCompareWith { get; set; }

    public override bool IsValid(object value)
    {
        if (PasswordToCompareWith == (string)value)
        {
            return true;
        }
       return false;
    }
}

现在我的问题是当我尝试在模型文件中设置这样的属性时:

 [Required]
    [ComparePassword(PasswordToCompareWith=ConfirmPassword)]
    public string Password { get; set; }


    [Required]
    public string ConfirmPassword { get; set; }
   }

我收到以下错误:

错误 1 ​​非静态字段、方法、 或属性 'Project.Data.Models.GebruikerRegistreerModel.ConfirmPassword.get'

似乎VS不接受PasswordToCompareWith=ConfirmPassword部分中的confirmpassword

我做错了什么?

【问题讨论】:

    标签: c# asp.net-mvc validation asp.net-mvc-2 attributes


    【解决方案1】:

    根据此链接http://devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-1,现在在 MVC3 中有一个特殊的验证属性:

    public class RegisterModel
    {
        // skipped
    
        [Required]
        [ValidatePasswordLength]
        [DataType(DataType.Password)]
        [Display(Name = "Password")]
        public string Password { get; set; }                       
    
        [DataType(DataType.Password)]
        [Display(Name = "Confirm password")]
        [Compare("Password", ErrorMessage = "The password and confirmation do not match.")]
        public string ConfirmPassword { get; set; }
    }
    

    CompareAttribute 是一个新的、非常有用的验证器,实际上并不是 部分 System.ComponentModel.DataAnnotations, 但已添加到 团队的 System.Web.Mvc DLL。同时 不是特别好命名(唯一的 它所做的比较是为了检查 平等,所以也许 EqualTo 是 更明显),很容易从 此验证器检查的用法 一个财产的价值等于 另一个财产的价值。你可以 从代码中可以看出,该属性 接受一个字符串属性,它是 其他属性的名称 你在比较。经典用法 这种类型的验证器就是我们 在这里使用它:密码 确认。

    【讨论】:

    【解决方案2】:

    很抱歉让您失望了,但是使用数据注释处理像您这样简单的案例可能会很痛苦。你可以看看this post

    【讨论】:

      【解决方案3】:

      FoolProof http://foolproof.codeplex.com/ 似乎是最好的解决方案。

      public class SignUpViewModel
      {
          [Required]
          public string Password { get; set; }
      
          [EqualTo("Password", ErrorMessage="Passwords do not match.")]
          public string RetypePassword { get; set; }
      }
      

      它比建议的 PropertiesMustMatchAttribute 更好,因为它为“RetypePassword”添加了验证错误,而不是像 PropertiesMustMatchAttribute 那样添加全局模型级别。

      【讨论】:

        【解决方案4】:

        我不知道为什么这会如此重要,请这样做:

        [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
        public class ComparePassword: ValidationAttribute
        {
            public ComparePassword() 
                : base("Passwords must match.") { }
        
            protected override ValidationResult IsValid (object value, ValidationContext validationContext)
            {
                if (value == null) return new ValidationResult("A password is required.");
        
                // Make sure you change YourRegistrationModel to whatever  the actual name is
                if ((validationContext.ObjectType.Name != "YourRegistrationModel") 
                     return new ValidationResult("This attribute is being used incorrectly.");
                if (((YourRegistrationModel)validationContext.ObjectInstance).ConfirmPassword != value.ToString())
                    return new ValidationResult("Passwords must match.");
        
                return ValidationResult.Success;
            }
        }
        

        现在您需要做的就是将[ComparePassword] 添加到您的密码属性中,无需传递任何内容...简单且相当干净

        【讨论】:

        • 超级好,但是考虑到新的 CompareAttribute @orcy 引起了我们的注意,我们没有必要推出我们自己的。
        • 这是令人满意的演示代码,但明显的问题是可重用性;它针对具有特定属性 (ConfirmPassword) 的特定实现 (YourRegistrationModel) 进行了硬编码。例如,如果您想将此方法用于多个模型,则需要多个实例或基本 PasswordModel 类型/接口。
        【解决方案5】:

        除非您执行一些相当蹩脚的反射代码,否则您不能将引用类型传递给属性。

        在这种情况下,我认为创建自定义模型绑定器会是一个更好的主意,然后检查 Password 和 ComparePassword。

        【讨论】:

        • 我认为模型绑定器肯定比使用带有反射的 DataAnnotations 更蹩脚。我认为模型绑定器不应该定义验证规则。
        • 哈,这是一个巨大的讨论话题。我无法正确解释空间这么短,但我可以为您指出一个很好的资源:@​​987654321@
        • 谢谢!!感谢您的帮助
        【解决方案6】:

        在您的情况下,您需要一个 STATIC 方法: 示例:

                public static ValidationResult ValidateFrequency( double frequency, ValidationContext context )
            {
                if( context == null )
                {
                    return ( ValidationResult.Success );
                }
          }
        

        【讨论】:

          【解决方案7】:

          举个例子:

           using System;
           using System.Collections.Generic;
           using System.ComponentModel.DataAnnotations;
           using System.Globalization;
           using System.Web.Mvc;
           using System.Web.Security;
          
           namespace GDNET.Web.Mvc.Validation
           {
          [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
          public sealed class ValidatePasswordLengthAttribute : ValidationAttribute, IClientValidatable
          {
              private const string defaultErrorMessage = "'{0}' must be at least {1} characters long.";
              private readonly int minRequiredPasswordLength = Membership.Provider.MinRequiredPasswordLength;
          
              public ValidatePasswordLengthAttribute()
                  : base(defaultErrorMessage)
              {
              }
          
              public override string FormatErrorMessage(string name)
              {
                  return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, minRequiredPasswordLength);
              }
          
              public override bool IsValid(object value)
              {
                  string valueAsString = value as string;
                  return (valueAsString != null && valueAsString.Length >= minRequiredPasswordLength);
              }
          
              public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
              {
                  return new[]
                  {
                      new ModelClientValidationStringLengthRule(FormatErrorMessage(metadata.GetDisplayName()), minRequiredPasswordLength, int.MaxValue)
                  };
              }
          }
            }
          

          来源:https://code.google.com/p/gdnetprojects/source/browse/trunk/Experiments/Common/GDNET.Web.Mvc/Validation/ValidatePasswordLengthAttribute.cs?r=69

          【讨论】:

            猜你喜欢
            • 2016-12-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-02-03
            • 2017-12-16
            • 1970-01-01
            • 1970-01-01
            • 2011-04-04
            相关资源
            最近更新 更多