简体   繁体   English

ASP MVC:自定义验证属性

[英]ASP MVC: Custom Validation Attribute

I'm trying to write my own Custom Validation attribute but I'm having some problems. 我正在尝试编写自己的自定义验证属性,但我遇到了一些问题。

The attribute I'm trying to write is that when a user logs in, the password will be compared against the confirmation password. 我试图写的属性是当用户登录时,密码将与确认密码进行比较。

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;
    }
}

Now my problem is when i'm trying to set the attribute like this in the model file: 现在我的问题是当我试图在模型文件中设置这样的属性时:

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


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

I get the following error: 我收到以下错误:

Error 1 An object reference is required for the non-static field, method, or property 'Project.Data.Models.GebruikerRegistreerModel.ConfirmPassword.get' 错误1非静态字段,方法或属性'Project.Data.Models.GebruikerRegistreerModel.ConfirmPassword.get'需要对象引用

It seems that VS is not accepting the confirmpassword in the PasswordToCompareWith=ConfirmPassword part. 看来,VS是不接受confirmpasswordPasswordToCompareWith=ConfirmPassword一部分。

What am I doing wrong? 我究竟做错了什么?

According to this link http://devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-1 there is an special validation attribute now in MVC3: 根据这个链接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 is a new, very useful validator that is not actually part of System.ComponentModel.DataAnnotations, but has been added to the System.Web.Mvc DLL by the team. CompareAttribute是一个新的,非常有用的验证器,它实际上不是System.ComponentModel.DataAnnotations的一部分,但已被团队添加到System.Web.Mvc DLL中。 Whilst not particularly well named (the only comparison it makes is to check for equality, so perhaps EqualTo would be more obvious), it is easy to see from the usage that this validator checks that the value of one property equals the value of another property. 虽然没有特别好的命名(它唯一的比较是检查相等性,所以也许E​​qualTo会更明显),从使用中很容易看出这个验证器检查一个属性的值等于另一个属性的值。 You can see from the code, that the attribute takes in a string property which is the name of the other property that you are comparing. 您可以从代码中看到,该属性接受一个字符串属性,该属性是您要比较的另一个属性的名称。 The classic usage of this type of validator is what we are using it for here: password confirmation. 这种验证器的经典用法是我们在这里使用它:密码确认。

Sorry to disappoint you but handling such a simple case like yours using Data Annotations could be a pain. 很抱歉让您失望,但使用数据注释处理像您这样的简单案例可能会很痛苦。 You may take a look at this post . 你可以看一下这篇文章

I don't know why this is made out to be such a big deal, just do this: 我不知道为什么这是一个大问题,只需这样做:

[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;
    }
}

Now all you need to do is add [ComparePassword] to your password property, nothing to pass... simple and fairly clean 现在您需要做的就是将[ComparePassword]添加到您的密码属性中,无需通过......简单而且相当干净

FoolProof http://foolproof.codeplex.com/ seems to be the best solution. 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; }
}

It is better than suggested PropertiesMustMatchAttribute as it adds the validation error for the "RetypePassword' instead of the global model level as PropertiesMustMatchAttribute does. 它比建议的PropertiesMustMatchAttribute更好,因为它为“RetypePassword”而不是像PropertiesMustMatchAttribute那样添加了全局模型级别的验证错误。

you need a STATIC method in your case: EXAMPLE: 在你的情况下你需要一个STATIC方法:例子:

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

just as an example: 仅作为一个例子:

 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)
        };
    }
}
  }

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

You can't pass a reference type to an attribute unless you do some rather lame reflection code. 除非您执行一些相当蹩脚的反射代码,否则不能将引用类型传递给属性。

In this situation, I would think creating a custom model binder would be a better idea and then checking the Password and ComparePassword at that point. 在这种情况下,我认为创建自定义模型绑定器会更好,然后在此时检查密码和ComparePassword。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM