-1

I have added a CustomValidator to my page that validates the input on the server side. The validation works OK and shows the error message on screen when it is invalid but if I change it to show inside the validationsummary the page sets to isvalid=false but the validationsummary never shows.

I also have other validators (RegularExpression, RequiredField) on screen which work fine until I change the view mode of the CustomValidator, at which point they don't show either.

I have tried all existing threads including this one(below) but it the suggestion is to use an update panel as a wrapper. The problem is that you can't include the controls within it so I don't know exactly how to test the suggestion:

Why The error message for custom validator is not shown in message box?

This is the HTML code:

<asp:CustomValidator ID="validProductCode" runat="server"
    ControlToValidate="txtProductCode"
    OnServerValidate="ValidateProductCode"
    ErrorMessage="The product code entered is invalid"
    Display="None" 
    ValidationGroup="IWS"/>

<asp:ValidationSummary ID="ValidationSummary1" runat="server" ShowMessageBox="True" ShowSummary="False" ValidationGroup="IWS" />

This is the C#

protected void ValidateProductCode(object source, ServerValidateEventArgs args)
{
    try
    {
        using (SqlConnection conn = new SqlConnection(GetConnection.GetConnectionString()))
        using (SqlCommand sqlComm = new SqlCommand("PL_ProductCodes_FillScreen", conn))
        {
            sqlComm.Parameters.AddWithValue("@SiteID", ddlSiteId.SelectedValue);
            sqlComm.Parameters.AddWithValue("@ProductCode", txtProductCode.Text);
            sqlComm.Parameters.AddWithValue("@IsOntext", 1);

            sqlComm.CommandType = CommandType.StoredProcedure;

            SqlDataAdapter da = new SqlDataAdapter(sqlComm);
            DataSet ds = new DataSet();
            da.Fill(ds);

            args.IsValid = ds.Tables[0].Rows.Count != 0;
        }
    }
    catch (SqlException ex)
    {
        ExceptionHandling.SQLException(ex, constPageID, constIsSiteSpecific);
    }
}
Community
  • 1
  • 1
connersz
  • 1,153
  • 3
  • 23
  • 64
  • The other validators have ValidationGroup = "IWS"? Have you also set this ValidationGroup on the control (Button, LinkButton, etc,) that launch the validation? – tezzo Aug 05 '14 at 09:47
  • Yes I have done that. I added tried with and without the group and the outcome was the same. As soon as I change the customvalidator to display=none it all stops. – connersz Aug 05 '14 at 10:22
  • Just found this: http://stackoverflow.com/questions/15518798/validationsummary-doest-show-errors OR THIS http://stackoverflow.com/questions/4308475/custom-validator-firing-but-it-does-not-update-the-validationsummary – jbutler483 Aug 05 '14 at 15:22
  • @jbutler483 That is a completely different issue and different validators. That user is wondering why the message doesn't show but it was because the error message wasn't set. – connersz Aug 05 '14 at 15:24
  • This may be helpful: http://stackoverflow.com/questions/811734/elegant-way-to-make-customvalidator-work-with-validationsummary-messagebox – sr28 Aug 05 '14 at 15:54
  • @sr28 I tried the suggestion in there and still made no difference. – connersz Aug 07 '14 at 09:03
  • have you tried to use [Page.ModelState.AddModelError](http://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=EN-US&k=k(System.Web.ModelBinding.ModelStateDictionary.AddModelError);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.1);k(DevLang-csharp)&rd=true) – fuchs777 Aug 07 '14 at 09:07
  • @fuchs777 No but in what context do I use it and what will it do? – connersz Aug 07 '14 at 09:08
  • @connersz - did you try the second answer by bdukes? – sr28 Aug 07 '14 at 09:08
  • @sr28 Yes but it didn't work. I have never had such a problem with validation but it seems like an issue just trying to get the custom validator into the summary. – connersz Aug 07 '14 at 09:12
  • @connersz anything you add with that function should show up in the ValidationSummary, if you're not in the codebehind page you could try to use (HttpContext.Current.Handler as Page) to access the page. – fuchs777 Aug 07 '14 at 09:13
  • @fuchs777 Do you have an example because I'm struggling to picture it. – connersz Aug 07 '14 at 09:18
  • @connersz little bit much for a comment, but its quite simple [click here](https://github.com/DamianEdwards/WebFormsModelBindingExtensions/blob/master/samples/AspNet.WebForms.ModelBinding.Extensions.Samples/Account/Manage.aspx.cs) – fuchs777 Aug 07 '14 at 09:27

3 Answers3

0

Your problem is that message box from validation summary is shown only on client validation stage in and is called from ValidationSummaryOnSubmit function which is called from Page_ClientValidate function:

function Page_ClientValidate(validationGroup) {
    Page_InvalidControlToBeFocused = null;
    if (typeof(Page_Validators) == "undefined") {
        return true;
    }
    var i;
    for (i = 0; i < Page_Validators.length; i++) {
        ValidatorValidate(Page_Validators[i], validationGroup, null);
    }
    ValidatorUpdateIsValid();
    ValidationSummaryOnSubmit(validationGroup);
    Page_BlockSubmit = !Page_IsValid;
    return Page_IsValid;
}

Here is the snippet from ValidationSummaryOnSubmit which creates a list of error messages and shows alert:

if (summary.showmessagebox == "True") {
    s = "";
    if (typeof(summary.headertext) == "string") {
        s += summary.headertext + "\r\n";
    }
    var lastValIndex = Page_Validators.length - 1;
    for (i=0; i<=lastValIndex; i++) {
        if (!Page_Validators[i].isvalid && typeof(Page_Validators[i].errormessage) == "string") {
            switch (summary.displaymode) {
                case "BulletList":
                default:
                    s += "- " + Page_Validators[i].errormessage;
                    if (i < lastValIndex) {
                        s += "\r\n";
                    }
                    break;
                // Other cases omitted to shorten the snippet
            }
        }
    }
    alert(s);
}

The only way to make it work consistently is to add client validation function for your custom validator and expose the server side validation function as a web service method.

The first step would be to add ClientValidationFunction:

<asp:CustomValidator ID="validProductCode" runat="server"
    ControlToValidate="txtProductCode"
    OnServerValidate="ValidateProductCode"
    ClientValidationFunction="validateProductCode"
    ErrorMessage="The product code entered is invalid"
    Display="None" 
    ValidationGroup="IWS"/>

Second step is to modify validation method on the server side:

protected void ValidateProductCode(object source, ServerValidateEventArgs args)
{
    args.IsValid = ValidateProductCode(ddlSiteId.SelectedValue, txtProductCode.Text);
}

// This method would be called both from the client and server side
[WebMethod]
public static bool ValidateProductCode(string siteId, string productCode)
{
    try
    {
        using (SqlConnection conn = new SqlConnection(GetConnection.GetConnectionString()))
        using (SqlCommand sqlComm = new SqlCommand("PL_ProductCodes_FillScreen", conn))
        {
            sqlComm.Parameters.AddWithValue("@SiteID", siteId);
            sqlComm.Parameters.AddWithValue("@ProductCode", productCode);
            sqlComm.Parameters.AddWithValue("@IsOntext", 1);

            sqlComm.CommandType = CommandType.StoredProcedure;

            SqlDataAdapter da = new SqlDataAdapter(sqlComm);
            DataSet ds = new DataSet();
            da.Fill(ds);

            return ds.Tables[0].Rows.Count != 0;
        }
    }
    catch (SqlException ex)
    {
        ExceptionHandling.SQLException(ex, constPageID, constIsSiteSpecific);
    }

    return false;
}

Third step is to define client script validation function and call the ValidateProductCode method using JQuery.ajax call. Please note that I'm not suggesting using PageMethods here because in validator function we need to do a "synchronous" call to the server and the simple way is to use JQuery:

<script language="javascript">
    function validateProductCode(sender, args) {

        var txtProductCodeClientId = "<%= txtProductCode.ClientID %>";
        var productCodeValue = ValidatorGetValue(txtProductCodeClientId);

        var ddlSiteIdClientId = "<%= ddlSiteId.ClientID %>";
        var ddlSiteIdValue = ValidatorGetValue(ddlSiteIdClientId);

        var isValid;
        var parameters = {
            siteId: ddlSiteIdValue,
            productCode: productCodeValue
        };
        $.ajax({
            type: "POST",
            async: false,
            url: "<%= Page.ResolveUrl("~/<RELATIVE PATH TO YOUR PAGE>/ValidateProductCode") %>",
            data: parameters,
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (response) {
                isValid = response.d;
            },
            error: function() {
                isValid = false;
            }
        });

        args.IsValid = isValid;
    }
</script>

Be warned that this approach will make a call to the server whenever txtProductCode will change its value and lose focus (i.e. onchange event) but this will not automatically update a validation summary so no alert message will be shown. To avoid making such "redundant" calls to server you can clear the onchange event handler for txtProductCode input after the document been loaded.


A quick note if you are using FriendlyUrls:

To make it work you'll need to set FriendlyUrlSettings.AutoRedirectMode to RedirectMode.Off in your routes configuration.

If that's not an option then you'll need to setup asmx service, see Exposing Web Services to Client Script MSDN article.

Alexander Manekovskiy
  • 3,185
  • 1
  • 25
  • 34
  • I tried this and I still have the problem with the other validators not showing. I have several validators that are setup on the page load for required fields and regular expressions and I added them into the IWS group also but they are just not working still. – connersz Aug 12 '14 at 08:54
  • Also it doesn't hit the code on the product code validate and shows an error no matter what you enter. – connersz Aug 12 '14 at 09:17
  • @connersz Then I'm not sure what is happening in your case. Before answering the question I've created a new project and used both `RequiredFieldValidator` and `RegularExpressionValidator` with the setup you described. So the code I've posted is verified to be working. – Alexander Manekovskiy Aug 13 '14 at 07:50
  • Its interesting to know what is wrong with this answer so it got a downvote. I like to have a feedback :) – Alexander Manekovskiy Aug 15 '14 at 10:44
  • It didn't solve the problem and it was just the same as before. In the end I had to write a whole new validator control but that still won't show in the same validation summary. I have to make do with a second validation summary box. – connersz Aug 15 '14 at 11:37
  • Alright, its up to you. I found a test project I was talking previously: http://1drv.ms/1kIL6vA. What is wrong there? – Alexander Manekovskiy Aug 16 '14 at 07:47
0

In function validateProductCode(sender, args), you can get "productCodeValue" just by using args.Value:

      var productCodeValue = args.Value;

You don't need:

    var txtProductCodeClientId = "<%= txtProductCode.ClientID %>";
    var productCodeValue = ValidatorGetValue(txtProductCodeClientId);
0

To specify your parameters, use can do this instead:

   var parameters = { };
   parameters.siteId = ddlSiteIdValue;
   parameters.productCode = productCodeValue;

then in the data argument in your $.ajax({ call, use this:

   data:  JSON.stringify(parameters)