UpdatePanel with TextBox.OnTextChanged Async Event not firing - asp.net

I have a textbox for inputting a desired username. When the user types in their name and the input loses focus, I want to send an async postback to check whether their username is already taken. This works fine in the cases that no error is thrown, but I want to handle errors, as well.
Per MSDN, I've added an AsyncPostBackError handler to the ScriptManager. I've tried this both on every page load and only on non-postback page loads.
I have my TextBox in an UpdatePanel like so:
<asp:UpdatePanel ID="upLogin" runat="server" ChildrenAsTriggers="true" UpdateMode="Conditional">
<ContentTemplate>
<asp:TextBox ID="tbLogin" runat="server" placeholder="username"
OnTextChanged="tbLogin_TextChanged" required />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="tbLogin" EventName="TextChanged" />
</Triggers>
</asp:UpdatePanel>
In the code-behind, I have:
protected void Page_Load(object sender, EventArgs e)
{
ScriptManager.GetCurrent(Page).AsyncPostBackError +=
BootstrapLogin_AsyncPostBackError;
}
void BootstrapLogin_AsyncPostBackError(object sender, AsyncPostBackErrorEventArgs e)
{
tbLogin.Attributes.Remove("data-success");
tbLogin.Attributes["data-error-message"] = myErrorMessage;
}
protected void tbLogin_TextChanged(object sender, EventArgs e)
{
throw new Exception("what?");
}
I also added Async="true" to my Default.aspx Page markup.
When I have AutoPostBack="true" on my TextBox, the error is thrown and the AsyncPostBackError handler is never called. For some reason, during the postback, Page.IsAsync is false. I suspect this is the reason (or indication of why) it's not being handled.
When I set AutoPostBack="false", no postback is fired at all, despite the specified trigger.
Ideas?

It looks like following code doesn't work as intended
ScriptManager.GetCurrent(Page).AsyncPostBackError +=
BootstrapLogin_AsyncPostBackError;
Instead of that I just set the OnAsyncPostBackError property of the ScriptManager in markup and it worked with AutoPostback = "True" in your TextBox.
<asp:ScriptManager ID="ScriptManager1" runat="server" OnAsyncPostBackError="BootstrapLogin_AsyncPostBackError"></asp:ScriptManager>
Not sure why your code didn't work. It picks up the correct ScriptManager.
UPDATE
Solved it!
I should refresh my knowledge on Page lifecycle :(
Actually, we should add your code into Page_Init rather than in Page_Load. Following works perfectly.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
ScriptManager.GetCurrent(Page).AsyncPostBackError +=
BootstrapLogin_AsyncPostBackError;
}
UPDATE 2
See this screen capture
Hope this helped!

Related

Updatepanel in ascx refreshing the whole control

I've got a sitecore proejct, in which I have prepared a sub-layout in the form of an ascx User Control. I need to set up cascading drop downs in this user control, and based on what I found an UpdatePanel is the way to go. The problem is that the UpdatePanel seems to be refreshing the whole control, which I don't think is the correct behaviour.
I understand there are some similar questions on SO, but none of the solutions worked for me. I'm also beginning to suspect that this may be a Sitecore specific issue.
Here is a code sample of the user control:
<p><%= MyItem.Text %>" /></p>
<asp:UpdatePanel ID="LocationFilterUpdatePanel" runat="server">
<ContentTemplate>
<asp:DropDownList ID="DDL1" OnSelectedIndexChanged="DDL1_SelectedIndexChanged" runat="server" AutoPostBack="true">
</asp:DropDownList>
<asp:DropDownList ID="DDL2" OnSelectedIndexChanged="DDL2_SelectedIndexChanged" runat="server" AutoPostBack="true">
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
And the Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!System.Web.UI.ScriptManager.GetCurrent(Page).IsInAsyncPostBack)
{
var context = new SitecoreContext();
//Get Model from Sitecore
DDL1.DataSource = Model.Data;
DDL1.DataValueField = "Id";
DDL1.DataTextField = "Name";
DDL1.DataBind();
}
}
protected void DDL1_SelectedIndexChanged(object sender, EventArgs e)
{
var context = new SitecoreContext();
//Get Model from Sitecore
DDL2.DataSource = Model.Data;
DDL2.DataValueField = "Id";
DDL2.DataTextField = "Name";
DDL2.DataBind();
}
protected void DDL2_SelectedIndexChanged(object sender, EventArgs e)
{
}
The page loads fine, but (when debugging) changing the DDL1's index it will show a Null exception in MyItem.Text. This is outside the control panel. Note: I have also added a script manager.
There are plenty of things I've tried. Setting different update modes, updated the AjaxToolkit in my solution by executing Install-Package AjaxControlToolkit from the Package Manager Console... but the behaviour remains the same.
Thank you.
Put the databinding for DDL1 to the OnInit, rather than the Page_Load.
And don't include the if statement in there, just do the databind.
After the OnInit the selected values will be correctly set and you will be able to access the DDL1's options in the other event handlers.
You have asp:DropDownList control with an AutoPostBack set to true.
Remove the AutoPostBack=true from the Dropdownlist control and set an Async trigger for your UpdatePanel, set to the Dropdownlist and its eventname="SelectedIndexChanged"
This is a know issue, and you find a lot of documentation about it.

OnClick Event for Button in GridView is not working

Here is my DataGridView
<asp:GridView ID="gvPredstave" runat="server" CssClass="gridview"
AlternatingRowStyle-CssClass="even" AutoGenerateColumns="True">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="btnRezervisi" runat="server" Text="Rezervisi" onclick="Button1_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
This is my code for click on button in GridView
protected void Button1_Click(object sender, EventArgs e)
{
Response.Redirect("AktivneRezervacije.aspx?korisnicko_ime=" + korisnicko_ime);
conn.Close();
}
When i click on button i got this error in browser:
Invalid postback or callback argument. Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%# Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.
Does anybody know the reason why is this happening.
I tried with EnableEventValidation="false" but it doesn't work.
I recreated the error using your gridView and binding it. The answer lies on the Page_Load event. If you have it like this:
protected void Page_Load(object sender, EventArgs e)
{
bindGridView(); //code to bind the GridView
}
You will get the exception. Change it to:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
bindGridView();
}
}
and you should not get the error anymore.
if the page is in postback,
you have two ways to make it work
either add a postback event on your gridview
or control in on page load.
Regarding to the conn.close();
close first the connection after redirecting it to another page.
happy coding.

How can I create an ASP.NET AJAX UpdatePanel that refreshes a Repeater when a DropdownList control has the Selected Item changed?

I have a simple problem. I have a dropdown list and a databound repeater. When the user changes the selection in the dropdown list I would like to reload the repeater. I would like to use ASP.NET AJAX so that this does not refresh the entire page. I have read the ASP.NET AJAX documentation over and over but can not find a clear explanation of how to do this. Here is part of my ASPX page
<asp:ScriptManager id="smScriptManager" runat="server" />
<asp:DropDownList id="ddlLocations" runat="server" AutoPostback="true" OnSelectedIndexChanged="ddlLocations_SelectedIndexChanged">
<asp:ListItem Text="Location 1" Value="1"></asp:ListItem>
<asp:ListItem Text="Location 2" Value="2"></asp:ListItem>
<asp:ListItem Text="Location 2" Value="3"></asp:ListItem>
</asp:DropDownList>
<asp:UpdatePanel id="upUpdatePanel" runat="server" ChildrenAsTriggers="false" UpdateMode="Conditional">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ddlLocations" EventName="SelectedIndexChanged" />
</Triggers>
<ContentTemplate>
<asp:Repeater id="rptItems" runat="server">
<ItemTemplate>
... data bound fields for each location go here ...
</ItemTemplate>
</asp:Repeater>
</ContentTemplate>
</asp:UpdatePanel>
In my code behind I have a separate data binding function that binds the repeater. Currently I call it on Page Load only if Page.IsPostBack = false. So the page loads fine the first time and the Repeater is loaded with all of the data for Location 1 (since it is selected). I also have code in the "ddlLocations_OnSelectedIndexChanged" function that calls the data binding function. In fact, if I strip out all of the AJAX/UpdatePanel stuff the page works fine (although it does a complete page refresh).
With the AJAX stuff, when the user selects Location 2 or Location 3 I get the following JS error:
Message: Sys.WebForms.PageRequestManagerServerErrorException: StartIndex cannot be less than zero.
Parameter name: startIndex
Line: 4723
Char: 21
Code: 0
URI: http://localhost/ScriptResource.axd?d=sTWt9V9Pb7V99ft1kYaE90l3bO7maFff4srx6ham1O6ideYDjPbZU5dv5QJjmzBCPxFQIGrdN2PIuOG7y3evLrZF4ETSZ2de6iwiLo9yZ4w0RvtADl-5JZXm0C_1eyn2F6p6fNX5ZDkxi6yJHF0czKc2lWjUlRrkShaVa4T1l8BPah6A0&t=ffffffff9bdfdd38
Anyone have any ideas why this is happening? Am I doing something wrong? I feel like I don't quite understand how the UpdatePanel works. I get the feeling that I should first set up the page to work without the UpdatePanel/AJAX stuff (and do a complete page refresh). Then add in the UpdatePanel/AJAX stuff and somehow the code magically figures out that I just want the updated Repeater HTML. Or something like that. Any ideas?
UPDATE:
Here is how my back end code works
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
this.BindData();
}
}
protected void BindData()
{
this.BindDropDownList();
this.BindRepeater();
}
protected void BindDropDownList()
{
...call code for binding drop down list...
(ddlLocations is actually databound - I simplified it above for purposes of this post)
}
protected void BindRepeater()
{
...call code for binding the repeater...
}
protected void ddlLocations_SelectedIndexChanged(object sender, EventArgs e)
{
this.BindRepeater();
}
Thanks,
Corey

Can I put a Timer in Ajax updatePannel in a masterpage?

I made a very simple pannel updating wich will query a database and show a message on masterpage through a label.
Thus, I've put an updatePannel with a label and a timer within (obviously with a scriptManager) in my site's masterpage.
However, when I try to interact with the timer1 object, I receive an error message: "object not set to an instance of an object". I not receive this message when placing the schema in a blank page (without masterpage).
I must to run the query in masterpage because the users need to receive information whatever they are in my site.
How can I correctly place the components to do this work? what I'm doing wrong?
Thanks!
I just tried it within a master page without a problem. Here is the relevant code:
<asp:ToolkitScriptManager ID="ToolkitScriptManager1" runat="server" />
<asp:UpdatePanel ID="updMessage" runat="server">
<ContentTemplate>
<asp:Label ID="lblMessage" runat="server" />
<asp:Timer ID="tmrMessage" Interval="5000" ontick="tmrMessage_Tick" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
From master page code-behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Session["Message"] = 1;
}
}
protected void tmrMessage_Tick(object sender, EventArgs e)
{
int message = (int)Session["Message"];
lblMessage.Text = message.ToString();
Session["Message"] = ++message;
}
The problem was where I was putting the panel, label and timer. I put in contentPlaceHolder, where the problem occours. Now I put the control in the form tag, then the problem is solved.

UpdatePanel wrapped around a user control

I have a user control which contains some buttons and a placeholder. Those buttons cause controls to be added/removed from placeholder. Everything works fine.
Now I want to put this user control in a page, and wrap it in an updatepanel like so:
<asp:UpdatePanel ChildrenAsTriggers="true" ID="UpdatePanelFoo" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<grid:tablegrid ID="tablegrid_chapters" runat="server" SomeProperty="bar" />
</ContentTemplate>
</asp:UpdatePanel>
When I run the page, it's still doing a full postback when I hit one of the buttons inside the user control. What am I doing wrong, and how can I remedy this?
Update:
protected void Page_Init()
{
ScriptManager scr = ScriptManager.GetCurrent(this.Page);
Response.Write("EnablePartialRendering: " + scr.EnablePartialRendering);
}
Outputs "EnablePartialRendering: true"
Make sure you have EnablePartialRendering=true on your ScriptManager in the page.
Update
It looks like your UserControl has no events to be looking for...you have 2 options here. Move the UpdatePanel inside the UserControl .ascx so it can see the button events as children to rig up or add an event for it to see, to do that try something like this:
public event EventHandler Click;
void btn_del_Click(object sender, EventArgs e)
{
if (NumberOfRowControls > 0)
{
var rowToWhack = panel_rows.Controls.Children().Single(x => x.ID == "myrow" + (NumberOfRowControls - 1));
panel_rows.Controls.Remove(rowToWhack);
NumberOfRowControls--;
}
if(Click != null) Click(this, e);
}
void btn_add_Click(object sender, EventArgs e)
{
var row = NewRow(NumberOfRowControls);
panel_rows.Controls.Add(row);
if(Click != null) Click(this, e);
}
And update the UpdatePanel to be looking for it:
<asp:UpdatePanel ID="UpdatePanelFoo" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<grid:tablegrid ID="tablegrid_chapters" runat="server" SomeProperty="bar" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="tablegrid_chapters" EventName="Click">
</Triggers>
</asp:UpdatePanel>
Make sure you add a ScriptManager as well to the page, otherwise there's no UpdatePanel functionality.

Resources