CodeVerge.Net Beta


   Item Entry   Register  Login  
Microsoft News
Asp.Net Forums
IBM Software
Borland Forums
Adobe Forums
Novell Forums



Zone: > Asp.Net Forum > asp.net_ajax.asp.net_ajax_ui Tags:
Item Type: Date Entered: 1/7/2008 4:13:28 PM Date Modified: Subscribers: 0 Subscribe Alert
Rate It:
9.50
XPoints: N/A Replies: 7 Views: 3816 Favorited: 0 Favorite
Can Reply:  No Members Can Edit: No Online: Yes
8 Items, 1 Pages |< << Go >> >|
"O11Y" <>
NewsGroup User
UpdatePanel Woes8/2/2007 8:50:45 AM

0

Hey guys,

Another day, another ajax problem! After 2 days of fighting with a "HelloWorld" app I'm losing the will to live Smile I have a WebPart, containing an UpdatePanel, which retrieves the time and date and some scripts to show / hide it which seem to be working okay. The source code is below. A final point of note is that this is a SharePoint 2007 WebPart. The AJAX framework was installed on a development SharePoint server, the ScriptManager is in the main MasterPage, and the web.config was updated with all the relevant entries.

When one of these WebParts is put onto a page it works fine. When several are put onto a page they seemingly work fine... but not quite. When I tell a Panel/WebPart to update (either through a __doPostBack('upPanel',''); or a myTriggerControl.click(); ) it goes off to perform a callback. If during this time I tell another WebPart to update then the previous call never returns.

So for example; If I click on the "refresh" button inside WebPart1, then before it returns click on the "refresh" button inside WebPart2, then WebPart2 will refresh and WebPart 1 will not.

This is quite a big problem for us, since it makes asynchronous callbacks a nightmare on a page with several WebParts. I've chopped my WebPart down to the bare essentials and still get this issue, which makes me wonder if this is an internal problems with the PageRequestManager or the UpdatePanel (perhaps conflicting with some aspect of SharePoint?).

Could anyone think of a reason why this would be happening and any way to fix it?

Thanks very much,

Olly

1      public class HelloWorldWP : Microsoft.SharePoint.WebPartPages.WebPart  
2        {        
3            UpdatePanel up;
4            UpdateProgress ur;
5            Button but3;
6            Label lab1;
7    
8            protected override void OnInit(EventArgs e)
9            {
10               base.OnInit(e);
11               //disable conflicting Sharepoint functionality
12               EnsureUpdatePanelFixups();
13   
14               up = new UpdatePanel();
15               up.ID = "updatePanel";
16               up.UpdateMode = UpdatePanelUpdateMode.Conditional;
17   
18               //Create an UpdateProgress for the control
19               ur = new UpdateProgress();
20               //Show it immediatly after callback 
21               ur.DisplayAfter = 0;
22               ur.ID = "updateProgress" ;
23               //Associate it with the update panel
24               ur.AssociatedUpdatePanelID = up.ClientID;
25               ur.ProgressTemplate = new MyTemplate();
26              
27               lab1 = new Label();
28               lab1.ID = "label1";
29               lab1.Text = "";
30   
31               but3 = new Button();
32               but3.ID = "updatePBBut3";
33               but3.Text = "Click";
34               but3.Click += new EventHandler(but3_Click);
35   
36               AsyncPostBackTrigger apbt = new AsyncPostBackTrigger();
37               apbt.ControlID = but3.ClientID;
38               up.Triggers.Add(apbt);
39   
40               //Register Controls            
41               up.ContentTemplateContainer.Controls.Add(new LiteralControl("&lt;HR />"));
42               up.ContentTemplateContainer.Controls.Add(lab1);
43               up.ContentTemplateContainer.Controls.Add(new LiteralControl("&lt;HR />"));
44   
45               this.Controls.Add(but3);
46               this.Controls.Add(up);
47               this.Controls.Add(ur);           
48   
49               //These scripts hide the Panel during a callback. This gives the impression that it's loading
50               //THE PROBLEM STILL APPEARS WITH THIS COMMENTED OUT (!)
51               //MakeScripts(); 
52           }      
53   
54           void but3_Click(object sender, EventArgs e)
55           {
56               Random rand = new Random();
57               int i = rand.Next(7) * 1000;
58               System.Threading.Thread.Sleep(i);
59               ((HelloWorldWP)((Button)sender).Parent).lab1.Text = DateTime.Now.ToString();                                            
60           }
61          
62         
63           /// <summary>
64           /// Disable Sharepoint form functions
65           /// </summary>
66           void EnsureUpdatePanelFixups()
67           {            
68               if (this.Page.Form != null)
69               {
70                   //Fetch the onSubmit attributes for the form
71                   string formOnSubmitAtt = this.Page.Form.Attributes["onsubmit"];
72                   //If the attribute is equal to our problematic script...
73                   if (formOnSubmitAtt == "return _spFormOnSubmitWrapper();")
74                   {
75                       //Amend it
76                       this.Page.Form.Attributes["onsubmit"] = "_spFormOnSubmitWrapper();";
77                   }
78               }
79               //Rig up the new action for the form and suppress old function. This is all Sharepoint 
80               //stuff I'm not entirely sure what these functions do.
81               ScriptManager.RegisterStartupScript(this, typeof(HelloWorldWP), "wpCW_UpdatePanelFixup",
82               "_spOriginalFormAction = document.forms[0].action; _spSuppressFormOnSubmitWrapper=true;", true);
83           }
84   
85           public override void RenderControl(HtmlTextWriter writer)
86           {
87               base.RenderControl(writer);            
88           }
89   
90           /// <summary>
91           /// Generates scripts to hide UpdatePanel on a callback
92           /// </summary>
93           void MakeScripts()
94           {        
95                   //Register Event Handlers.
96                   //You should use the ClientScriptManger of the page as opposed to the AJAX
97                   //ScriptManager as the AJAX version re-writes the script block every callback
98                   Page.ClientScript.RegisterStartupScript(typeof(HelloWorldWP), "wpCW_addAjaxHandlers",
99                   "Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(wpCW_beginRequest);\n" +
100                  "Sys.WebForms.PageRequestManager.getInstance().add_endRequest(wpCW_endRequest);\n",
101                      true);
102  
103                  //beingRequest / endRequest are called before / after the client callback is made
104               
105                  //The beginRequest handler hides the panel
106                  Page.ClientScript.RegisterStartupScript(typeof(HelloWorldWP), this.ClientID + "wpCW_beginRequestMethod",
107                  "function wpCW_beginRequest(sender, args) {\n"
108                  + "var id = sender._postBackSettings.panelID.split('|')[1];\n"
109                  + "id = id.replace(/\\$/gi, '_');\n"
110                  + "document.getElementById(id).nextSibling.style.display = 'none';\n"
111                  + "document.getElementById(id).nextSibling.nextSibling.style.display = '';\n"
112                  + "return true;"
113                  + "}\n"
114                  , true);
115  
116                  //The endRequest handler shows the panel
117                  Page.ClientScript.RegisterStartupScript(typeof(HelloWorldWP), this.ClientID + "wpCW_endRequestMethod",
118                  "function wpCW_endRequest(sender, args) {"
119                  + "var id = sender._postBackSettings.panelID.split('|')[1];\n"
120                  + "id = id.replace(/\\$/gi, '_');\n"
121                  + "document.getElementById(id).nextSibling.style.display = '';\n"
122                  + "document.getElementById(id).nextSibling.nextSibling.style.display = 'none';\n"
123                  + "return true;"
124                  + "}\n"
125                  , true);
126                  
127                  //None of this is current working (hence commented out)
128                  //Page.ClientScript.RegisterStartupScript(typeof(HelloWorldWP), this.ClientID + "wpCW_pageLoading",                    
129                  //"window.attachEvent(\"onload\", function(){document.getElementById('" + but3.ClientID + "').click();}); "
130                  //"window.attachEvent(\"onload\", function(){__doPostBack('" + up.ClientID + "',''); return true;}); "
131                  //"window.onload = function() {document.getElementById('" + but3.ClientID + "').click();};"
132                  //, true);
133          }
134      }
 
"O11Y" <>
NewsGroup User
Re: UpdatePanel Woes8/2/2007 9:42:50 AM

0

After further testing I can confirm that this problem is also happening on a regular aspx page. Code:

 

 

 protected void Page_Load(object sender, EventArgs e)
        {
            AddPanel(1);
            AddPanel(2);
            AddPanel(3);
            AddPanel(4);
            AddPanel(5);
            AddPanel(6);
        }
        

        protected void AddPanel(int panels)
        {
            UpdatePanel up;
            UpdateProgress ur;
            Button but3;
            Label lab1;                      

            up = new UpdatePanel();
            up.ID = "updatePanel" + panels.ToString();
            up.UpdateMode = UpdatePanelUpdateMode.Conditional;

            //Create an UpdateProgress for the control
            ur = new UpdateProgress();
            //Show it immediatly after callback (we know it will always take 2 seconds)
            ur.DisplayAfter = 0;
            ur.ID = "updateProgress" + panels.ToString();
            //Associate it with the update panel
            ur.AssociatedUpdatePanelID = up.ClientID;
            //We can't add controls directly to the UpdateProgress. Instead we need to make a custom
            //template and use this instead. MyTemplate is listed below this class.
            ur.ProgressTemplate = new MyTemplate();

            //Set the label equal to the current ticks. This is how we can see a callback has occured 
            //successfully
            lab1 = new Label();
            lab1.ID = "label1" + panels.ToString();
            lab1.Text = "";

            //The button is added to the UpdatePanel for simplicities sake
            //you could add this outside and create an AsyncPostbackTrigger
            but3 = new Button();
            but3.ID = "updatePBBut3" + panels.ToString();
            but3.Text = "Click";
            but3.Click += new EventHandler(but3_Click);
            //but3.Attributes.Add("style", "display:none;");

            AsyncPostBackTrigger apbt = new AsyncPostBackTrigger();
            apbt.ControlID = but3.ClientID;
            up.Triggers.Add(apbt);

            //Register Controls            
            up.ContentTemplateContainer.Controls.Add(new LiteralControl("&lt;HR />"));
            up.ContentTemplateContainer.Controls.Add(lab1);
            up.ContentTemplateContainer.Controls.Add(new LiteralControl("&lt;HR />"));

            this.Form.Controls.Add(but3);
            this.Form.Controls.Add(up);
            this.Form.Controls.Add(ur);

            //These scripts hide the Panel during a callback. This gives the impression that it's loading
            //MakeScripts(); 
        }

        void but3_Click(object sender, EventArgs e)
        {
            Random rand = new Random();
            int i = rand.Next(7) * 1000;
            System.Threading.Thread.Sleep(i);
            string str = ((Button)sender).ID;
            string str1 = str.Replace("updatePBBut3", "label1");
            string str2 = str.Replace("updatePBBut3", "updatePanel");
            
            Control cont = Page.Form.FindControl(str2);
            Control cont2 = ((UpdatePanel)cont).ContentTemplateContainer.FindControl(str1);           
            ((Label)cont2).Text = DateTime.Now.ToString();
        } 
 
"Steve Marx" <>
NewsGroup User
Re: UpdatePanel Woes8/2/2007 11:18:32 PM

0

This is by design... only one postback is allowed to happen at a time.  The default behavior is "last one wins", but you can change that by the method described here in the documentation: http://www.asp.net/AJAX/Documentation/Live/tutorials/ExclusiveAsyncPostback.aspx.  That way you could somehow tell the user to wait until the previous postback is done to try again.

Truly running both in parallel would have strange consequences... for example, the ViewState of the entire page gets passed back and forth during an async postback.  If both postbacks modify the ViewState, how do you merge the two?  If you don't merge, then incorrect information will come back to the server during the next async postback, and that could easily cause some disastrous consequences.

The best I can come up with for this sort of scenario would be to batch the requests by somehow holding on to the new request and resubmitting it when the first one completes.  I don't have an example of doing this, but my sense is that it should be possible (but not easy) with some client-side code.


Steve Marx | ASP.NET AJAX Evangelist | Microsoft Corporation
"chetan.sarode"
NewsGroup User
Re: UpdatePanel Woes8/3/2007 3:41:26 AM

0

Web Parts are not compatible with Update Panel

Controls that Are Not Compatible with UpdatePanel Controls

The following ASP.NET controls are not compatible with partial-page updates, and are therefore not supported inside an UpdatePanel control:

 http://forums.asp.net/t/1066700.aspx


Chetan Sarode
Software Professional,
Extentia Information Technology,
Pune, India.
"Steve Marx" <>
NewsGroup User
Re: UpdatePanel Woes8/3/2007 3:49:37 AM

0

Web Parts are not supported inside an UpdatePanel.

The other way around is fine; UpdatePanels can be inside Web Parts.


Steve Marx | ASP.NET AJAX Evangelist | Microsoft Corporation
"O11Y" <>
NewsGroup User
Re: UpdatePanel Woes8/3/2007 8:29:30 AM

0

Thanks Steve, this is exactly what I was looking for. Just out of interest would it be possible to tell the requests to execute synchronously - so that if a user makes a series of clicks then they will execute in order? 

Cheers,

"O11Y" <>
NewsGroup User
Re: UpdatePanel Woes8/3/2007 1:20:48 PM

0

This is a slightly unorthodox, but functional way of achieving this functionality. The example below is for an UpdatePanel that contains a button to refresh. For different setups you will need to parse the sender._postBackSettings.panelID.sd in a different way and perform some more advanced functions to determine how to postback the event in DoSomething.

Also, posting back in this manner requires the server to perform the full page lifecycle. If bandwidth is an issue then this will kill your site. One final point of note is that I'm using a setTimeout to poll the prm every second. You could try playing with this value to improve performance.

Hope it helps someone

Queuing async postbacks for an UpdatePanel

Sys.Application.add_load(ApplicationLoadHandler)
function ApplicationLoadHandler(sender, args)
{
    if (!Sys.WebForms.PageRequestManager.getInstance().get_isInAsyncPostBack())
    {
      Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(InitializeRequest);
    }
}

function InitializeRequest(sender, args)
{ 
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    if (prm.get_isInAsyncPostBack())                            
    {
          var id = sender._postBackSettings.panelID.split('|')[1];
          id = id.replace(/\\$/gi, '_');              
          args.set_cancel(true);
          setTimeout("DoTryAgain('" + id + "')", 1000);                
    }                     
}



function DoTryAgain(id)
{
    var prm = Sys.WebForms.PageRequestManager.getInstance();
    if (prm.get_isInAsyncPostBack())                                
          setTimeout("DoTryAgain('" + id + "')", 1000);   
    else
        document.getElementById(id).click();                          
}

if(typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded()
 
"chetan.sarode"
NewsGroup User
Re: UpdatePanel Woes8/6/2007 3:34:21 AM

0

Thats nice Smile


Chetan Sarode
Software Professional,
Extentia Information Technology,
Pune, India.
8 Items, 1 Pages |< << Go >> >|



Free Download:






   
  Privacy | Contact Us
All Times Are GMT