Wednesday, March 28, 2012

Multiple UpdatePanels in my web app

Hi,

In my asp.net 2.0 web app running under IE 6.0, myprimary UpdatePanel is working well in conjuction with the Timercontrol.

The problem I encounter is when I open a newaspx page in a new window (launched via javascript window.open() ). Thenew aspx page that opens in this window also has its own UpdatePanel(with a different ID of course) and a Timer control.

Notonly is my new window NOT updating via the UpdatePanel, but when Iclose this window and return control to the main window, my main windowcompletely hangs up. My browers goes white, the normal URL appears inthe address bar, but the site appears to be trying to refreshindefinitely. It appears to be an infinite refresh loop.

BasicallyI have an Orders.aspx page which displays customer orders (within aRepeater control). I have the timer set at 30 seconds and theUpdatePanel works fine. Now if a customer clicks on the "Submit Orders"link, I launch the SubmitOrders.aspx page in a new window (viajavascript window.open). SubmitOrders also contains an UpdatePanel andTimer control, which does NOT work.

I shall post the code to show you.

Thank you,

Bob

By the way, all my pages are linked to a master page. Here's what my SubmitOrders.aspx page looks like :

<%@. Page Language="C#" MasterPageFile ... >

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">

<asp:ScriptManager runat="server"></asp:ScriptManager
<asp:Timer ID="TimerSubmit" Interval="3000" runat="server"></asp:Timer>
...

<asp:UpdatePanel ID="UpdatePanelSubmit" UpdateMode="Always" runat="server">
<ContentTemplate>

<asp:GridView ID="GridView1" ... >

<Columns>...

</Columns>...

</asp:GridView
</ContentTemplate>

<Triggers>
<asp:AsyncPostBackTrigger ControlID="TimerSubmit" />
</Triggers
</asp:UpdatePanel>

...


</asp:Content>

<> This is the page that does not appear to be update. Then when I close it, my main Orders.aspx page hangs up.

<>Thank you for your advice and/or suggestions.

<>Bob

<>------


Bob,

It looks like you set your timer to 3 milliseconds instead 30 seconds.

30 seconds = 30,000, please verify


I set it to 3 seconds (3000 ms).

Thanks for checking...

Bob


Bob,

I too have seen a similar behavior in my web app. I have a "inbox" of records that is refreshed via a timer every 2 minutes. Users can create a new record via a new form opened as yours is (window.open) and once they click the save button the record will be asynchronously saved (form fields are within update panel) and a status message (success/failure) is displayed (via ModalPopupExtender) to indicate the result. Once the user clicks the "OK" button on the status modal it calls a javascript function (OnOkScript property) that triggers a remote refresh of the Inbox web form. Once the new record form is closed the Inbox page is usually "broken" (sometimes it happens on 1st new record, sometimes after 2nd/3rd update but it eventually happens) - all actions that trigger an async postback time out (e.g. grid sort, grid select, trying to add a new record (new window just hangs and is blank)). It seems to me that there is something that is killing the session or connection but there are no errors being generated that would give me an indication as to what is causing the problem. My thread that discusses my problem can be found here:

http://forums.asp.net/thread/1688076.aspx

Michael Jensen


Hi Michael,

Yes, I also noticed that the browserfreeze-up doesn't occur the first time. It usually happens the secondor third time I close the second window.

<> In my case, Ithink I figure out one of the potentially several reasons. I have ajavascript function that refreshes the main page when I close thesecond page. However, I think my old refresh technique is obsolete dueto the fact I'm now using Timers and UpdatePanels. Here's what I mean :

On my SubmitOrders aspx page (launched in a new window), the user can click on theReturn button and go back to the main orders page using this button :

<><asp:Button ID="btnClose" OnClientClick="javascript:OnAbort();" Width="" Text="Return" />

The OnAbort function looks like this :

function OnAbort(pActionFrom) {

// initialize client and user vars here ...

opener.location.href = 'orders.aspx?client=' + escape(lcClient) + '&user_id=' + escape(lcUser_Id) + '&action=UnlockAll';
self.close();
return;
}

I think there's a clash between thisopener.location.href command and the ajax UpdatePanel. In other words,if my refresh occurs at the same time as the Ajax-style update then mybrower freezes (my timer is set to 3 seconds on the main orders page).

Anyhow, I think I still have other issue but so far this is what I discovered...

Bob


Hi Michael,

Yes, I also noticed that the browserfreeze-up doesn't occur the first time. It usually happens the secondor third time I close the second window.

<> In my case, Ithink I figure out one of the potentially several reasons. I have ajavascript function that refreshes the main page when I close thesecond page. However, I think my old refresh technique is obsolete dueto the fact I'm now using Timers and UpdatePanels. Here's what I mean :

On my SubmitOrders aspx page (launched in a new window), the user can click on theReturn button and go back to the main orders page using this button :

<><asp:Button ID="btnClose" OnClientClick="javascript:OnAbort();" Width="" Text="Return" />

The OnAbort function looks like this :

function OnAbort(pActionFrom) {

// initialize client and user vars here ...

opener.location.href = 'orders.aspx?client=' + escape(lcClient) + '&user_id=' + escape(lcUser_Id) + '&action=UnlockAll';
self.close();
return;
}

I think there's a clash between thisopener.location.href command and the ajax UpdatePanel. In other words,if my refresh occurs at the same time as the Ajax-style update then mybrower freezes (my timer is set to 3 seconds on the main orders page).

Anyhow, I think I still have other issue but so far this is what I discovered...

Bob


Bob,

This is my implementation of performing a parent form refresh - this script is called when users click the OK button on the child form modal status popup (e.g. "The record was saved successfully.") (ModalPopupExtender property --> OnOkScript="RefreshParent(false)"):

// Function Name: RefreshParent
// Function Purpose: Trigger a async refresh of the parent form.
// Author: Michael Jensen
function RefreshParent(autoClose){

// put function within try-catch-finally block
try
{
// debug statement - set debug = true to view
if (debug) alert(">>Entered JavaScript:RefreshParent");

// define local variables
var control = GetParentDocumentElement('HiddenRefreshButton');

if(control != null)
{
control.click();
}
// if autoClose = true
if(autoClose)
{
self.close();
}
// return false
return false;
}
catch(ex)
{
var msg = "JavaScript:RefreshParent failed. ";
alert(msg + ex.messsage);
}
finally
{
// debug statement = set debug = true to view
if (debug) alert("<<Exiting JavaScript:RefreshParent");
}
}

My parent form has a hidden (style="display: none;") asp:button that is set as an AsyncPostBack trigger for the update panel so when the click event is triggered via the JavaScript it refreshes the "inbox" (gridview). It works great and I love the new functionality it brings to the table but it consistently breaks after the first/second refresh as we both have noticed. I too thought that it was causing a conflict with the timer so I tried setting the refresh behavior to use "window.opener.document.forms[0].submit()" (hard postback) but this did not resolve the issue with the parent form breaking. The autoClose is used by some child forms of the new record form that facilitate adding sub-child records so that the sub-child forms auto close after triggering a refresh of the parent record form.

Regards,

Michael Jensen


Bob,

I forgot to mention also that I have been unable to reproduce this problem when using Firefox/Netscape. I am using IE6 on my dev system but my app testers have seen the problem in IE7 as well.

Regards


I like the scripting technique you're using. Let me ask this: if youdisable the Timer control, does the parent window still break ? If itdoesn't break then I believe our conflict theory is correct.

Ifdisabling the timer doesn't make a difference, can I suggest doing whatI tried. I set my timer to 3 seconds (3000 ms) and just close the childwindow without any refreshes whatsoever. At this point just let thetimer take care of the refresh on its own. Please tell me if that works.

Theproblem I just discovered is more of a application-design issue. I usedto do a "hard" refresh as you mentioned with this script (upon closingthe child window):

opener.location.href = 'orders.aspx?client=' + escape(lcClient) + '&user_id=' + escape(lcUser_Id) + '&action=UnlockAll';

Ifyou'll notice, however, I was also using my custom "action" parameter.This notified the Orders.aspx page that I needed to unlock that user'srecords. I guess I just lost that functionality by letting the timertake control of the refresh. Perhaps I'll use a session varinstead...gotta think about it...

Regards,

Bob


would you mind showing me the code for the hidden refresh button on your aspx page ?

Thanks,

Bob


Bob,

Here is the code for the hidden Asp:Button:

<div style="display: none;"> <asp:Button ID="HiddenRefreshButton" runat="server" OnClick="HiddenRefreshButton_OnClick" /></div>

I also tried the two tests you mentioned previously. I blocked the child form from triggering a refresh both with the timer enabled and disabled and the parent form still broke. A child initiated refresh with the timer disabled also broke the parent form. I am also getting some sporadic parsing errors that I was not getting before. Back to the drawing board I guess. Will keep you posted.


I ended up successfully using your idea toaccess the hidden button from the child window using this js code (opener.document was previously the missing key in my js code).

Keep in mind that I usemaster pages, so the rendered HTML page declares my hidden refresh button asID="ctl00_ContentPlaceHolder1_hidRefreshImg" (as opposed to the simpler ID="hidRefreshImg").

function OnAbortSubmit() { // This fires when I close the child window

var hidRefresh =opener.document.getElementById("ctl00_ContentPlaceHolder1_hidRefreshImg");// hard coding the id work fine...
hidRefresh.click();

self.close();
return;

}


I put this on my main Orders.aspx pagewithin my UpdatePanel:

<> <div style="display:none">
<asp:Button ID="hidRefreshImg" runat="server" />
</div>

I do use a technique for dynamically injectingjavascript vars at runtime in order to store the actual aspx-generatedID for my controls, but the variable does not work for me in thisscenario. I'll share the technique if your interested.

Thanks again,

Bob


Bob,

Eureka!!! I figured out the problem. I have JavaScript methods that are called by my child forms when a user is clicking the "Close/Cancel" button that verify there are no unsaved changes before closing otherwise user is prompted to verify that they want to discard changes or not. If they confirmed that they wanted to close the web form I was simply calling window.close() but was not returning any value from the function which I think was a problem because the Close/Cancel button is located within the update panel (because the image changes depending on the scope of the form (e.g. new or view)) and thus despite closing the window I think somehow the AJAX event lifecycle was being initiated but terminated abnormally because of the form closing. I added a "return false;" in my finally clause for all the functions that are used in the closing of a child web form and lo and behold my parent form no longer breaks (see example function below - added statement is bolded). I hope this solution also works for you. Also, thanks for the compliment on js scripting technique - if you can get it, I highly recommend using CodeSmith Pro to develop coding templates that will help enforce standards and practices on code items (classes, methods, properties, etc.):

// Function Name: CloseVisitLog
// Function Purpose: Close the visit log form.
// Author: Michael Jensen
function CloseVisitLog(scope)
{
// put function within try-catch-finally block
try
{
// debug statement - set debug = true to view
if (debug) alert(">>Entered JavaScript:CloseVisitLog");

// declare local variables
var unsavedChanges = GetUnsavedChangesFlag();

if(scope == "new")
{
// make sure the user really wants to cancel
if (confirm("Are you sure you want to cancel creation of this visit log entry?"))
{
// close the window
window.close();
}
else
{
return false;
}
}
else if(scope == "view")
{
// if there are unsaved changes make sure the user really
// wants to close
if(unsavedChanges == "true")
{
if (confirm("There are unsaved changes, are you sure you want to close?"))
{
// close the window
window.close();
}
else
{
return false;
}
}
else
{
// close the window
window.close();
}
}
}
catch(ex)
{
var msg = "JavaScript:CloseVisitLog failed. ";
alert(msg + ex.messsage);
}
finally
{
// debug statement = set debug = true to view
if (debug) alert("<<Exiting JavaScript:CloseVisitLog");
// return false to prevent postback when window is closing
// otherwise parent form AJAX will break
return false;
}
}


Hi Michael,

I'm glad to hear you found yoursolution. I tried experiementing with the return false idea, but itstill breaks when the parent form's Timer fires off.

Here's my on abort routine again with your return false idea :

function OnAbortSubmit() { // This fires when I close the child window

var hidRefresh =opener.document.getElementById("ctl00_ContentPlaceHolder1_hidRefreshImg");
hidRefresh.click();

try{
self.close();
}
finally{
return false;
}

}

So is the "return false" statement reached even though I'm doing aself.close() before that ? In any case, I think what I'll do is justcomment out the hidRefresh.click() statement due to the fact that Ialready have a 3-second timer on the parent form. So in the worse-casethe user will wait three seconds to see the main window update. Unlessof course there was a way that I could momentarily disable the Timercontrol, then re-enable it when my main page reloads...I'll look intothat...

Thanks for the CodeSmith recommendation.

Regards,

Bob

No comments:

Post a Comment