If two of textboxes fail validation at once then the ValidationSummary displays the same message twice.
Am I doing something wrong? Or is there a setting I can change to hide duplicate messages?
I have broken it down to the simplest example:
View:
@model MyModel
@Html.ValidationSummary()
@Html.TextBoxFor(model => model.A)
@Html.TextBoxFor(model => model.B)
Model:
public class MyModel : IValidatableObject
{
public int A { get; set; }
public int B { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
//Some logic goes here.
yield return new ValidationResult("Validation failed", new[] { "A", "B" });
}
}
Result:
They are not duplicate from the point of view of ValidationSummary - you are assigning model state error to both fields A and B, so there must be 2 errors in validation summary. It doesnt "know" that they are the same.
Easy solutions :
- assign model only to one of them
- exclude property-assigned errors from summary - Html.ValidationSummary(true)
A little bit harder solution :
- make your own ValidationSummary helper, call standard validation summary logic in it, and then filter the result in "select distinct" way (linq is your friend here).
EDIT:
something like this for example :
public static class ValidationExtensions
{
public static MvcHtmlString FilteredValidationSummary(this HtmlHelper html)
{
// do some filtering on html.ViewData.ModelState
return System.Web.Mvc.Html.ValidationExtensions.ValidationSummary(html);
}
}
Whack this is your View
<ul class="validation-summary-errors">
@{
string errorMessage = "", previousError = "";
foreach (ModelState modelState in (ViewContext.ViewData.ModelState.Values)){
foreach (ModelError modelError in modelState.Errors)
{
errorMessage = modelError.ErrorMessage;
if (errorMessage != previousError)
{
<li>@modelError.ErrorMessage</li>
previousError = modelError.ErrorMessage;
}
}
}
}
</ul>
You might be able to improve this as it only works when 2 consecutive errors are the same, if it jumbles the order this might not work, but this will start you off. I suppose you could build an array of error messages and check the error off it each run through, but this solution seems to work most of the time.
ValidationSummary
method returns property-level and model-level errors. It just enumerates all validation messages if you don't specify any arguments.
You can: 1) Use different message for field A and B
// logic here
yield return new ValidationResult("Validation failed for left field", new[] { "A" });
// logic here
yield return new ValidationResult("Validation failed for right field", new[] { "B" });
or, in your view
2) Call ValidationSummary with excludePropertyErrors argument set to true - ValidationSummary(true)
. And place call Html.ValidationMessage[For]
near each of your fields.
UPDT: ... and third case:
In your model add common message (model-level):
//logic here
yield return new ValidationResult("Validation failed");
yield return new ValidationResult("any text or empty string", new[] { "A", "B" });
In your view exclude property messages but don't add ValidationMessage for fields:
@model MyModel
@Html.ValidationSummary(true)
@Html.TextBoxFor(model => model.A)
@Html.TextBoxFor(model => model.B)
So you'll get single message and both red boxes.
来源:https://stackoverflow.com/questions/7766749/validationsummary-displays-duplicate-messages