ASP.NET Dropdownlist SelectedIndexChanged fired again after rasing exception - asp.net

Here's my sample code.
My scenarios is
1. Change dropdownlist item it will fire SelectedIndexChanged event.
2. During SelectedIndexChanged event, raise the exception.
3. Popup error alert message
4. Click the button
5. SelectedIndexChanged fired again.
I'm really curious to know what's going on this procedure?
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<script type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(PageRequestManager_OnEndRequest);
function PageRequestManager_OnEndRequest(sender, args) {
//debugger;
var alertMessage = "Application exception has been occurred.\n\nMessage: ";
if (args.get_error() && args.get_error().httpStatusCode == '500') {
var errorMessage = args.get_error().message
var findIndex = 0;
args.set_errorHandled(true);
if ((findIndex = errorMessage.indexOf(":")) > -1) {
errorMessage = errorMessage.substr(findIndex + 2);
}
alert(alertMessage + errorMessage);
}
};
</script>
<div>
<asp:UpdatePanel runat="Server" UpdateMode="Conditional" ID="UpdatePanel1">
<ContentTemplate>
<asp:DropDownList ID="DropDownListState" runat="server" OnSelectedIndexChanged="DropDownListState_SelectedIndexChanged" AutoPostBack="true">
<asp:ListItem Text="Michigan" Value="07"></asp:ListItem>
<asp:ListItem Text="Mississippi" Value="08"></asp:ListItem>
<asp:ListItem Text="Nevada" Value="09"></asp:ListItem>
</asp:DropDownList>
<asp:Button runat="server" ID="Button" OnClick="Button_Click" Text="Click Here" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
codebehind:
protected void DropDownListState_SelectedIndexChanged(object sender, EventArgs e)
{
int stateNo = 0;
string stateName = "California";
stateNo = Convert.ToInt32(stateName);
}
protected void Button_Click(object sender, EventArgs e)
{
string ddd = "";
}

It happens because error in event DropDownListState_SelectedIndexChanged ends the request to the server in abnormal way. That's why not all properties and states are properly propagated. So when you hit the button it will think that dropdownlist value on the server is different that the one provided by the browser and will fire DropDownListState_SelectedIndexChanged again. If you comment out the error all will work as expected.

Related

Timer in ASP.NET webform to update a label text

I use this code for create timer that want to update a label each second:
timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(OnRefresh_Tick);
timer.Interval = 1000;
The function OnRefresh_Tick call each second but the label text doesn't change.
Edit:
I use the below code for the timer, but when the timer starts, I can't write in the second textbox (txtPassword) and it refreshes and the cursor goes to the first textbox (txtUserName)
.aspx file:
<form id="form1" runat="server">
<br /><br />
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtUserName" runat="server" Height="30px" Width="100px"></asp:TextBox><br /><br />
<asp:TextBox ID="txtPassword" runat="server" Height="30px" Width="100px"></asp:TextBox><br /><br />
<asp:Label runat="server" id="lnkSendVerificationCode"></asp:Label><br /><br />
<asp:Button ID="Button1" runat="server" Text="Start Timer" CssClass="btn" OnClick="Button1_Click"/>
<asp:Timer ID="Timer1" runat="server" Enabled="False" Interval="1000" OnTick="Timer1_Tick"></asp:Timer>
</ContentTemplate>
</asp:UpdatePanel>
</form>
.cs file:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
{
}
}
protected void Button1_Click(object sender,EventArgs e)
{
Session["VerificationCodeCounter"] = "20";
Timer1.Enabled = true;
}//Button1_Click
protected void Timer1_Tick(object sender, EventArgs e)
{
int sendVerificationCounter = -1;
try { sendVerificationCounter = int.Parse(Session["VerificationCodeCounter"].ToString()); } catch { }//catch
if (sendVerificationCounter == 1)
{
sendVerificationCounter = -1;
Session["VerificationCodeCounter"] = sendVerificationCounter.ToString();
Timer1.Enabled = false;
}//if
else if (sendVerificationCounter > 0)
{
sendVerificationCounter--;
lnkSendVerificationCode.Text = sendVerificationCounter.ToString();
Session["VerificationCodeCounter"] = sendVerificationCounter.ToString();
}//else if
}//Button1_Click
Try say this:
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<div style="padding:25px">
<h4>enter seconds to count down</h4>
<asp:TextBox ID="txtCount" runat="server"
Height="42px"
Width="80px"
Font-Size="XX-Large"
Text="0"
style="text-align: center">
</asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Start Timer" CssClass="btn" OnClick="Button1_Click"/>
<asp:Timer ID="Timer1" runat="server" Enabled="False" Interval="1000" OnTick="Timer1_Tick"></asp:Timer>
<br />
</div>
And code behind would be this:
protected void Button1_Click(object sender, EventArgs e)
{
Timer1.Interval = 1000; // tick our timer each second
Timer1.Enabled = true;
}
protected void Timer1_Tick(object sender, EventArgs e)
{
int MyCount = Convert.ToInt32(txtCount.Text);
if (MyCount > 0 )
{
MyCount = MyCount - 1;
txtCount.Text = MyCount.ToString();
}
else
{
// we are done, stop the timer
Timer1.Enabled = false;
}
}
So, we now see this if we enter 10 (for 10 seconds).
If we hit start timer, then it counts down to 0, and then stops the timer.
Edit: With a up-date panel
So, if we don't want a whole page re-fresh, then we can use this:
<h4>enter seconds to count down</h4>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:TextBox ID="txtCount" runat="server"
Height="42px"
Width="80px"
Font-Size="XX-Large"
Text="0"
style="text-align: center">
</asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Start Timer" CssClass="btn" OnClick="Button1_Click"/>
<asp:Timer ID="Timer1" runat="server" Enabled="False" Interval="1000" OnTick="Timer1_Tick"></asp:Timer>
</ContentTemplate>
</asp:UpdatePanel>
Remember, while the whole page will now not re-fresh, do keep in mind that the page life cycle DOES trigger. So, if you have some code in on-page load to setup controls? Then you need this
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// code here to load up grids, and controls
// code here ONLY runs on first time page load
}
}
So, keep in mind that for any up-date panel (button clicks, timer etc.), then the page load event DOES fire each time.
However, that !IsPostback check? The last 100+ web pages I created that loads or sets up ANYTHING on a page will have the above code stub, and check for !IsPostback.
You can't quite even make a working webforms page unless you follow the above rule. What this means is your page can now handle post-backs, and not re-load controls and run the first time setup of such controls.
So, keep in mind, a update panel DOES post-back, and does trigger the page load event. Better said, a update panel, and click of a button (or timer) inside will post-back, but it what we call a partial page post-back.
Edit3: With a label
So, say we want a label - not a text box. Then do this:
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
<div style="padding:25px">
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label ID="txtCount" runat="server"
Height="42px"
Width="80px"
Font-Size="XX-Large"
Text="999"
style="text-align: center">
</asp:Label>
<br />
<asp:Button ID="Button1" runat="server" Text="Start Timer" CssClass="btn" OnClick="Button1_Click"/>
<asp:Timer ID="Timer1" runat="server" Enabled="False" Interval="1000" OnTick="Timer1_Tick"></asp:Timer>
</ContentTemplate>
</asp:UpdatePanel>
<br />
</div>
</form>
</body>
And now our code becomes this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// code here to load up grids, and controls
// code here ONLY runs on first time page load
txtCount.Text = "10";
}
}
protected void Button1_Click(object sender, EventArgs e)
{
Timer1.Interval = 1000; // tick our timer each second
Timer1.Enabled = true;
}
protected void Timer1_Tick(object sender, EventArgs e)
{
int MyCount = Convert.ToInt32(txtCount.Text);
if (MyCount > 0 )
{
MyCount = MyCount - 1;
txtCount.Text = MyCount.ToString();
}
else
{
// we are done, stop the timer
Timer1.Enabled = false;
}
}
And now we see this:

RegisterStartupScript from code behind not working when Update Panel is used

I have created a radiobutton list followed by one button. I can select one of the item from the radiobutton list and then click the button to execute something. And I want the page to pop up a window if the button is clicked without selecting any of the options from the radiobutton list. My codebehide is like this:
protected void ButtonPP_Click(object sender, EventArgs e)
{
if (radioBtnPP.SelectedIndex < 0)
{
String csname1 = "PopupScript";
Type cstype = this.GetType();
// Get a ClientScriptManager reference from the Page class.
ClientScriptManager cs = Page.ClientScript;
// Check to see if the startup script is already registered.
if (!cs.IsStartupScriptRegistered(cstype, csname1))
{
StringBuilder cstext1 = new StringBuilder();
cstext1.Append("<script type=text/javascript> alert('Please Select Criteria!') </");
cstext1.Append("script>");
cs.RegisterStartupScript(cstype, csname1, cstext1.ToString());
}
}
}
and my html part is:
<asp:RadioButtonList class ="radioBtn" ID="radioBtnACO" runat="server">
<asp:ListItem Text="All Dim" />
<asp:ListItem Text="Select Dim" />
</asp:RadioButtonList>
<asp:Button id ="ButtonPP" class ="buttonRight" runat="server" Text="Run PP" OnClick="ButtonPP_Click" />
This works fine. However, now I don't want to refresh the whole page when i click the button, so I use updatepanel. And I changed my html code to the following:
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="ControlUpdatePanel" runat="server" Visible="True">
<ContentTemplate>
<asp:RadioButtonList class ="radioBtn" ID="radioBtnACO" runat="server">
<asp:ListItem Text="All Dim" />
<asp:ListItem Text="Select Dim" />
</asp:RadioButtonList>
<asp:Button id ="ButtonPP" class ="buttonRight" runat="server" Text="Run PP" OnClick="ButtonPP_Click" />
</ContentTemplate>
</asp:UpdatePanel>
But now my code doesn't work anymore... If I don't select any option from the radiobutton list and just click the button, no window would pop up :( I am sure my codebehind is still executed but seems like it just doesn't passed to my .aspx page...
Anyone please help me out? I don't know what to do now... Millions of thanks!
You need to use ScriptManager.RegisterStartupScript for Ajax.
protected void ButtonPP_Click(object sender, EventArgs e)
{
if (radioBtnACO.SelectedIndex < 0)
{
string csname1 = "PopupScript";
var cstext1 = new StringBuilder();
cstext1.Append("alert('Please Select Criteria!')");
ScriptManager.RegisterStartupScript(this, GetType(), csname1,
cstext1.ToString(), true);
}
}

CustomValidator not executing on second step of a multi-panel Page

I am experiencing a problem with an ASPX page not executing a CustomValidator. The Page consists of 3 ASP Panels which swap visibility for each step in a 3 step process. The first step/panel functions as expected, executing all CustomValidators when I click the submit button. If valid, the button click hides its panel and shows the second panel for step #2 which contains another CustomValidator. When clicking the submit button on this second panel, the CustomValidator never executes and the Page always reports that it IsValid.
I have reproduced this behavior in a small, example app. Here is the relevant code...
Default.aspx
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<h2>
Welcome to ASP.NET!
</h2>
<p>
To learn more about ASP.NET visit www.asp.net.
</p>
<p>
You can also find <a href="http://go.microsoft.com/fwlink/?LinkID=152368&clcid=0x409"
title="MSDN ASP.NET Docs">documentation on ASP.NET at MSDN</a>.
</p>
<asp:Panel ID="Panel1" runat="server" Visible="true">
<div>
<asp:CustomValidator
ID="CustomValidator1"
runat="server"
ControlToValidate="TextBox1"
ValidateEmptyText="true"
Display="Dynamic"
OnServerValidate="CustomValidator1_ServerValidate">
</asp:CustomValidator>
</div>
<div>
<asp:Label ID="Label1" runat="server" Text="Type in anything:" AssociatedControlID="TextBox1" />
<asp:TextBox ID="TextBox1" runat="server" />
</div>
<div>
<asp:Button ID="Button1" runat="server" Text="Show Panel #2" OnClick="Button1_Click" />
</div>
</asp:Panel>
<asp:Panel ID="Panel2" runat="server" Visible="false">
<div>
<asp:CustomValidator
ID="CustomValidator2"
runat="server"
Display="Dynamic"
OnServerValidate="CustomValidator2_ServerValidate">
</asp:CustomValidator>
</div>
<div>
<asp:Button ID="Button2" runat="server" Text="I should cause an Exception..." OnClick="Button2_Click" />
</div>
</asp:Panel>
<asp:Panel ID="Panel3" runat="server" Visible="false">
<p>An exception should have been thrown. :(</p>
</asp:Panel>
</asp:Content>
Default.aspx.cs
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Panel1.Visible = true;
Panel2.Visible = false;
Panel3.Visible = false;
}
protected void Button1_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
Panel1.Visible = false;
Panel2.Visible = true;
Panel3.Visible = false;
}
}
protected void Button2_Click(object sender, EventArgs e)
{
if (Page.IsValid)
{
Panel1.Visible = false;
Panel2.Visible = false;
Panel3.Visible = true;
}
}
protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args)
{
string userEnteredText = TextBox1.Text;
if (string.IsNullOrEmpty(userEnteredText))
{
CustomValidator1.Text = "Text is required!";
args.IsValid = false;
}
else if (!userEnteredText.ToLower().Equals("anything"))
{
CustomValidator1.Text = "You didn't type 'anything'! ;)";
TextBox1.Text = null;
args.IsValid = false;
}
else
{
args.IsValid = true;
}
}
protected void CustomValidator2_ServerValidate(object source, ServerValidateEventArgs args)
{
throw new Exception("This ServerValidate() method never triggers!");
}
}
I don't understand why the CustomValidator2 method is never executing. Can anyone explain this behaviour?
As you're not setting the ControlToValidate property in your scenario set the property ValidateWhenEmpty to true on the CustomValidator.
The CustomValidator will not be evaluated when the ControlToValidate is blank unless ValidateWhenEmpty is true.
UPDATE:
Ok this was wrong. But do you really need to set visibility of the panels in the Page_Load? You've done it already declaratively in the .aspx.
If you remove it from Page_Load, the validator works. I suppose it does not work if the validator is Visible=false or is inside a containing control that is Visible=false.
You should use ValidationGroup property of the buttons and the corresponding validation controls in each panel.

How do I maintain user entered text in a TextBox nested in an UpdatePanel between updates?

I have an ASP.Net UpdatePanel that updates on a timer. Within the UpdatePanel and nested in a GridView, I have a TextBox that the user enters a value in with a submit button. Everything works fine, except if the user does not submit the value before the timed interval, the text is removed from the TextBox.
Is there a way to persist the user entry into the TextBox between updates? Is there a better way of doing this?
All suggestions welcome.
Respectfully,
Ray K. Ragan
Code Postscript:
aspx:
<script type="text/javascript">
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_beginRequest(beginRequest);
function beginRequest() {
prm._scrollPosition = null;
}
</script>
<asp:Timer ID="Timer1" runat="server" Interval="900" OnTick="Timer1_Tick"></asp:Timer>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="Timer1" EventName="Tick" />
</Triggers>
<ContentTemplate>
<asp:DataList RepeatColumns="5" RepeatDirection="Horizontal" ID="dlMine" runat="server" OnItemCommand="Item_Command">
<ItemTemplate>
<div style="border:1px solid black;margin:3px;height:300px;text-align:center;padding:5px;">
<div style="width:150px;">
<asp:Label ID="lblTitle" runat="server" Text='<%# left(DataBinder.Eval(Container.DataItem,"title").ToString(), 75) %>'></asp:Label>
</div>
<asp:Label ID="Label1" runat="server" Text='<%# (DateTime)DataBinder.Eval(Container.DataItem,"end_date") %>'></asp:Label>
<br />
<asp:Label ID="Label2" runat="server" Text='<%# String.Format("{0:C}",DataBinder.Eval(Container.DataItem,"current_value")) %>'></asp:Label>
<br />
<asp:TextBox ID="txtNewValue" runat="server"></asp:TextBox>
<asp:Button Visible='<%# (isInThePast((DateTime)DataBinder.Eval(Container.DataItem,"end_date"))) ? false : true %>' CssClass="bid_button" runat="server" CommandArgument='<%# Eval("ID") %>' CommandName="Revalue" ID="btnBid" Text="Submit New Valuation" />
</div>
</ItemTemplate>
</asp:DataList>
</ContentTemplate>
</asp:UpdatePanel>
Codebehind:
protected void Page_Load(object sender, EventArgs e)
{
Timer1.Tick += new EventHandler<EventArgs>(Timer1_Tick);
if (!IsPostBack)
{
dataBindList();
}
}
protected void dataBindList()
{
if (Request.QueryString["GroupID"] != null)//Are they coming here with a URL var? If so, build content object
{
List<Item> itemList = ItemManager.getItemsByGroupID(Request.QueryString["GroupID"].ToString());
dlMine.DataSource = itemList.Take(15);
dlMine.DataBind();
}
}
protected void Timer1_Tick(object sender, EventArgs e)
{
dataBindList();
UpdatePanel1.Update();
}
protected void Item_Command(Object sender, DataListCommandEventArgs e)
{
if (e.CommandName == "Revalue")
{
Person p = (Person)Session["Person"];
foreach (DataListItem item in dlMine.Items)
{
string textBoxText = ((TextBox)item.FindControl("txtNewValue")).Text;
Utilities.writeLog("txtNewValue: " + textBoxText, 1);
}
dataBindList();
UpdatePanel1.Update();
}
}
You're rebinding the DataList every time the Timer ticks. All changes in the ItemTemplates of the DataList will be lost on postback.
Why not use Javascript to "pause" the timer whenver one of the textboxes gains focus. This will prevent the Timer from firing and let users finish entering text. Once they leave the textbox of "onblur" then you can restart the timer.
Update
The following will take a bit of effort to make it happen but you can do something like:
When the Timer posts back, before rebinding, iterate over the DataList while searching for textboxes with text in them. Something like:
foreach (DataListItem item in dlMine.Items)
{
//find the textbox control and check for text
}
At this point, you'll know which rows need there textboxes repopulated. Store this information in a hashtable.
In the DataList ItemDataBound event, check each rowID against the hashtable to see if its corresponding textbox exists. If so, repopulate the textbox in the DataList row.
Are you initializing the TextBbox value in your code-behind, perhaps in Page_Load or another page method?
TextBox1.Text = "";
If so, that code is executing on every timer event. You can prevent that like this:
if (! IsPostback) {
TextBox1.Text = "";
}
The first request that hits an ASP.NET page is usually an HTTP GET request, while ASP.NET buttons and update panel events issue HTTP POST requests. So the code above will clear TextBox1 the first time you access the page, but leave the value alone when receiving requests from itself. (If you really are setting the text box's value to its default - empty - you could just remove the initialization code.)

How to update a control outside of an updatepanel?

I am going to show some text in a TextBox, which is located outside of an updatepanel, after checking a CheckBox but I cannot make it work. please help me out ?
Here is my code:
<asp:UpdatePanel runat="server" ID="uplMaster">
<ContentTemplate>
<asp:CheckBox ID="cbShowText" runat="server" Text="Show Some Text" AutoPostBack="true"
OnCheckedChanged="cbShowText_CheckedChanged" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:TextBox ID="txtBox" Text="Empty" runat="server" />
Code Behind:
protected void cbShowText_CheckedChanged(object sender, EventArgs e)
{
txtBox.Text = "Some Text";
}
Thanks in advance :D
P.S. As you might have guessed, I have resembled my problem and that is why I don't want to put the TextBox in the UpdatePanel
I put the TextBox in another UpdatePanel and then called the Update method:
Here is my new code:
<asp:UpdatePanel runat="server" ID="uplMaster" UpdateMode="Always">
<ContentTemplate>
<asp:CheckBox ID="cbShowText" runat="server" Text="Show Some Text" AutoPostBack="true"
OnCheckedChanged="cbShowText_CheckedChanged" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdatePanel runat="server" ID="uplDetail" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="txtBox" Text="Empty" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
Code Behind:
protected void cbShowText_CheckedChanged(object sender, EventArgs e)
{
txtBox.Text = "Some Text";
uplDetail.Update();
}
Hope this helps
The textbox has to be in update panel also.
*Edit:
I am sorry I didn't read your question properly. Perhaps write a javascript function, and call the function from codebehind?
I know its been a while since this was asked, but here is what I did. Like #bla said write a javascript function and call it from code behind.
So in your checked changed call this. The changeText is a javascript function on your page in the header or in a script file.
protected void cbShowText_CheckedChanged(object sender, EventArgs e)
{
ScriptManager.RegisterStartupScript(this, GetType(), "Show Different Text", "changeText();", true);
}
Sample Javascript. Just gets called when checked changed event fires from code behind.
<script type="text/javascript">
function changeText() {
var txt= document.getElementById('<%= txtBox.ClientID %>');
var chk = document.getElementById('<%= cbShowText.ClientID %>');
if (chk.checked === true) {
txt.Text = "Something";
} else {
txt.Text = "Somethingelse";
}
}
</script>
Hope this helps someone.

Resources