Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ValidationSummary displays duplicate messages

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:

enter image description here

like image 233
Buh Buh Avatar asked Dec 03 '25 19:12

Buh Buh


2 Answers

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);
    }
}
like image 86
rouen Avatar answered Dec 06 '25 15:12

rouen


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.

like image 29
stuartdotnet Avatar answered Dec 06 '25 16:12

stuartdotnet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!