Data Annotation to validate confirm password

C#asp.netData Annotations

C# Problem Overview


My User model has these data annotations to validate input fields:

[Required(ErrorMessage = "Username is required")]
[StringLength(16, ErrorMessage = "Must be between 3 and 16 characters", MinimumLength = 3)]
public string Username { get; set; }
    
[Required(ErrorMessage = "Email is required"]
[StringLength(16, ErrorMessage = "Must be between 5 and 50 characters", MinimumLength = 5)]
[RegularExpression("^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$", ErrorMessage = "Must be a valid email")]
public string Email { get; set; }

[Required(ErrorMessage = "Password is required"]
[StringLength(255, ErrorMessage = "Must be between 5 and 255 characters", MinimumLength = 5)]
public string Password { get; set; }

[Required(ErrorMessage = "Confirm Password is required"]
[StringLength(255, ErrorMessage = "Must be between 5 and 255 characters", MinimumLength = 5)]
public string ConfirmPassword { get; set; }

However, I'm having trouble working out how to make sure Confirm Password is the same as Password. As far as I know only these validation routines exist: Required, StringLength, Range, RegularExpression.

What can I do here? Thanks.

C# Solutions


Solution 1 - C#

If you are using ASP.Net MVC 3, you can use System.Web.Mvc.CompareAttribute.

If you are using ASP.Net 4.5, it's in the System.Component.DataAnnotations.

[Required(ErrorMessage = "Password is required")]
[StringLength(255, ErrorMessage = "Must be between 5 and 255 characters", MinimumLength = 5)]
[DataType(DataType.Password)]
public string Password { get; set; }

[Required(ErrorMessage = "Confirm Password is required")]
[StringLength(255, ErrorMessage = "Must be between 5 and 255 characters", MinimumLength = 5)]
[DataType(DataType.Password)]
[Compare("Password")]
public string ConfirmPassword { get; set; }

EDIT: For MVC2 Use the below Logic, Use PropertiesMustMatch instead Compare attribute [Below code is copied from the default MVCApplication project template.]

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public sealed class PropertiesMustMatchAttribute : ValidationAttribute
{
    private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";
    private readonly object _typeId = new object();

    public PropertiesMustMatchAttribute(string originalProperty, string confirmProperty)
        : base(_defaultErrorMessage)
    {
        OriginalProperty = originalProperty;
        ConfirmProperty = confirmProperty;
    }

    public string ConfirmProperty { get; private set; }
    public string OriginalProperty { get; private set; }

    public override object TypeId
    {
        get
        {
            return _typeId;
        }
    }

    public override string FormatErrorMessage(string name)
    {
        return String.Format(CultureInfo.CurrentUICulture, ErrorMessageString,
            OriginalProperty, ConfirmProperty);
    }

    public override bool IsValid(object value)
    {
        PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(value);
        object originalValue = properties.Find(OriginalProperty, true /* ignoreCase */).GetValue(value);
        object confirmValue = properties.Find(ConfirmProperty, true /* ignoreCase */).GetValue(value);
        return Object.Equals(originalValue, confirmValue);
    }
}

Solution 2 - C#

You can use the compare annotation to compare two values, and if you need to make sure it isn't persisted anywhere downstream (For example if you are using EF) You can also add NotMapped to ignore any entity->DB mapping

For a full list of data annotations available, see here:

https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations(v=vs.110).aspx

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

[Required]
[DataType(DataType.Password)]
[Compare("Password")]
[NotMapped]
public string ConfirmPassword { get; set; }

Solution 3 - C#

Other data annotations are optional. You can add those according to your requirement but you need to do this to implement password comparison operation.

[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

[Required]
[DataType(DataType.Password)]
[Compare("Password")]
public string ConfirmPassword { get; set; }

Solution 4 - C#

For Blazor EditForm validation

The above answers didn't work for me as it was not displaying any message.


    [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
    public sealed class PropertyMustMatchAttribute : ValidationAttribute
    {
        private const string _defaultErrorMessage = "'{0}' and '{1}' do not match.";

        public PropertyMustMatchAttribute(string originalProperty)
            : base(_defaultErrorMessage)
        {
            OriginalProperty = originalProperty;
        }
        
        public string OriginalProperty { get; }

        protected override ValidationResult IsValid(object value,
            ValidationContext validationContext)
        {
            var properties = TypeDescriptor.GetProperties(validationContext.ObjectInstance);
            var originalProperty = properties.Find(OriginalProperty, false);
            var originalValue = originalProperty.GetValue(validationContext.ObjectInstance);
            var confirmProperty = properties.Find(validationContext.MemberName, false);
            var confirmValue = confirmProperty.GetValue(validationContext.ObjectInstance);
            if (originalValue == null)
            {
                if (confirmValue == null)
                {
                    return ValidationResult.Success;
                }

                return new ValidationResult(ErrorMessage,
                    new[] { validationContext.MemberName });
            }

            if (originalValue.Equals(confirmValue))
            {
                return ValidationResult.Success;
            }

            return new ValidationResult(ErrorMessage,
                new[] { validationContext.MemberName });
        }
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJames DawsonView Question on Stackoverflow
Solution 1 - C#Prasad KanaparthiView Answer on Stackoverflow
Solution 2 - C#Mahadi HasanView Answer on Stackoverflow
Solution 3 - C#Khursand KousarView Answer on Stackoverflow
Solution 4 - C#FabView Answer on Stackoverflow