Update Panels in Repeaters - Why can't multiple callback at the same time? - asp.net

I have an update panel in a repeater
(Edit: I removed Runat and Id attributes to make the post look cleaner)
<asp:Repeater>
<ItemTemplate>
<asp:UpdatePanel UpdateMode="Conditional">
<ContentTemplate>
<asp:LinkButton onclick="btnCallback_Click" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:UpdateProgress DisplayAfter="0">
<ProgressTemplate>
<img src="spinningProgress.gif" />
</ProgressTemplate>
</asp:UpdateProgress>
</ItemTemplate>
</asp:Repeater>
The idea is here that you click the LinkButton and it calls back and performs a server side action for that data item. This works perfectly fine for one item. However, if I click the button for every item without waiting for the previous update panel to finish the call back, it appears to cancel the previous callback.
Can UpdatePanels not perform call backs at the same time? Is there anyway I can make it so you don't need to wait before clicking on the next button?

Every AJAX request performed via UpdatePanel cancels any previous one (if previous is still running). This is how it is built. UpdatePanel AJAX request passes portions of ViewState along with request. It is impossible (at least very hard) to reconcile multiple arbitrary viewstates brought back by concurrent ajax calls. I heard that this was the primary reason MS chose to build it that way.
EDIT: use jQuery and have fun :-)

I had the same problem before. But i finded out that making some tricks can allow you to implement multiple ajax calbacks in different microsoft update panels.
function ProcessCallBack(uniqID)
{
var prm = Sys.WebForms.PageRequestManager.getInstance();
//checking if there is somewhere perforimg of callback
if (prm.get_isInAsyncPostBack())
{
setTimeout("ProcessCallBack()", 1000); //here we move execution of callback
//for 1 sec forward
}
else
{
__doPostBack(uniqID,'');
}
return false;
}
So you must add calling of that function to your button or control on client-side click. uniqID is the unique identifier of server control, you can get it on server side.
So enjoy, and remember that everything is possible, but for some is needed a lot of time todo :-)
I was thinking about that, why guys from microsoft didn't implement such thing :-)

Related

Disable page refresh after button click ASP.NET

I have an asp button that looks like this:
Default.aspx
<asp:button id="button1" runat="server" Text="clickme" onclick="function" />
Default.aspx.cs
protected void function(object sender EventArgs e)
{
// Do some calculation
}
However, whenever I press the button, the entire page gets refreshed. I have looked on this site and found many solutions, but none of them really works for my project. Here are some of the suggested solutions:
set onclick="return false;" // but then how do I run the function in the code-behind?
use !IsPostBack in Page_Load // but the page still refreshes completely. I don't want Page_Load to be called at all.
Disable AutoEventWireup. // making this true or false doesn't make a difference.
Does anyone have a solution to this, or is it really impossible?
I would place the control inside of an Update panel.
To do so, you would also need a script manager above it, so something like this:
<asp:ScriptManager runat="server" ID="sm">
</asp:ScriptManager>
<asp:updatepanel runat="server">
<ContentTemplate>
<asp:button id="button1" runat="server" Text="clickme" onclick="function" />
</ContentTemplate>
</asp:updatepanel>
if a control inside the update panel does a postback, it will only reload the part of the page inside of the upate panel.Here is a link you may find useful from the MSDN site.
I think there is a fundamental misunderstanding here of how ASP.Net works.
When a user first requests your page, an instance of your Page class is created. The ASP.Net framework runs through the page lifecycle with this page instance in order to generate html. The html response is then sent to the user's browser. When the browser receives the response it renders the page for the user. Here's the key: by the time rendering is complete, your page class instance was probably already collected by the .Net garbage collector. It's gone, never to be seen again.
From here on out, everything your page does that needs to run on the server, including your method, is the result of an entirely new http request from the browser. The user clicks the button, a new http request is posted to the web server, the entire page lifecycle runs again, from beginning to end, with a brand new instance of the page class, and an entirely new response is sent to the browser to be re-rendered from scratch. That's how ASP.Net (and pretty much any other web-based technology) works at its core.
Fortunately, there are some things you can do to get around this. One option is to put most of your current Page_Load code into an if (!IsPostBack) { } block. Another option is to set up your method with the [WebMethod] attribute and make an ajax request to the method from the button. Other options include calling web services from custom javascript and ASP.Net UpdatePanel controls.
What works best will depend on what other things are on the page that user might have changed.
That is normal behavior for asp.net, you are actually causing a postback of the the page in order for the associated event to be called on the server.
I would suggest working with update panels but if you just need something to happen on the backend without it causing any major change on the web page, I would use jquery and a web service. The main reason for me is that update panels create huge viewstate objects.
Have a look here for asp.net ajax : http://www.asp.net/ajax
And here for an example of jquery and wcf : http://www.codeproject.com/Articles/132809/Calling-WCF-Services-using-jQuery
I have a similar problem. this answer helps me a lot. in your asp button.<asp:button id="button1" runat="server" Text="clickme" OnClientClick="return SomeMethod();" /> and in the SomeMethod which is a js method do your logic like manipulating your page then return false as the mentioned answer suggest.

How can I persist the changes of a text box when it loses focus?

I have several text boxes on a page. I want to save the text in the corresponding TextBox on LostFocus. It is to ensure the data is not lost when power failure or internet connectivity is lost. How can I accomplish something like this?
Another solution would be to use an UpdatePanel. You could then leverage server-side events rather than an event handler. You're markup might look something like this:
<asp:ScriptManager ID="ScriptManager" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server">
<asp:TextBox ID="SomeTextBox" runat="server" TextChanged="SomeTextBox_TextChanged" AutoPostBack="true" />
</asp:UpdatePanel>
</asp:ScriptManager
and then in the TextChanged handler you could do your work.
Explanation: the TextChanged event will fire on the text box in which the text was actually changed when the post back occurs. The AutoPostBack property is necessary so that the page will in fact post back when the text box loses focus.
One final thing to remember, you will probably need to leverage this.IsPostBack on the page in the Load handler because every time a control is updated it's going to reconstruct the page. It's common that logic in the Load handler only needs to execute one time, but that would pose a problem if you didn't check to see if it was a post back because then it would execute every single time you left a text box.
Use jquery.
First on attach blur event handler, where you call ajax method to server passing new value of the textbox.
Handle this ajax event on serverside and write your data to the database or anywhere else.
Here is a piece of code that may help.
$('#textbox_id').blur(function() {
$.ajax({url:"handler_url.ashx?textbox_value=" + $('#textbox_id').val()});
});
Then create your ashx handler on server and handle your requests with ProcessRequest method. From there you will have access to Request.QueryString where new value of textbox will be stored.

UpdatePanel update without trigger button

I have an UpdatePanel with ContentTemplate specified. When page loads, user can do some AJAX work in other part of the page. Then, after that work is finished, I would like to update only content inside UpdatePanel, but without pressing any buttons etc. I should be done automatically using JavaScript when previously started AJAX work finishes. How to do it without manual clicking on the trigger button?
EDIT:
Ok, I've followed that _doPostBack rule, and whole page is posted.
<asp:UpdatePanel ID="panelAttachments" runat="server">
<ContentTemplate>
........
</ContentTemplate>
</asp:UpdatePanel>
<input type="text" name="test" onchange="__doPostBack('<%=panelAttachments.UniqueID %>',''); return false;" />
</td>
Thanks, Pawel
To refresh an update panel from javascript:
__doPostBack(updatePanelUniqueID,'');
The first parameter is the UniqueID (not CientID) of the UpdatePanel.The 2nd parameter is optional arguments you can pass which will be available to your server code. Both are stored in hidden form fields by ASP.NET, you can access them in codebehind:
Request.Form["__EVENTTARGET"];
Request.Form["__EVENTARGUMENT"];
But if you just want to refresh a panel and don't need to pass any additional info from the client, you can ignore then 2nd argument.
If you look at the HTML generated by ASP.NET for an async postback control, you'll see it's exactly this.

ASP.NET sync issues

I am having a weird issue with a web form I'm working on that seems related to some async stuff going on. Basically, I need to do the following:
UserInputPanel.Visible = False
ProgressPanel.Visible = True
ResultsSet = New DataSet()
GetResults(ResultsSet)
FillOutput()
ProgressPanel.Visible = False
OutputPanel.Visible = True
This code all runs as the result of clicking a button on the WebForm. The call to GetResults(ResultsSet) is a lengthy one, thus the need to show the panel ProgressPanel. Problem is, the call to GetResults is happening before my ProgressPanel actually shows. If I comment out the call to GetResults and the lines that follow, then ProgressPanel shows up no problems. How can I force the first two lines to execute and show on the page before the call to GetResults happens?
It sounds like you need to use the UpdateProgress control instead of trying to trigger your own. When your form button is clicked, all the code on the server side click handler runs before any response is sent to the client.
You need something like this instead of your ProgressPanel:
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
</ProgressTemplate>
</asp:UpdateProgress>
The contents of the ProgressTemplate will automatically be displayed whent the asynchronous postback starts, and then will hide once it is complete.
To hide the UserInputPanel, create a javascript function like the following (use jQuery or some other client-side js framework for more robust cross browser code):
function hideUserInput() {
document.getElementById('<%=UserInputPanel.ClientID%>').style.visibility="hidden";
}
and attach this function to your button's OnClientClick property:
<asp:button id="YourButton"
text="Submit"
onclientclick="hideUserInput()"
runat="server" onclick="YourButton_Click" />

firing ASP.NET Events from javascript

I'm doing some straight up asynchronous calls from javascript using the XMLHTTPRequest object. On success, with certain return values, I would like to do an asynchonous post back on an update panel and run some server side methods. This is about how I'm implementing it now:
<script language="javascript">
function AjaxCallback_Success(objAjax) {
if (objAjax.responseText == "refresh") {
document.getElementById('<%= btnHidden.ClientID %>').click();
}
}
</script>
<asp:UpdatePanel ID="upStatus" runat="server">
<ContentTemplate>
<asp:Button ID="btnHidden" runat="server" style="display: none;" OnClick="SomeMethod" />
<asp:DropDownList ID="ddlStatus" field="Orders_Status" parent="Orders" runat="server">
</asp:DropDownList>
</ContentTemplate>
</asp:UpdatePanel>
This has to do with work flow. If while you are working on an order, someone invoices it, then the options available in the status drop down actually changes. So a timed even checks for changes and if there is a change, which wouldn't normally happen, the update panel posts back and the drop down list gets re-bound to a new data table based on various return values from the ajax response text.
My original code is actually much more complicated than this, but I've abstracted just enough to make my concept clearer. Is there a better, cleaner way to do this by dropping the hidden button and making a straight javascript call that will cause an update panel to asynchonously postback and run a server side method?
Be very careful with UpdatePanels, they can be very heavy if not used properly as I explain here.
But the JavaScript for submitting a form is:
__doPostBack('eventTarget','eventArguments');
So in your example you'd have something like:
__doPostBack('<%= btnHidden.ClientID %>','');
You can remove the hidden button and call
__doPostBack('upStatus','');
This will cause an asynchronous update for that update panel

Resources