Reputation: 9645
I've got an MVC app which features a DropDownList and TextBox. I'm using MVC validation and I'm happy with it.
At the moment The DropDownList is [Required], but I want to make it so the TextBox can function as an 'other: please specify' style input for the DropDownList.
How do I make it so that the [Required] attribute on the DropDownList is conditional on the TextBox being empty?
This question is similar, but it's over a year old. Anything in the current version of MVC that makes this easy to do?
Upvotes: 3
Views: 928
Reputation: 1039478
It would be pretty easy to write a custom validation attribute:
public class RequiredIfPropertyIsEmptyAttribute : RequiredAttribute
{
private readonly string _otherProperty;
public RequiredIfPropertyIsEmptyAttribute(string otherProperty)
{
_otherProperty = otherProperty;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var property = validationContext.ObjectType.GetProperty(_otherProperty);
if (property == null)
{
return new ValidationResult(string.Format("Unknown property {0}", _otherProperty));
}
var otherPropertyValue = property.GetValue(validationContext.ObjectInstance, null);
if (otherPropertyValue == null)
{
return base.IsValid(value, validationContext);
}
return null;
}
}
then you could have a view model:
public class MyViewModel
{
public string Foo { get; set; }
[RequiredIfPropertyIsEmpty("Foo")]
public string SelectedItemId { get; set; }
public IEnumerable<SelectListItem> Items {
get
{
return new[]
{
new SelectListItem { Value = "1", Text = "item 1" },
new SelectListItem { Value = "2", Text = "item 2" },
new SelectListItem { Value = "3", Text = "item 3" },
};
}
}
}
A controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel());
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
And of course a view:
@model MyViewModel
@using (Html.BeginForm())
{
<div>
@Html.LabelFor(x => x.Foo)
@Html.EditorFor(x => x.Foo)
</div>
<div>
@Html.LabelFor(x => x.SelectedItemId)
@Html.DropDownListFor(x => x.SelectedItemId, Model.Items, "-- select an item --")
@Html.ValidationMessageFor(x => x.SelectedItemId)
</div>
<input type="submit" value="OK" />
}
or you could do as I do: download and use the FluentValidation.NET library, forget about data annotations and write the following validation logic which seems pretty self-explanatory:
public class MyViewModelValidator: AbstractValidator<MyViewModel>
{
public MyViewModelValidator()
{
RuleFor(x => x.SelectedItemId)
.NotEmpty()
.When(x => !string.IsNullOrEmpty(x.Foo));
}
}
Just go ahead and Install-Package FluentValidation.MVC3
and make your life easier.
Upvotes: 8
Reputation: 43107
You can create a ConditionalAttribute.
ASP.net MVC conditional validation
ASP.NET MVC Conditional validation
Upvotes: 1