Validation Summary for Lists using Data Annotations with MVC
- by David Liddle
I currently use a custom method to display validation error messages for lists but would like to replace this system for using with Data Annotations.
In summary on validation of my form, I want to display "*" next to each input that is incorrect and also provide a Validation Summary at the bottom that relates each error message to the particular item in the list.
e.g. say if validation failed on the 2nd list item on a Name input box and the 4th item on an Address input box the validation summary would display
[2] Name is invalid
[4] Address is invalid
Please ignore if there are mistakes in the code below. I'm just writing this as an example.
The code below shows how I was able to do it using my custom version of adding model errors but was wondering how to do this using Data Annotations?
//Domain Object
public class MyObject
{
public int ID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public bool IsValid
{
get { return (GetRuleViolations().Count() == 0); }
}
public void IEnumerable<RuleViolation> GetRuleViolations()
{
if (String.IsNullOrEmpty(Name))
yield return new RuleViolation(ID, "Name", "Name is invalid");
if (String.IsNullOrEmpty(Address))
yield return new RuleViolation(ID, "Address", "Address is invalid");
yield break;
}
}
//Rule Violation
public class RuleViolation
{
public int ID { get; private set; }
public string PropertyName { get; private set; }
public string ErrorMessage { get; private set; }
}
//View
<% for (int i = 0; i < 5; i++) { %>
<p>
<%= Html.Hidden("myObjects[" + i + "].ID", i) %>
Name: <%= Html.TextBox("myObjects[" + i + "].Name") %> <br />
<%= Html.ValidationMessage("myObjects[" + i + "].Name", "*")<br />
Address: <%= Html.TextBox("myObjects[" + i + "].Address") %>
<%= Html.ValidationMessage("myObjects[" + i + "].Address", "*")<br />
</p>
<% } %>
<p><%= Html.ValidationSummary() %>
//Controller
public ActionResult MyAction(IList<MyObject> myObjects)
{
foreach (MyObject o in myObjects)
{
if (!o.IsValid)
ModelState.AddModelErrors(o.GetRuleViolations(), o.GetType().Name);
}
if (!Model.IsValid)
{
return View();
}
}
public static class ModelStateExtensions
{
public static void AddModelError(this ModelStateDictionary modelState,
RuleViolation issue, string name)
{
string key = String.Format("{0}[{1}].{2}", name, issue.ID, issue.PropertyName);
string error = String.Format("[{0}] {1}", (issue.ID + 1), issue.ErrorMessage);
//above line determines the [ID] ErrorMessage to be
//displayed in the Validation Summary
modelState.AddModelError(key, error);
}