asp.net postback prevented after clientside validation - asp.net

I have an asp.net form which contains a dropdownlist which posts back to the server on change and populates second dropdownlist with some dates.
The form also contains other fields some of which are validated clientside and some server side.
Here's the problem I'm having. If I get a clientside validation error then try to change the dropdownlist, the second dropdown does not get populated. If I then change the first dropdownlist again, it works as expected.
Here's my submit button:
<asp:Button ID="btnSubmit" Text="Submit" runat="server" OnClientClick="Page_ClientValidate(); return checkPassengers();" OnClick="Page_Transfer" ValidationGroup="FormSubmit" />
Here's my clientside validation:
function checkPassengers() {
if($("#testField").val() == "Name *" || $("#testField").val() == "") {
$("#pltester").prepend("<p class='fillall'>Please fill in all fields marked with *</p>");
return false;
}
};
Dropdowns:
<asp:UpdatePanel ID="UpdatePanel1" runat="server" >
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddl1st" EventName="SelectedIndexChanged" />
</Triggers>
<ContentTemplate>
<asp:DropDownList ID="ddl1st" Width="190" AutoPostBack="true" OnSelectedIndexChanged="ChooseDates1st" runat="server" />
<asp:DropDownList ID="ddlDepart1st" AutoPostBack="true" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>

I've ran into this problem many times before when using updatepanels.
I've found that if the field needs to be validated then you have to actually set CausesValidation="true" on the element for it to still work with updatepanels.
Hope this helps you out!

Simply setting CausesValidation="true" did not resolve the issue for me. This appears to be issue when using asp dropdownlist's SelectedIndexChange event.
The workaround I found was to reset the validation on front end with a js by validating non-existing validation group name before the postback.
function ignoreValidation() {
if (typeof Page_ClientValidate != 'undefined') {
Page_ClientValidate('reset-validation');
Page_BlockSubmit = false;
}
return true;
}
And for dropdownlist
<asp:DropDownList CausesValidation="false" onchange="ignoreValidation();" runat="server" ID="CustomerDropDownList" OnSelectedIndexChanged="LoadCustomers" AutoPostBack="true"/>

If the Drop-Down list doesn't need to be validated, you can set CausesValidation="false" on the initial dropdown list. This will cause it not to trigger validation, so it can be changed at will.
Alternatively, you could put the DropDownList in a different ValidationGroup so that changing it doesn't trigger validation on the other controls.

function validateCommand(group) {
if (typeof (Page_ClientValidate) == 'function') {
Page_ClientValidate(group);
if (Page_IsValid) {
Page_BlockSubmit = !confirm('Are you sure?');
}
}
}

Related

How to use a custom ValidatorUpdateDisplay function when the controls / validators are loaded on postback in an UpdatePanel the first time?

In ASP.NET when using validation controls (i.e. RequiredFieldValidator) the client sided framework will execute the JS function Page_ClientValidate. This function will validate all controls on the page (of the given ValidationGroup) and call the JS function ValidatorUpdateDisplay with a parameter of the DOM element of the span tag of the validator control.
ValidatorUpdateDisplay toggles the visibility of the span tag depending on the result of the validation.
In my web application I've overridden the ValidatorUpdateDisplay JS function to provide more functionality on the validation scenario (i.e. red borders around the controls, showing popover on the first failed control and scrolling to it).
Now this works very well until my controls (incl. submit button) are shown the first time after a postback in an UpdatePanel.
<asp:ScriptManager runat="server" />
<asp:UpdatePanel ID="upTest" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button ID="bShow" runat="server" UseSubmitBehavior="false" Text="SHOW" OnClick="bShow_Click" />
<asp:Panel ID="pContent" runat="server" Visible="false">
<asp:TextBox ID="tbTest" runat="server" />
<asp:RequiredFieldValidator ID="rfvTest" runat="server" ControlToValidate="tbTest" Text="Not valid" />
<asp:Button ID="bTest" runat="server" UseSubmitBehavior="false" Text="TEST" />
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
<script type="text/javascript">
function ValidatorUpdateDisplay(val) {
debugger; // this will not be reached
}
</script>
protected void bShow_Click(object sender, EventArgs e)
{
this.pContent.Visible = true;
}
After initial load press bShow to display pContent.
Now, if you leave tbTest.Text empty and press on bTest it should enter the overridden ValidatorUpdateDisplay function, however it enters the function of the framework and displays "Not valid" from rfvTest.
If you change pContent.Visible to true and press bTest after initial load the desired effect will happen: It will enter the custom ValidatorUpdateDisplay function and not display "Not valid".
If you move the button bTest out of the UpdatePanel the problem persists.
How can I make it work inside an UpdatePanel?
ASP.NET uses a lazy loading approach to insert the ValidatorUpdateDisplay function when it needs it the first time, hence in my example it will load the function after the postback of the UpdatePanel.
This will override my own implementation of the ValidatorUpdateDisplay function, because it's inserting the function at the end of the page.
There is a dirty workaround, I just inserted an empty CustomValidator on initial load that is always valid:
<asp:CustomValidator runat="server" />
I wish there was a cleaner solution.

ASP.NET: Button inside a ListView inside an Update Panel causes full Postback

<script type="text/javascript">
function ClientSideClick(myButton) {
//make sure the button is not of type "submit" but "button"
if (myButton.getAttribute('type') == 'button') {
// disable the button
myButton.disabled = true;
//myButton.className = "btn-inactive";
myButton.value = "Posting...";
}
return true;
}
</script>
<asp:UpdatePanel ID="upComments" runat="server" UpdateMode="Always" >
<ContentTemplate>
<asp:ListView ... >
<asp:Button ID="btnSubPostComment" runat="server" Text="Reply Comment"
CommandName="cmdPostSubComment" OnClientClick="ClientSideClick(this)" UseSubmitBehavior="false"
</asp:ListView>
</ContentTemplate>
</asp:UpdatePanel>
The Javascript function (ClientSideClick) disables the button when it's processing.
The problem is that when I include
OnClientClick="ClientSideClick" UseSubmitBehavior="false"
in my button, even though it's inside an Update Panel it causes full postback.
If I remove those two Properties OnClientClic and UseSubmitBehavior the button does not cause full postback. Does anyone know why this happens?
All I wanted to do is disable the button and chagne it's text to prevent multiple submissions.
I'm not sure if this is exactly what you're looking for but I usually use this:
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<script type="text/javascript">
var pbControl = null;
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(BeginRequestHandler);
prm.add_endRequest(EndRequestHandler);
function BeginRequestHandler(sender, args) {
pbControl = args.get_postBackElement();
pbControl.disabled = true;
}
function EndRequestHandler(sender, args) {
pbControl.disabled = false;
pbControl = null;
}
</script>
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:ListView ... >
<asp:Button ID="btnSubPostComment" runat="server" Text="Reply Comment" CommandName="cmdPostSubComment" OnClientClick="this.value='Posting...';" />
</asp:ListView>
</ContentTemplate>
</asp:UpdatePanel>
The only problem is that if the same button is clicked again after the first async postback then it throws a "Operation is not valid due to the current state of the object" error. This might appear as a javascript exception in the form of a 500 internal server error. After doing some research, I came across:
"Microsoft recently (12-29-2011) released an update to address several serious security vulnerabilities in the .NET Framework. MS11-100 was introduced just recently that handles potential DoS attacks. Unfortunately the fix has also broken page POSTs with very large amounts of posted data (form fields). MS11-100 places a limit of 500 on postback items. The new default max introduced by the recent security update is 1000."
Scott Gu writes about it here: http://weblogs.asp.net/scottgu/archive/2011/12/28/asp-net-security-update-shipping-thursday-dec-29th.aspx
Adding the setting key to the web-config file overcomes this error:
<appSettings>
<add key="aspnet:MaxHttpCollectionKeys" value="2000" />
</appSettings>

imagebutton with onclientclick isn't firing onclick event

I have an imagebutton with an postbackurl and an onclientclick script. When i added the onclientclick code, if my javascript validation passes (aka returns true), the page just seems to perform a postback (the screen just seems to refresh itself), rather than post to the postbackurl. Any ideas why this is happening?
Sample:
<asp:ImageButton ID="imgSendInfo" runat="server" SkinID="SendInfo" PostBackUrl="MyUrlOnAnotherSite" onClientClick="javascript:return onFormSubmit(this.form);return document.MM_returnValue" />
UPDATE:
OK, so I decided to change what JS functions I'm calling now since calling Multiple functions definitely wasn't helping. Here's my updated code. All I'm doing now is validating a single textbox and returning true or false. Even this simple function is causing the postback URL to never get called. Could it have anything to do with the fact that I'm trying to call a function to return a true or false?
My validation function:
function valForm() {
if (document.getElementById('FName').value == '') {
alert('no');
return false;
}
else {
alert('yes');
return true;
}
}
My ImageButton:
<asp:ImageButton ID="imgSendInfo" runat="server" SkinID="SendInfo" PostBackUrl="SetOnCodeBehind" onClientClick="javascript:return valForm();" />
OK figured out a workaround. I REMOVED the return statement from the onclientclick, since the return is what was messing with the postback. I then added requiredfieldvalidators to the page, but Im not displaying any text. This way, 2 sets of validation are occurring (booo), but the first displays my alert messages (this is how the client wants validation performed), and the second prevents the form from posting.
My imagebutton:
<asp:ImageButton ID="imgSendInfo" runat="server" SkinID="SendInfo" PostBackUrl="SetOnCodeBehind" ValidationGroup="enroll" CausesValidation="true" onClientClick="javascript:onFormSubmit(this.form);document.MM_returnValue;" />
My requiredfieldvalidation group:
<asp:RequiredFieldValidator ID="reqVal1" runat="server" ErrorMessage="" ValidationGroup="enroll" ControlToValidate="FName" InitialValue="" />
<asp:RequiredFieldValidator ID="reqVal2" runat="server" ErrorMessage="" ValidationGroup="enroll" ControlToValidate="LName" InitialValue="" />
Did you know that your onClientClick js-function returns twice? return document.MM_returnValue never gets reached.
Is your PostBackUrl's page in your application? You can even validate the previous page on serverside:
If Page.PreviousPage.IsValid Then
' Handle the post back
Else
Response.Write("Invalid")
End If
For further information: MSDN LinkButton.PostBackUrl

Enable/disable RequiredValidator on client-side / CustomValidator not firing

I've got a drop-down where the user selects a Country. It is a required "field".
Next to it, there is a textfield named State. If the user selects US, then the field State is required. If the user selects e.g. Sweden, the State is not required, since Sweden has no states.
Example code:
<asp:DropDownList runat="server" ID="Country"></asp:DropDownList>
<asp:RequiredFieldValidator ControlToValidate="Country"
runat="server" Display="Static" ErrorMessage="Required field" />
<asp:TextBox runat="server" ID="State"></asp:TextBox>
<asp:CustomValidator ClientValidationFunction="DoesntGetFiredIfStateIsEmpty"
runat="server" Display="Static" ErrorMessage="Required field" />
<!-- SO, RATHER THIS TOGETHER WITH CONDITIONAL FIRING -->
<asp:RequiredFieldValidator ControlToValidate="State"
runat="server" Display="Static" ErrorMessage="Required field" />
My question to you is: How can I make this CustomValidator fire validation when it is empty?
Or put simplier: How can I make a RequiredValidator fire conditionally?
Or simplest: How can I enable/disable a RequiredValidator on client-side?
Try doing this with javascript to enable and disable validators
ValidatorEnable(RequiredFieldValidatorId, false);
Check out this question that I answered.
Asp.net has a client side javascript function to manage the validators, the "ValidatorEnable" function,
ValidatorEnable(RequiredFieldValidatorId, false);
you can call it simply using javascript, you must send the validator object to the function (not only its id).
if (x==y) {
ValidatorEnable($('#<%=rfvFamily.ClientID %>'), false);
} else {
ValidatorEnable($('#<%=rfvFamily.ClientID %>'), true);
}
or
if (x==y) {
ValidatorEnable(document.getElementById("<%=rfvFamily.ClientID %>", false);
} else {
ValidatorEnable(document.getElementById("<%=rfvFamily.ClientID %>", true);
}
full documnet on:
http://msdn.microsoft.com/en-us/library/Aa479045#aspplusvalid_clientside
another way is to Set in your DropDownList CausesValidation="false" to avoid that the validators block a postback when you change the DropDownList entry.
(*) Remember this function is for client side, for disabling validator in server side, you must to disable validator on page postback too.
if (IsPostBack){
if (x==y) {
rfvFamily.Enabled = false;
}
}

Problem with textbox inside updatepanel - not causing OnTextChanged event

I have the following situation: I have a textbox inside an ajax updatepanel. Wherever the user types in the textbox I must display a message (different message that depends on the user typed data).
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always">
<ContentTemplate>
<asp:TextBox ID="txtMyTexbox" runat="server" Width="500px" OnTextChanged="txtMyTexbox_TextChanged" AutoPostBack="true"></asp:TextBox>
<br />
<asp:Label ID="lblMessage" runat="server" CssClass="errorMessage" Visible="false">Hello World</asp:Label>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="txtMyTexbox" />
</Triggers>
</asp:UpdatePanel>
In server side I have written the following at page load
ScriptManager.GetCurrent(this).RegisterAsyncPostBackControl(txtMyTexbox);
and the method like this
protected void txtMyTexbox_TextChanged(object sender, EventArgs e)
{
if (.....)
{
lblMessage.Visible = false;
}
else
{
lblMessage.Visible = true;
}
}
My problem now is that: when the user types in the textbox it doesn't cause OnTextChanged event.
Am I missing something?
I'm not sure that your problem has anything to do with the UpdatePanel.
In fact, the TextChanged event doesn't fire while typing. It will only fire after the textbox loses focus. This happens directly if AutoPostBack is set to True, or when the next postback occurs. Please see the docs for the AutoPostBack property and the TextChanged event.
Afaik, your best bet is probably to handle the keyup event in javascript.
Here's a simple jQuery example:
$(document).ready(function() {
$(':text[id$=YourTextBox]').keyup(function() {
if ($(this).val() === "your special value") {
$('span[id$=YourLabel]').css('visibility', 'visible');
}
else {
$('span[id$=YourLabel]').css('visibility', 'hidden');
}
});
});
Set the EventName property for your txtMyTexbox AsyncPostBackTrigger to TextChanged
<Triggers>
<asp:AsyncPostBackTrigger ControlID="txtMyTexbox" EventName="TextChanged" />
</Triggers>
Other sugguestion:
Have you tried looking at the AutoComplete control that is part of the AjaxControlToolKit? Its behaves the same way you want your solution to behave.
its strnage to know that even after adding update panel / AsyncPostBackTrigger , TextBox ChangeEvent doesn't work properly. Some time its works and some times it not..Since its is Asychronous call, we need to some time refresh, or wait or unpredictable , Hopes microsoft will come up with competent one.. Below are easy way to check user name pretty good
------ Under Page_Load - aspx.cs -----------------------
this.TextBox1.Attributes.Add("onKeyUp", "fnUNameSubmit(this);");
-------in aspx -add script ---------------------------------------
<script language="javascript" type="text/javascript">
function fnUNameSubmit(urInput) {
var inpt= urInput.value;
if (inpt.length > 21) {
document.getElementById('<%= TextBox1.ClientID %>').style.backgroundColor = "green";
document.form1.submit(); // This is only trick we use here..
}
else {
document.getElementById('<%= TextBox1.ClientID %>').style.backgroundColor = "red";
}
}
</script>
-------in aspx -add script ---------------------------------------
----------------aspx.cs -------------------
if (TextBox1.Text.Length > 21)
{
CheckUsrName();
Label2.Text = "";
}
else
{
Label2.Text = "Length is less than 21"; //lets do some stuff..bla..bla
}
------------------------------------------------- CheckUsername()
public void CheckUsrName()
{
Call dB values
}
You should not be using RegisterAsyncPostBackControl for your TextBox. That method is really only for use for controls that reside outside of UpdatePanels. I would try removing that line of code and seeing what happens.
See this for more info: http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanager.registerasyncpostbackcontrol.aspx
a workaround check textbox - causesvalidation property and set it to true
The Control which id is used in AsyncPostBackTrigger must be outside the update Panel(that cause to fire the Async call) like this:
<tr>
<td colspan="4"><asp:Label ID="lblEnter_Successfully" Text="Enter Record SuccessFully" runat="server" Visible ="false" ForeColor ="Blue" Font-Size ="Larger" Font-Bold ="true"></asp:Label>
</td>
</tr>
</table>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID = "Button_Save" EventName ="Click"/>
</Triggers>
</asp:UpdatePanel>
<table>
<tr>
<td width = "472px" align ="right">
<asp:Button ID="Button_Save" runat="server" Text="Save" OnClientClick ="return URLValidation();"/>
<asp:Button ID="Button_Clear" runat="server" Text="Clear"/>
</td>
</tr>
</table>

Resources