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.
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.
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.
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.
ASKER
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:textB ox><br />
<ss:reqFldVal id="rfvSearch" runat="server" ControlToValidate="txtKeyw ords">* Please enter search criteria.</ss:reqFldVal>
<asp:button id="btnSearch" tabIndex="5" runat="server" Text="Search" cssClass="action"></asp:bu tton>
Here is my custom control:
Public Class reqFldVal
Inherits System.Web.UI.WebControls. RequiredFi eldValidat or
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?
<ss:textBox id="txtKeywords" tabIndex="4" runat="server" width="300" defaultButton="btnSearch">
<ss:reqFldVal id="rfvSearch" runat="server" ControlToValidate="txtKeyw
<asp:button id="btnSearch" tabIndex="5" runat="server" Text="Search" cssClass="action"></asp:bu
Here is my custom control:
Public Class reqFldVal
Inherits System.Web.UI.WebControls.
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?
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?
ASKER
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("nam e", Name)
Attributes.Remove("name")
writer.WriteAttribute("met hod", 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
Public Class actionlessForm
Inherits HtmlControls.HtmlForm
Protected Overrides Sub RenderAttributes(ByVal writer As HtmlTextWriter)
writer.WriteAttribute("nam
Attributes.Remove("name")
writer.WriteAttribute("met
MyBase.Attributes.Remove("
Attributes.Render(writer)
MyBase.Attributes.Remove("
If Not MyBase.ID Is Nothing Then
writer.WriteAttribute("id"
End If
End Sub
End Class
ASKER
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("nam e", Name)
Attributes.Remove("name")
writer.WriteAttribute("met hod", 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("onsubmi t")
End If
writer.WriteAttribute("lan guage", "javascript")
writer.WriteAttribute("ons ubmit", l_submitEvent)
End If
End If
writer.WriteAttribute("id" , Me.ClientID)
' From HtmlContainerControl
ViewState.Remove("innerhtm l")
' 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_propert yName, BindingFlags.IgnoreCase Or BindingFlags.Instance Or BindingFlags.NonPublic)
If Not l_property Is Nothing Then
Return l_property.GetValue(pi_tar get, 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(MyB ase.Page, GetType(System.Web.UI.Page ), "ClientOnSubmitEvent"))
End Function
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("nam
Attributes.Remove("name")
writer.WriteAttribute("met
MyBase.Attributes.Remove("
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("onsubmi
End If
writer.WriteAttribute("lan
writer.WriteAttribute("ons
End If
End If
writer.WriteAttribute("id"
' From HtmlContainerControl
ViewState.Remove("innerhtm
' 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
'<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(
If Not l_property Is Nothing Then
Return l_property.GetValue(pi_tar
Else
Return Nothing
End If
End Function
'<summary>
'Uses reflection to access the ClientOnSubmitEvent property of the Page class
'</summary>
Private Function Page_ClientOnSubmitEvent()
Return CStr(GetHiddenProperty(MyB
End Function
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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.
Anyways, thanks for your help.
onclick="return Page_ClientValidate(); "
And also, in the form tag youmight want to try <form onsubmit="return Page_ClientValidate()">