ASP MVC: Custom Validation Attribute

I am trying to write my own Custom Validation attribute, but I am having some problems.

The attribute I'm trying to write is that when a user logs in, the password will be compared with 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 that I am trying to set such an attribute 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 a non-static field, method, or property 'Project.Data.Models.GebruikerRegistreerModel.ConfirmPassword.get'

It seems that VS is not accepting confirmpassword in the PasswordToCompareWith=ConfirmPassword .

What am I doing wrong?

+7
c # validation asp.net-mvc attributes asp.net-mvc-2
source share
7 answers

Sorry to disappoint you, but handling a simple case like yours using data annotations can be a pain. You can take a look at this post .

+4
source share

According to this link http://devtrends.co.uk/blog/the-complete-guide-to-validation-in-asp.net-mvc-3-part-1 , MVC3 now has a special validation attribute:

 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 the System.ComponentModel.DataAnnotations, but has been added to the System.Web.Mvc DLL from the command. while not particularly well-named (the only comparison he makes is to verify equality, so maybe EqualTo will be more obvious), it is easy to see from the use that this validator checks that the value of one property is equal to the value of another property. You can see from the code that the attribute accepts a string property, which is the name of another property that you are comparing. The classic use of this validator is that we use it here: password confirmation.

+18
source share

I don't know why this is done to be such a big deal, just do the following:

 [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 have to do is add [ComparePassword] to your password, not pass anything ... simple and pretty clean.

+2
source share

FoolProof http://foolproof.codeplex.com/ seems like the best solution.

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

This is better than the proposed PropertiesMustMatchAttribute property, because it adds a validation error for "RetypePassword" instead of the global model level, as the PropertiesMustMatchAttribute property does.

+1
source share

You cannot pass a reference type to an attribute unless you make some fairly weak reflection code.

In this situation, I would have thought that creating a custom middleware would be a better idea, then checking the password and ComparePassword at this point.

0
source share

you need a STATIC method in your case: EXAMPLE:

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

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

0
source share

All Articles