Monday, March 26, 2012

Trigger does not work

I have a trigger, which is set to lblProgress.Text property. Once the user clicks the button, the code changes the property, but nothing is displayed untill the onclick event finish. Should not be the Atlas asynchronous?

Default.aspx:

<%

@dotnet.itags.org.PageLanguage="C#"AutoEventWireup="true"CodeFile="Default.aspx.cs"Inherits="_Default" %>

<!

DOCTYPEhtmlPUBLIC"-//W3C//DTD XHTML 1.1//EN""http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<

htmlxmlns="http://www.w3.org/1999/xhtml">

<

headrunat="server"><title>Untitled Page</title>

</

head>

<

body><formid="form1"runat="server"><atlas:ScriptManagerID="scriptManager"EnablePartialRendering="true"runat="server"/>

<atlas:UpdatePanelID="UpdatePanel1"Mode="Conditional"runat="server"><ContentTemplate><asp:ButtonID="btnImport"runat="server"Text="Import"OnClick="btnImport_Click"/><divstyle="background-color:Lime"><h1><asp:LabelID="lblProgress"runat="server"Text=""></asp:Label></h1></div></ContentTemplate><Triggers><atlas:ControlValueTriggerControlID="lblProgress"PropertyName="Text"/></Triggers></atlas:UpdatePanel></form>

</

body>

</

html>

Deafault.aspx.cs

using

System;

using

System.Data;

using

System.Configuration;

using

System.Web;

using

System.Web.Security;

using

System.Web.UI;

using

System.Web.UI.WebControls;

using

System.Web.UI.WebControls.WebParts;

using

System.Web.UI.HtmlControls;

public

partialclass_Default : System.Web.UI.Page

{

protectedvoid Page_Load(object sender,EventArgs e)

{

}

protectedvoid btnImport_Click(object sender,EventArgs e)

{

lblProgress.Text =

"Starting Import...";

System.Threading.

Thread.Sleep(5000);

lblProgress.Text =

"That took awhile...";

}

}

I suspect any of two:

1) Call to button_Onclick is not asynchronous, so the page is waiting for the sub to finish

or

2) Setting lblProgress.Text from code does not trigger the trigger.. That would mean a bug in Atlas I guess

Wonder what you think...


Hi,

Atlas being asynchronous means that when you trigger an update for an UpdatePanel, a HTTP request is sent asynchronously to the web server, i.e. you can do other processing on client-side while the request you sent is being processed and the corresponding response is generated.

But the above response is generated when the partial postback ends, i.e. when the page has completed its whole lifecycle and rendered the HTML for the controls inside the UpdatePanel. This means that when btnImport_Click returns, the Label's text is set to "That took awhile..." and it's this text that will be displayed, since it is this text that it is rendered by the Label control and sent in the response from the server.

OK, sounds logical.How do I make the label to refresh in my long running process, which is executed after click?

I have also noticed that UpdatePanel has update property, but not sure how to use it...


Hi,

there are many approaches to monitor a long running task. The one I would take is to spawn a separate thread to run the task (btw checkthis article) and then poll the server at a specified interval to check the task's status and update a progress bar or other kind of progress indicator.

Without Atlas, this could be done using pure Javascript or a meta refresh. Adding Atlas would probably mean using a Timer control to just send the polling requests asynchronously, and update some controls (the progress indicators) inside an UpdatePanel.

Thanks, I was hoping that this could be done simpler using Atlas, if I could only somehow force the UpdatePanel to refresh itself once the lblProgress.text property is updated, my initial thought was that the trigger would do it, but than reading your post I realized that it is waiting for the btnImport_OnClick sub to finish...

Maybe if I need to have btnImport_OnClick running in seperate thread?


You said:

"...But the above response is generated when the partial postback ends, i.e. when the page has completed its whole lifecycle and rendered the HTML for the controls inside the UpdatePanel. This means that when btnImport_Click returns, the Label's text is set to "That took awhile..." and it's this text that will be displayed, since it is this text that it is rendered by the Label control and sent in the response from the server..."

Can I render page early in my onlick sub? before onclick sub will finish?How would I execute UpdatePanel partial postback once my onlick sub sets the lplProgress.text property?


Hi,

rfurdzik:


Can I render page early in my onlick sub? before onclick sub will finish?


no, because the rendering of a page is a stage in its lifecycle and you cannot modify the Page's lifecycle.

rfurdzik:


How would I execute UpdatePanel partial postback once my onlick sub sets the lplProgress.text property?


A partial postback is just a postback performed asynchronously (i.e. using XMLHTTP). From the Page's lifecycle point of view, a classic postback and a partial postback are pretty much the same thing: the Page goes through all its whole lifecycle, like in a "regular" postback. The difference is that only the HTML of the controls inside the UpdatePanels that are updating is injected into the response.

Also what is the porpouse of UpdatePanel1.Update(); ?

Does it force UpdatePanel to do partial postback?


I have also found this interesting article:http://forums.asp.net/thread/1338483.aspx

Seems that he found a way around to execute partial postback... Wonder how would it be possible to execute partial postback in my code:

protectedvoid btnImport_Click(object sender,EventArgs e)

{

lblProgress.Text =

"Starting Import...";

//Here I would like to execute partial postback of Updatepanel1. I have tried UpdatePanel.Update(), but it did not work

System.Threading.

Thread.Sleep(5000);

//THIS LAST MESSAGE IS ONLY SHOWN

lblProgress.Text =

"That took awhile...";

}


<<A partial postback is just a postback performed asynchronously (i.e. using XMLHTTP). From <<the Page's lifecycle point of view, a classic postback and a partial postback are pretty much <<the same thing: the Page goes through all its whole lifecycle, like in a "regular" postback. The <<difference is that only the HTML of the controls inside the UpdatePanels that are updating is <<injected into the response.

I think I understand now, so the page lifecycle will be finished when the last line of the OnClick sub is executed. Is this correct? In this case I guess I need:

1) to have Onclick to instantiate a seperate thread for long running task and leave the task running.. (what happens if the user closes the browser?)

2) My import class calls delegate method (part of my page, setup in import class constructor),how could I make that delegate method to update the lblProgress.text and execute partial postback?

Do you think that using webservice would make more sense?


After doing some research I realized that you were right,btnClick_ONClick sub is part of Postback, that is why postback request can not be generated within.

So now the question would be which aproach to use?

1) The one suggested by you btnClick_ONClick sub would create a seperate thread. Seems like it should be OK to execute Postback from a seperate thread process...

2) Create control in Atlas and have the control to call webservice. Seems like only the control can update progress label settings, server side code can not...

What would be the cons and prons of eighter aproach?


Instead of worrying about creating a new thread, you could separate the single request into 3 separate requests. The initial button click would cause the UpdatePanel to postback where you can change the text to 'loading', and use RegisterClientScriptBlock to inject javascript which would then initiate a second postback. The second postback would then perform your long operation, and would use RegisterClientScriptBlock to inject javascript to fire the final request which would be responsible for changing your text to 'finished' or whatever you decide.

Hope this helps,
-Tony


That is a great idea! I did not think about it. Would this technique allow the text to change several times during the Long Running Process? For example (1,2,3% etc..)

What is the exact injected java script/atlas code to fire the LRP sub? I do not know java script too much... Do you think that that javascript could call asynchronous web method, which would perform LRP and update the label's text? Will the web method have access to the Page object? Thanks,

Rafal


<< and then poll the server at a specified interval to check the task's status

Is not that waste of resources? I was thinking to have the LRP (Long Running Process) to call page's method (via delegate) and force the page to postback itself (partial postback).

What do you think?

No comments:

Post a Comment