I got a similar problem and solved it using a custom attribute.
Below you can find the ViewModel, the View and the Attribute.
The ViewModel
public class TheViewModel{
[Display(Name = "YourOtherFieldDisplayName", ResourceType = typeof(YourResourceFile))]
public string YourOtherField { get; set; }
[Display(Name = "YourFieldDisplayName", ResourceType = typeof(YourResourceFile))]
[RequiredIf("TheOtherField", true, ErrorMessageResourceName = "FieldRequired", ErrorMessageResourceType = typeof(YourResourceFile))]
public string YourField { get; set; }
}
The View
@Html.LabelFor(model => model.YourOtherField)
@Html.CheckBoxFor(model => model.YourOtherField)
@Html.LabelFor(model => model.YourField)
@Html.TextBoxFor(model => model.YourField)
@Html.ValidationMessageFor(model => model.YourField)
The Attribute
namespace YOURNAMESPACE.attributes
{
public class RequiredIfAttribute : ValidationAttribute, IClientValidatable
{
private RequiredAttribute _innerAttribute = new RequiredAttribute();
public string DependentProperty { get; set; }
public object TargetValue { get; set; }
public RequiredIfAttribute(string dependentProperty, object targetValue)
{
this.DependentProperty = dependentProperty;
this.TargetValue = targetValue;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var containerType = validationContext.ObjectInstance.GetType();
var field = containerType.GetProperty(this.DependentProperty);
if (field != null)
{
var dependentvalue = field.GetValue(validationContext.ObjectInstance, null);
// compare the value against the target value
if ((dependentvalue == null && this.TargetValue == null) ||
(dependentvalue != null && dependentvalue.Equals(this.TargetValue)))
{
if (!_innerAttribute.IsValid(value))
return new ValidationResult(this.ErrorMessage, new[] { validationContext.MemberName });
}
}
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
var rule = new ModelClientValidationRule()
{
ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
ValidationType = "requiredif",
};
string depProp = BuildDependentPropertyId(metadata, context as ViewContext);
string targetValue = (this.TargetValue ?? "").ToString();
if (this.TargetValue.GetType() == typeof(bool))
targetValue = targetValue.ToLower();
rule.ValidationParameters.Add("dependentproperty", depProp);
rule.ValidationParameters.Add("targetvalue", targetValue);
yield return rule;
}
private string BuildDependentPropertyId(ModelMetadata metadata, ViewContext viewContext)
{
// build the ID of the property
string depProp = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(this.DependentProperty);
var thisField = metadata.PropertyName + "_";
if (depProp.StartsWith(thisField))
depProp = depProp.Substring(thisField.Length);
return depProp;
}
}
}
I hope this can help you