A bit late for the party, but here is the implementation I just wrote that also includes support for client-side validation using the IClientValidatable interface. You could also use Darin Dimitrovβs answer as a starting point, I already had some of this.
Server side validation:
//Create your custom validation attribute [AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)] public class CompareStrings : ValidationAttribute, IClientValidatable { private const string _defaultErrorMessage = "{0} must match {1}"; public string OtherPropertyName { get; set; } public bool IgnoreCase { get; set; } public CompareStrings(string otherPropertyName) : base(_defaultErrorMessage) { if (String.IsNullOrWhiteSpace(otherPropertyName)) throw new ArgumentNullException("OtherPropertyName must be set."); OtherPropertyName = otherPropertyName; } public override string FormatErrorMessage(string name) { return String.Format(ErrorMessage, name, OtherPropertyName); } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { string otherPropVal = validationContext.ObjectInstance.GetType().GetProperty(OtherPropertyName).GetValue(validationContext.ObjectInstance, null) as string; //Convert nulls to empty strings and trim spaces off the result string valString = (value as string ?? String.Empty).Trim(); string otherPropValString = (otherPropVal ?? String.Empty).Trim(); bool isMatch = String.Compare(valString, otherPropValString, IgnoreCase) == 0; if (isMatch) return ValidationResult.Success; else return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); }
Client side validation
//...continuation of CompareStrings class public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { return new[] { new ModelClientValidationCompareStringsRule(FormatErrorMessage(metadata.GetDisplayName()), OtherPropertyName, IgnoreCase) }; } }
Define a ModelClientValidationCompareStringsRule that is used (above) to pass the attribute properties to the client-side script.
public class ModelClientValidationCompareStringsRule : ModelClientValidationRule { public ModelClientValidationCompareStringsRule(string errorMessage, string otherProperty, bool ignoreCase) { ErrorMessage = errorMessage;
Javascript:
(function ($) {
Usage is standard:
public string EmailAddress { get; set; } [CompareStrings("EmailAddress", ErrorMessage = "The email addresses do not match", IgnoreCase=true)] public string EmailAddressConfirm { get; set; }
This connects to an unobtrusive verification infrastructure, so it should already be installed and working. At the time of this writing, I am on Microsoft.jQuery.Unobtrusive.Validation v 3.0.0.