我正在尝试编写自己的自定义验证属性,但我遇到了一些问题。
我想写的属性是当用户登录时,密码将与确认密码进行比较。
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不接受confirmpassword
部分中的PasswordToCompareWith=ConfirmPassword
。
我做错了什么?
答案 0 :(得分:18)
根据此链接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会 更明显),很容易看出来 此验证程序检查的用法 一个属性的值等于 另一个财产的价值。您可以 从代码中看,该属性 接受一个字符串属性 其他属性的名称 你在比较。经典用法 这类验证器就是我们的 正在使用它:密码 确认。
答案 1 :(得分:4)
很抱歉让您失望,但使用数据注释处理像您这样的简单案例可能会很痛苦。您可以查看this post。
答案 2 :(得分:1)
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那样添加了全局模型级别的验证错误。
答案 3 :(得分:1)
我不知道为什么这是一个大问题,只需这样做:
[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]
添加到您的密码属性中,无需通过......简单而且相当干净
答案 4 :(得分:0)
除非你做一些相当蹩脚的反射代码,否则你不能将引用类型传递给属性。
在这种情况下,我认为创建自定义模型绑定器会更好,然后检查密码和ComparePassword。
答案 5 :(得分:0)
你需要一个STATIC方法: 示例:
public static ValidationResult ValidateFrequency( double frequency, ValidationContext context )
{
if( context == null )
{
return ( ValidationResult.Success );
}
}
答案 6 :(得分:0)
仅举例:
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)
};
}
}
}