Rectangle 27 18

You can specify error messages against the properties or against the model. Those specified against the model are displayed using the validationsummary().

The bool property indicates if you would like to display the validation summary error messages at the same time as displaying the property error messages. If you choose not to then the property error messages will be displayed to the user first. Then, when the user has resolved all of those error messages, the summary error messages will be displayed after.

If the bool parameter is true then only model-level errors are displayed. If the parameter is false then all errors are shown.

Could you explain the difference between model-level errors and property-level errors?

Page 103 of Professional ASP.NET MVC 4 might help to clarify this.

asp.net mvc - @Html.ValidationSummary(true) - What's the true do? - St...

asp.net-mvc asp.net-mvc-3
Rectangle 27 5

If ValidationSummary is used with the ExcludePropertyErrors argument set to True, it will look for errors in the model state using a key equal to ViewData.TemplateInfo.HtmlFieldPrefix. By default this is String.Empty.

If you have a view model which exposes your business model, something like this:

namespace ValidationSummary.Models
{
   using System;
   using System.Collections.Generic;
   using System.ComponentModel.DataAnnotations;

   public class TradeModel : IValidatableObject
   {
      public DateTime StartDate { get; set; }

      public DateTime EndDate { get; set; }

      public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
      {
         List<ValidationResult> validationResults = new List<ValidationResult>();

         if (EndDate < StartDate)
         {
            validationResults.Add(new ValidationResult("End date must not be before start date"));
         }

         return validationResults;
      }
   }
}

namespace ValidationSummary.ViewModels
{
   public class Trade
   {
      public Trade()
      {
         this.TradeModel = new Models.TradeModel();
      }

      public Models.TradeModel TradeModel { get; private set; }
   }
}

When the validation takes place, errors (ValidationResults) that are added at the model-level (where there is no further argument to the ValidationResult constructor that takes the property name(s), are added to the ModelState with a prefix of the property name of the view model - in this example "TradeModel".

There are a few ways around this that we're currently considering.

  • Do not expose the business model outside the view model. This essentially involves binding to the view model, rather than to the business model of the view model. This could be done two ways: make the view model a subclass of the business model; or duplicate properties from business model to the view model. I prefer the former.
  • Write code to copy model-level errors into a new ModelState dictionary key of String.Empty. Unfortunately this might not be possible to do elegantly since the property name of the view model that exposes the business model is what's used as the key. This may be different per controller/view-model.

Use the following in the view. This will display error messages that are for the business model. Essentially this pretending that model-level errors for the business model are in fact property errors. The display of these is not the same as for ValidationSummary, but maybe this could be cured with CSS:

Subclass ValidationSummary. This would involve changing it so that it knows which keys in ModelState refer to business model properties of the view model.

c# - MVC ValidationSummary ignores model level validation errors when ...

c# asp.net asp.net-mvc-3 validationsummary
Rectangle 27 1

You need to remove the Html.ValidationMessageFor(...) lines. These are the inline validation messages and are unrelated to ValidationSummary.

@{var bool bInline = true;}
@Html.ValidationSummary(bInline)

@Html.LabelFor(m => m.MyField)
@Html.EditorFor(m => m.MyField)
@if (bInline)
{
    @Html.ValidationMessageFor(m => m.MyField)
}

See edit. I've added an example of how to make it optional.

asp.net mvc 3 - MVC3 ValidationSummary(No) not suppressing detail erro...

asp.net-mvc-3
Rectangle 27 2

Here is a code sample that uses RequiredFieldValidator together with CustomValidator. It validates both fields, as well as when one of them fails, and displays the error messages in the ValidationSummary.

The CustomValidator has OnServerValidate function in the code behind.

<form id="form1" runat="server">
                <div>
                    <label>Name:</label>
                    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" EnableClientScript="false"
                    ControlToValidate="TextBox1" ErrorMessage="The 'Name' field cannot be empty!" Text="*" ForeColor="Red" 
                    Display="Dynamic"></asp:RequiredFieldValidator>

                    <br /><br />

                    <label>Number:</label>
                    <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
                    <asp:CustomValidator ID="CustomValidator1" runat="server" ValidateEmptyText="true"
                    ControlToValidate="TextBox2" ErrorMessage="The 'Number' field must be exactly 5 digits!" Text="*" ForeColor="Red" 
                    Display="Dynamic" onservervalidate="CustomValidator1_ServerValidate"></asp:CustomValidator>

                    <asp:ValidationSummary ID="ValidationSummary1" runat="server" HeaderText="Please check the following fields:" ForeColor="Red" DisplayMode="BulletList" />

                    <br />

                    <asp:Button ID="Button1" runat="server" Text="Submit" />
                </div>
            </form>

and the validation function in .aspx.cs file:

protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args)
            {
                if (args.Value.Length < 5 || args.Value.Length > 5)
                {
                    args.IsValid = false;
                }
                else
                {
                    args.IsValid = true;
                }
            }

In order to be able to display both error messages, and not only the RequiredFieldValidator's, its property 'EnableClientScript' should be set to false.

requiredfieldvalidator - Asp.net Required Field Validator Issue - Stac...

asp.net requiredfieldvalidator
Rectangle 27 0

Believe me I achieved this without doing any of these suggestions. I just set validation group of my button and all the validators to the same value. That's it.Let me remind you the case: I have a two updatepanels.Validators of the controls on the first panel are in a seperate div, which is not contained in either of the panels. The second update panel has only one control to validate so I've put its validator to the same panel. And I have a button that's completely apart from all these. When I click the buton I can get all the validation messages summarized in the validationsummary. However a very strange thing still remains a secret: As I said validators of the first panel controls are outside that panel and they work pretty well. But if I take the only validator from the second update panel and put it among the other validators I don't get that single validator's message. I'm almost sure that this is a bug in Visual Studio as I've witnessed many things like this.

asp.net - Validating controls in an UpdatePanel with a button outside ...

asp.net validation updatepanel
Rectangle 27 0

I also had duplicate messages showing up and found the following javascript solution that worked for me.

<script language="javascript" type="text/javascript">

function RemoveValidationDuplicates(validationGroup) {
    Page_ClientValidate(validationGroup);

    if (typeof (Page_ValidationSummaries) == "undefined")
        return;
    var summary, sums, s;
    for (sums = 0; sums < Page_ValidationSummaries.length; sums++) {
        summary = Page_ValidationSummaries[sums];
        summary.style.display = "none";
        if (!Page_IsValid) {

            if (summary.showsummary != "False") {
                summary.style.display = "";
                if (typeof (summary.displaymode) != "string") {
                    summary.displaymode = "BulletList";
                }
                switch (summary.displaymode) {
                    case "List":
                        headerSep = "<br/>";
                        first = "";
                        pre = "";
                        post = "<br/>";
                        final = "";
                        break;
                    case "BulletList":
                    default:
                        headerSep = "";
                        first = "<ul>";
                        pre = "<li>";
                        post = "</li>";
                        final = "</ul>";
                        break;
                    case "SingleParagraph":
                        headerSep = " ";
                        first = "";
                        pre = "";
                        post = " ";
                        final = "<br/>";
                        break;
                }
                s = "";
                if (typeof (summary.headertext) == "string") {
                    s += summary.headertext + headerSep;
                }
                s += first;

                for (i = 0; i < Page_Validators.length; i++) {
                    if (!Page_Validators[i].isvalid && typeof (Page_Validators[i].errormessage) == "string") {
                        var tempstr = pre + Page_Validators[i].errormessage + post;
                        var isExist = s.search(tempstr);
                        if (isExist == -1)
                            s += pre + Page_Validators[i].errormessage + post;
                    }
                }
                s += final;
                summary.innerHTML = s;
                window.scrollTo(0, 0);
            }
        }
    }
}    
</script>

The summary and the validators share a ValidationGroup which serves as input for the call to RemoveValidationDuplicates when the OnClientClick of the submit button is fired:

<div>
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" ValidationGroup="validationGroupName"/>
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ControlToValidate="TextBox1" ID="RequiredFieldValidator1" runat="server" ErrorMessage="RequiredFieldValidator" ValidationGroup="validationGroupName"></asp:RequiredFieldValidator>
    <br/>
    <asp:TextBox ID="TextBox2" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ControlToValidate="TextBox2" ID="RequiredFieldValidator2" runat="server" ErrorMessage="RequiredFieldValidator" ValidationGroup="validationGroupName"></asp:RequiredFieldValidator>
    <br/>
    <asp:TextBox ID="TextBox4" runat="server"></asp:TextBox>
    <asp:RequiredFieldValidator ControlToValidate="TextBox4" ID="RequiredFieldValidator4" runat="server" ErrorMessage="RequiredFieldValidator1" ValidationGroup="validationGroupName"></asp:RequiredFieldValidator>
    <br/>
    <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" OnClientClick="RemoveValidationDuplicates('validationGroupName')"/>
</div>

Update March 23rd: changed the javascript function to make it reusable, removed some redundant code.

asp.net - Show only unique error messages in ValidationSummary - Stack...

asp.net .net validation webforms validationsummary
Rectangle 27 0

I assume that you have a ValidationSummary control similar to this:

<asp:ValidationSummary runat="server" ForeColor="Red" ValidationGroup="EmployerRegister" />

If any of your validators has client-side validation enabled (EnableClientScript="true", the default value), it will prevent the postback when the client validation fails, so that server-side validation will not be performed. In your current code, the RegularExpressionValidator has client-side validation enabled (not explicitly disabled, in fact); if it fails, the server-side validation for the required fields is not performed and the other error messages are not displayed.

You could disable the client-side validation for all your validators. The message would appear for all of them (if appropriate) every time you submit the form.

Another reasonable approach could be to enable the client-side validator for the most basic requirements, and disable it for the CustomValidator. The more advanced validation does not make much sense if the e-mail is empty or not valid in the first place.

<asp:RequiredFieldValidator ID="uxEmployerNameValReq" EnableClientScript="true" ... />
<asp:RequiredFieldValidator ID="uxEmailValReq" EnableClientScript="true" ... />
<asp:RegularExpressionValidator ID="uxEmailExprVal" EnableClientScript="true" ... />
<asp:CustomValidator ID="uxEmailValUnique" EnableClientScript="false" ... />

validation - ASP.NET Required Field Validator & Custom Validator not w...

asp.net validation requiredfieldvalidator customvalidator