I am surprised how much work is involved in MVC to check if at least one of 2 fields has been entered. My solution is derived from a book, you may recognise it! What does not exist in the book is a way to display the error message. So how do I do that? In global.asax, Application_Start I put; ModelValidatorProviders.Providers.Add(new CustomValidatorProvider());
I set up the attribute as follows; private sealed class Metadata { [DisplayName("Client Order Instruction")] [MustExistProperty("ClientOrderNumber")] public string InstructionWithoutClientOrder { get; set; }
The attribute is defined as follows; public class MustExistPropertyAttribute : Attribute { public readonly string OtherProperty;
public MustExistPropertyAttribute(string otherProperty)
{
OtherProperty = otherProperty;
}
}
public class MustExistPropertyValidator : ModelValidator
{
private readonly string OtherProperty;
public MustExistPropertyValidator(ModelMetadata metadata,
ControllerContext context, string otherProperty)
: base(metadata, context)
{
this.OtherProperty = otherProperty;
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
if (Metadata.Model == null)
yield break;
var propertyInfo = container.GetType().GetProperty(OtherProperty);
if (propertyInfo == null)
throw new InvalidOperationException("Unknown property:" + OtherProperty);
var valueToCompare = propertyInfo.GetValue(container, null);
if (Metadata.Model.ToString().Trim().Length + valueToCompare.ToString().Trim().Length == 0)
{
yield return new ModelValidationResult
{ Message = "You must enter either this value or " + this.OtherProperty };
}
}
}
public class CustomValidatorProvider : AssociatedValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(
ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
foreach (var attrib in attributes.OfType<MustExistPropertyAttribute>())
yield return new MustExistPropertyValidator(metadata, context, attrib.OtherProperty);
}
}