Hey guys,
Another day, another ajax problem! After 2 days of fighting with a "HelloWorld" app I'm losing the will to live
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("<HR />"));
42 up.ContentTemplateContainer.Controls.Add(lab1);
43 up.ContentTemplateContainer.Controls.Add(new LiteralControl("<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 }