7

I want to use ComponentModel DataAnnotations validate that at least one of two properties has a value. My model looks like this:

public class FooModel {
   public string Bar1 { get; set; }
   public int Bar2 { get; set; }
}

Basically, I want to validate FooModel so that either Bar1 or Bar2 is required. In other words, you can enter one, or the other, or both, but you can't just leave them both empty.

I would prefer that this worked both for server-side and unobtrusive client-side validation.


EDIT: This may be a possible duplicate, as this looks similar to what I'm looking to do

Community
  • 1
  • 1
Ben Lesh
  • 107,825
  • 47
  • 247
  • 232
  • 3
    That's right custom validator is your friend here. – veblock Mar 05 '12 at 00:31
  • 1
    There is a custom validator called RequiredIf that would solve your problem. – Joe Mar 05 '12 at 00:49
  • @JoeTuskan, you're right, I found [this blog post](http://blogs.msdn.com/b/simonince/archive/2011/02/04/conditional-validation-in-asp-net-mvc-3.aspx) on your guidance and it solves my issue. If you'd like to type up an answer so I could give you credit, that's fine by me. If not, have my +1. – Ben Lesh Mar 05 '12 at 01:49
  • AFAIK that should be solved by using different view models, inheriting common properties from a common parent. https://stackoverflow.com/a/5367788/2157640 https://stackoverflow.com/a/2519618/2157640 – Palec Aug 13 '18 at 08:31

2 Answers2

7

You would need to extend the ValidationAttribute class and over ride the IsValid method, and implement the IClientValidatable if you want to pump custom JavaScript to do the validation. something like below.

[AttributeUsage(AttributeTargets.Property)]
    public sealed class AtLeastOneOrTwoParamsHasValue : ValidationAttribute, IClientValidatable
    {
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var param1 = validationContext.ObjectInstance.GetType().GetProperty("Param1").GetValue(value, null);
            //var param2 = validationContext.ObjectInstance.GetType().GetProperty("Param2").GetValue(value, null);

            //DO Compare logic here.

            if (!string.IsNullOrEmpty(Convert.ToString(param1)))
            {
                return ValidationResult.Success;
            }


            return new ValidationResult("Some Error");
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            //Do custom client side validation hook up

            yield return new ModelClientValidationRule
            {
                ErrorMessage = FormatErrorMessage(metadata.DisplayName),
                ValidationType = "validParam"
            };
        }
    }

Usage:

[AtLeastOneOrTwoParamsHasValue(ErrorMessage="Atleast one param must be specified.")]
Ricky Gummadi
  • 4,559
  • 2
  • 41
  • 67
2

This worked for me, a simple solution, just using .net without any third party: https://stackoverflow.com/a/69621414/6742644

Like this:

public class EditModel
{
    public string ISBN { get; set; }
    public string ISBN13 { get; set; }

   [RegularExpression("True|true", ErrorMessage = "At least one field must be given a value")]    
   public bool Any => ISBN != null || ISBN13 != null;
}

Also good to know is that you can add any attributes to the properties in the model, like MinLength, MaxLength, etc. Just do not add the Required attribute.

  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/30125629) – cse Oct 20 '21 at 07:59