I am trying to validate that either of 2 textbox fields in my view have a value supplied. I made this Model Validator:
public class RequireEitherValidator : ModelValidator
{
private readonly string compareProperty;
private readonly string errorMessage;
public RequireEitherValidator(ModelMetadata metadata,
ControllerContext context, string compareProperty, string errorMessage)
: base(metadata, context)
{
this.compareProperty = compareProperty;
this.errorMessage = errorMessage;
}
public override IEnumerable<ModelValidationResult> Validate(object container)
{
if (Metadata.Model == null)
yield break;
var propertyInfo = container.GetType().GetProperty(compareProperty);
if (propertyInfo == null)
throw new InvalidOperationException("Unknown property:" + compareProperty);
string valueToCompare = propertyInfo.GetValue(container, null).ToString();
if (string.IsNullOrEmpty(Metadata.Model.ToString()) && string.IsNullOrEmpty(valueToCompare))
yield return new ModelValidationResult
{
Message = errorMessage
};
}
}
This validation logic never gets hit and I think it's because no value gets supplied to the textboxes.
In case you need it, here's the provider and attribute I created along with the attribute usage:
public class MyValidatorProvider : AssociatedValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(
ModelMetadata metadata, ControllerContext context,
IEnumerable<Attribute> attributes)
{
foreach (var attrib in attributes.OfType<RequireEitherAttribute>())
yield return new RequireEitherValidator(metadata, context,
attrib.CompareProperty, attrib.ErrorMessage);
}
}
public class RequireEitherAttribute : Attribute
{
public readonly string CompareProperty;
public string ErrorMessage { get; set; }
public RequireEitherAttribute(string compareProperty)
{
CompareProperty = compareProperty;
}
}
public class StudentLogin
{
[DisplayName("Last Name")]
[Required(ErrorMessage = "You must supply your last name.")]
public string LastName { get; set; }
[DisplayName("Student ID")]
[RegularExpression(@"^\d{1,8}$", ErrorMessage = "Invalid Student ID")]
[RequireEither("SSN", ErrorMessage = "You must supply your student id or social security number.")]
public int? StudentId { get; set; }
[DisplayName("Social Security Number")]
[RegularExpression(@"^\d{9}|\d{3}-\d{2}-\d{4}$", ErrorMessage = "Invalid Social Security Number")]
public string SSN { get; set; }
}
My view:
<%Html.BeginForm(); %>
<p>
Please supply the following information to login:</p>
<ol class="standard">
<li>
<p>
<%=Html.LabelFor(x => x.LastName) %><br />
<%=Html.TextBoxFor(x => x.LastName)%>
<%=Html.ValidationMessageFor(x => x.LastName) %></p>
</li>
<li>
<p>
<%=Html.LabelFor(x => x.StudentId) %><br />
<%=Html.TextBoxFor(x => x.StudentId) %>
<%=Html.ValidationMessageFor(x => x.StudentId) %></p>
<p style="margin-left: 4em;">
- OR -</p>
<p>
<%=Html.LabelFor(x => x.SSN)%><br />
<%=Html.TextBoxFor(x => x.SSN) %>
<%=Html.ValidationMessageFor(x => x.SSN) %>
</p>
</li>
</ol>
<%=Html.SubmitButton("submit", "Login") %>
<%Html.EndForm(); %>