Link to home
Start Free TrialLog in
Avatar of dustinclark
dustinclark

asked on

ASP.NET - Client side validation does not work

I know this is a very common issue, but every answer that I found said the same thing: make sure that your WebUIValidation.js is in the correct path.

I know that it is there, and I know that Page_ClientValidate() is returning false, because I put in some alerts.  However, the page is still posting back and I can't figure out why..

If you want to take a look at the source, check here:
http://www.collegeswapshop.com/Search.aspx

Just click search without entering keywords.
Avatar of UnexplainedWays
UnexplainedWays

Can you try this code to see if it makes a difference.
onclick="return Page_ClientValidate(); "

And also, in the form tag youmight want to try  <form onsubmit="return Page_ClientValidate()">
Avatar of dustinclark

ASKER

I know that would work, because you can save off the html source and make this change, and the page will not post back when it is not valid.

However, this is rendered as part of the asp.net button control.  I could extend the button control with my own, and change the way the onclick attribute is rendered, but there has to be a cleaner solution than this.  And besides that, why would it just stop working?

Thanks for your help.
All i can work off is the html(from aspx) you provided, without the code i can't do much more.
I can post the code, but I dont think that it is going to do much good.  I am basically using the built in asp.net validation controls (actually, I am extending it, but only to add style="display:NONE").  Here is the relevant aspx code:

<ss:textBox id="txtKeywords" tabIndex="4" runat="server" width="300" defaultButton="btnSearch"></ss:textBox><br />
<ss:reqFldVal id="rfvSearch" runat="server" ControlToValidate="txtKeywords">* Please enter search criteria.</ss:reqFldVal>
<asp:button id="btnSearch" tabIndex="5" runat="server" Text="Search" cssClass="action"></asp:button>

Here is my custom control:
    Public Class reqFldVal
        Inherits System.Web.UI.WebControls.RequiredFieldValidator

        Protected Overrides Sub Render(ByVal writer As HtmlTextWriter)
            If IsValid Then
                Attributes.Add("style", "display:NONE")
            Else
                Attributes.Add("style", "display:BLOCK")
            End If
            If CssClass = vbNullString Then
                CssClass = "messageError"
            End If
            MyBase.Render(writer)
        End Sub
    End Class

And, I have overriden this method in WebUIValidation.js:

function ValidatorUpdateDisplay(val) {
    if (typeof(val.display) == "string") {    
        if (val.display == "None") {
            return;
        }
        if (val.display == "Dynamic") {
            val.style.display = val.isvalid ? "none" : "inline";
            return;
        }
    }
    val.style.visibility = val.isvalid ? "hidden" : "visible";
    val.style.display = val.isvalid ? "NONE" : "";
}

Any ideas?

Sorry, i'm out of ideas.

The only thing i can suggest which i have no idea if it would even have an influence would be to not override ValidatorUpdateDisplay and suply your own?  Might have something to do with the overriding. You did say you have alerts in the functon so you know it's called so i doubt it will do anything.

Best of luck.

One last thing, has it ever worked and just broken lately after adding some things?
After racking my brain today to try to figure out what I might have changed to break this, I finally realized that it may be because I am forced to use an actionless form to support url rewriting.  My custom form control is below.  I havent had the time to test this theory, but I will try it tonight.  I will also try to remember why exactly I was forced to do this.  Any ideas for a workaround?

    Public Class actionlessForm
        Inherits HtmlControls.HtmlForm
        Protected Overrides Sub RenderAttributes(ByVal writer As HtmlTextWriter)
            writer.WriteAttribute("name", Name)
            Attributes.Remove("name")

            writer.WriteAttribute("method", Method)
            MyBase.Attributes.Remove("method")

            Attributes.Render(writer)

            MyBase.Attributes.Remove("action")

            If Not MyBase.ID Is Nothing Then
                writer.WriteAttribute("id", MyBase.ClientID)
            End If
        End Sub

    End Class
Woohoo!  I found the solution, in case anyone is interested.  Apparently, I was missing the "onsubmit" attribute that is rendered when validation is present on the form....which wasn't as easy as adding it, as you will see below.  The ClientOnSubmitEvent of the Page class is private, so you have to use reflection to access it.  However, this is much cleaner than any other solution I found.

I had to create my own custom form because asp.net renders the "action" attribute on your form.  If you are using url rewriting to make your paths cleaner, this will break on any postback.  The action attribute is not necessary in the first place (thanks to the genius who hard-coded that without a simple way to override).

Other solutions were extending the HtmlWriter class and checking the every tag name before rendering it (simply to remove the "action" attribute.)  Anyways, here is the code in case anyone else has the same problem.

    Public Class actionlessForm
        Inherits HtmlControls.HtmlForm

        Protected Overrides Sub RenderAttributes(ByVal writer As HtmlTextWriter)
            writer.WriteAttribute("name", Name)
            Attributes.Remove("name")

            writer.WriteAttribute("method", Method)
            MyBase.Attributes.Remove("method")

            Attributes.Render(writer)

            Dim l_submitEvent As String = Page_ClientOnSubmitEvent()
            If Not l_submitEvent Is Nothing Then
                If l_submitEvent.Length > 0 Then
                    If Not Attributes("onsubmit") Is Nothing Then
                        l_submitEvent = l_submitEvent & Attributes("onsubmit")
                        Attributes.Remove("onsubmit")
                    End If
                    writer.WriteAttribute("language", "javascript")
                    writer.WriteAttribute("onsubmit", l_submitEvent)
                End If
            End If

            writer.WriteAttribute("id", Me.ClientID)

            ' From HtmlContainerControl
            ViewState.Remove("innerhtml")

            ' From HtmlControl
            Attributes.Render(writer)
        End Sub


        ' <summary>
        'Uses reflection to access any property on an object, even tho the property is marked protected, internal, or private.
        '</summary>
        '<param name="pi_target">The object being accessed</param>
        '<param name="pi_targetType">The Type to examine. Usually the Type of target arg, but sometimes a superclass of it.</param>
        '<param name="pi_propertyName">The name of the property to access.</param>
        '<returns>The value of the property, or null if the property is not found.</returns>
        Private Function GetHiddenProperty(ByVal pi_target As Object, ByVal pi_targetType As Type, ByVal pi_propertyName As String) As Object
            Dim l_property As PropertyInfo = pi_targetType.GetProperty(pi_propertyName, BindingFlags.IgnoreCase Or BindingFlags.Instance Or BindingFlags.NonPublic)

            If Not l_property Is Nothing Then
                Return l_property.GetValue(pi_target, Nothing)
            Else
                Return Nothing
            End If
        End Function

        '<summary>
        'Uses reflection to access the ClientOnSubmitEvent property of the Page class
        '</summary>
        Private Function Page_ClientOnSubmitEvent() As String
            Return CStr(GetHiddenProperty(MyBase.Page, GetType(System.Web.UI.Page), "ClientOnSubmitEvent"))
        End Function
ASKER CERTIFIED SOLUTION
Avatar of UnexplainedWays
UnexplainedWays

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You were right...i just thought that I had the exact same code in my RenderAttributes method as the built-in .net version.

Anyways, thanks for your help.