Validate if either or both of two fields has been provided, as a ValidationAttribute I have a binding model where at least one of two fields must be specified. I can't just set them both as [Required]. Here is what I came up with:

using System;
using System.ComponentModel.DataAnnotations;

namespace MyApp.Utils.DataAnnotations
{
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
    public class EitherRequiredAttribute : ValidationAttribute
    {
        private readonly string _field1;
        private readonly string _field2;

        public EitherRequiredAttribute(string field1, string field2) =&gt; (_field1, _field2) = (field1, field2);

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var property1 = validationContext.ObjectType.GetProperty(_field1);
            if (property1 == null)
                return new ValidationResult(string.Format("Unknown property: {0}", _field1), new[] { _field1 });
            var property2 = validationContext.ObjectType.GetProperty(_field2);
            if (property2 == null)
                return new ValidationResult(string.Format("Unknown property: {0}", _field2), new[] { _field2 });

            var value1 = property1.GetValue(validationContext.ObjectInstance);

            if (value1 != null)
                return ValidationResult.Success;

            var value2 = property2.GetValue(validationContext.ObjectInstance);

            if (value2 != null)
                return ValidationResult.Success;

            return new ValidationResult(string.Format("Either or both of \"{0}\" and \"{1}\" are required", _field1, _field2), new[] { _field1, _field2 });
        }
    }
}


Use case:

[EitherRequired("A", "B")]
public class SomeModel
{
    public int? A {get; set;}
    public int? B {get; set;}
}
Fields and properties are different things. You are mixing them up: the naming in the attribute code suggests that you want to operate on fields, but the use site is supplying property names. The naming of field1 and field2 should be changed to propertyName1 and propertyName2 respectively.

Don't forget your BindingFlags! Right now your code will look up any public property with the given name, including static properties. You probably only want public instance properties:

var property1 = validationContext.ObjectType.GetProperty(_field1, BindingFlags.Instance | BindingFlags.Public);


Depending on your performance constraints, reflection might be too slow for you. If so, it's common practice to cache the results of calls to GetProperty since that information is unchanging at runtime.

It's good practice to use nameof for getting string representations of identifiers, because if SomeModel.A gets renamed then the program won't compile until you also update the attribute argument.

[EitherRequired(nameof(A), nameof(B))]
public class SomeModel
{
    public int? A {get; set;}
    public int? B {get; set;}
}