2007-12-18 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / System.Web.Extensions / System.Web.UI / ScriptManager.cs
1 //
2 // ScriptManager.cs
3 //
4 // Author:
5 //   Igor Zelmanovich <igorz@mainsoft.com>
6 //
7 // (C) 2007 Mainsoft, Inc.  http://www.mainsoft.com
8 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Collections.Generic;
32 using System.Text;
33 using System.ComponentModel;
34 using System.Security.Permissions;
35 using System.Collections.Specialized;
36 using System.Collections;
37 using System.Web.Handlers;
38 using System.Reflection;
39 using System.Web.Configuration;
40 using System.Web.UI.HtmlControls;
41 using System.IO;
42 using System.Globalization;
43 using System.Threading;
44 using System.Web.Script.Serialization;
45 using System.Web.Script.Services;
46 using System.Xml;
47
48 namespace System.Web.UI
49 {
50         [ParseChildrenAttribute (true)]
51         [DefaultPropertyAttribute ("Scripts")]
52         [DesignerAttribute ("System.Web.UI.Design.ScriptManagerDesigner, System.Web.Extensions.Design, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
53         [NonVisualControlAttribute]
54         [PersistChildrenAttribute (false)]
55         [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
56         [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
57         public class ScriptManager : Control, IPostBackDataHandler
58         {
59                 // the keywords are used in fomatting async response
60                 const string updatePanel = "updatePanel";
61                 const string hiddenField = "hiddenField";
62                 const string arrayDeclaration = "arrayDeclaration";
63                 const string scriptBlock = "scriptBlock";
64                 const string expando = "expando";
65                 const string onSubmit = "onSubmit";
66                 const string asyncPostBackControlIDs = "asyncPostBackControlIDs";
67                 const string postBackControlIDs = "postBackControlIDs";
68                 const string updatePanelIDs = "updatePanelIDs";
69                 const string asyncPostBackTimeout = "asyncPostBackTimeout";
70                 const string childUpdatePanelIDs = "childUpdatePanelIDs";
71                 const string panelsToRefreshIDs = "panelsToRefreshIDs";
72                 const string formAction = "formAction";
73                 const string dataItem = "dataItem";
74                 const string dataItemJson = "dataItemJson";
75                 const string scriptDispose = "scriptDispose";
76                 const string pageRedirect = "pageRedirect";
77                 const string error = "error";
78                 const string pageTitle = "pageTitle";
79                 const string focus = "focus";
80                 const string scriptContentNoTags = "ScriptContentNoTags";
81                 const string scriptContentWithTags = "ScriptContentWithTags";
82                 const string scriptPath = "ScriptPath";
83
84                 static readonly object ScriptManagerKey = new object ();
85
86                 int _asyncPostBackTimeout = 90;
87                 List<Control> _asyncPostBackControls;
88                 List<Control> _postBackControls;
89                 List<UpdatePanel> _childUpdatePanels;
90                 List<UpdatePanel> _panelsToRefresh;
91                 List<UpdatePanel> _updatePanels;
92                 ScriptReferenceCollection _scripts;
93                 ServiceReferenceCollection _services;
94                 bool _isInAsyncPostBack;
95                 bool _isInPartialRendering;
96                 string _asyncPostBackSourceElementID;
97                 ScriptMode _scriptMode = ScriptMode.Auto;
98                 bool _enableScriptGlobalization;
99                 bool _enableScriptLocalization;
100                 string _scriptPath;
101                 ScriptEntry _clientScriptBlocks;
102                 ScriptEntry _startupScriptBlocks;
103                 ScriptEntry _scriptIncludes;
104                 ScriptEntry _onSubmitStatements;
105                 List<ArrayDeclaration> _arrayDeclarations;
106                 Hashtable _hiddenFields;
107                 List<IScriptControl> _registeredScriptControls;
108                 Dictionary<IExtenderControl, Control> _registeredExtenderControls;
109                 bool? _supportsPartialRendering;
110                 bool _enablePartialRendering = true;
111                 bool _init;
112                 string _panelToRefreshID;
113                 Dictionary<Control, DataItemEntry> _dataItems;
114                 bool _enablePageMethods;
115                 string _controlIDToFocus;
116                 bool _allowCustomErrorsRedirect = true;
117                 string _asyncPostBackErrorMessage;
118                 List<DisposeScriptEntry> _disposeScripts;
119                 List<ScriptReferenceEntry> _scriptToRegister;
120                 bool _loadScriptsBeforeUI = true;
121                 AuthenticationServiceManager _authenticationService;
122                 ProfileServiceManager _profileService;
123
124                 [DefaultValue (true)]
125                 [Category ("Behavior")]
126                 public bool AllowCustomErrorsRedirect {
127                         get {
128                                 return _allowCustomErrorsRedirect;
129                         }
130                         set {
131                                 _allowCustomErrorsRedirect = value;
132                         }
133                 }
134
135                 [Category ("Behavior")]
136                 [DefaultValue ("")]
137                 public string AsyncPostBackErrorMessage {
138                         get {
139                                 if (String.IsNullOrEmpty (_asyncPostBackErrorMessage))
140                                         return String.Empty;
141                                 return _asyncPostBackErrorMessage;
142                         }
143                         set {
144                                 _asyncPostBackErrorMessage = value;
145                         }
146                 }
147
148                 [Browsable (false)]
149                 public string AsyncPostBackSourceElementID {
150                         get {
151                                 if (_asyncPostBackSourceElementID == null)
152                                         return String.Empty;
153                                 return _asyncPostBackSourceElementID;
154                         }
155                 }
156
157                 [DefaultValue (90)]
158                 [Category ("Behavior")]
159                 public int AsyncPostBackTimeout {
160                         get {
161                                 return _asyncPostBackTimeout;
162                         }
163                         set {
164                                 _asyncPostBackTimeout = value;
165                         }
166                 }
167
168                 [Category ("Behavior")]
169                 [MergableProperty (false)]
170                 [DefaultValue ("")]
171                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
172                 [PersistenceMode (PersistenceMode.InnerProperty)]
173                 public AuthenticationServiceManager AuthenticationService {
174                         get {
175                                 if (_authenticationService == null)
176                                         _authenticationService = new AuthenticationServiceManager ();
177                                 return _authenticationService;
178                         }
179                 }
180
181                 [Category ("Behavior")]
182                 [DefaultValue (false)]
183                 public bool EnablePageMethods {
184                         get {
185                                 return _enablePageMethods;
186                         }
187                         set {
188                                 _enablePageMethods = value;
189                         }
190                 }
191
192                 [DefaultValue (true)]
193                 [Category ("Behavior")]
194                 public bool EnablePartialRendering {
195                         get {
196                                 return _enablePartialRendering;
197                         }
198                         set {
199                                 if (_init)
200                                         throw new InvalidOperationException ();
201                                 _enablePartialRendering = value;
202                         }
203                 }
204
205                 [DefaultValue (false)]
206                 [Category ("Behavior")]
207                 public bool EnableScriptGlobalization {
208                         get {
209                                 return _enableScriptGlobalization;
210                         }
211                         set {
212                                 _enableScriptGlobalization = value;
213                         }
214                 }
215
216                 [Category ("Behavior")]
217                 [DefaultValue (false)]
218                 public bool EnableScriptLocalization {
219                         get {
220                                 return _enableScriptLocalization;
221                         }
222                         set {
223                                 _enableScriptLocalization = value;
224                         }
225                 }
226
227                 [Browsable (false)]
228                 public bool IsDebuggingEnabled {
229                         get {
230                                 if (IsDeploymentRetail)
231                                         return false;
232
233                                 CompilationSection compilation = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
234                                 if (!compilation.Debug && (ScriptMode == ScriptMode.Auto || ScriptMode == ScriptMode.Inherit))
235                                         return false;
236
237                                 if (ScriptMode == ScriptMode.Release)
238                                         return false;
239
240                                 return true;
241                         }
242                 }
243
244                 bool IsDeploymentRetail {
245                         get {
246 #if TARGET_J2EE
247                                 return false;
248 #else
249                                 DeploymentSection deployment = (DeploymentSection) WebConfigurationManager.GetSection ("system.web/deployment");
250                                 return deployment.Retail;
251 #endif
252                         }
253                 }
254
255                 [Browsable (false)]
256                 public bool IsInAsyncPostBack {
257                         get {
258                                 return _isInAsyncPostBack;
259                         }
260                 }
261
262                 internal bool IsInPartialRendering {
263                         get {
264                                 return _isInPartialRendering;
265                         }
266                         set {
267                                 _isInPartialRendering = value;
268                         }
269                 }
270
271                 [Category ("Behavior")]
272                 [DefaultValue (true)]
273                 public bool LoadScriptsBeforeUI {
274                         get {
275                                 return _loadScriptsBeforeUI;
276                         }
277                         set {
278                                 _loadScriptsBeforeUI = value;
279                         }
280                 }
281
282                 [PersistenceMode (PersistenceMode.InnerProperty)]
283                 [DefaultValue ("")]
284                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
285                 [Category ("Behavior")]
286                 [MergableProperty (false)]
287                 public ProfileServiceManager ProfileService {
288                         get {
289                                 if (_profileService == null)
290                                         _profileService = new ProfileServiceManager ();
291                                 return _profileService;
292                         }
293                 }
294
295                 [Category ("Behavior")]
296 #if TARGET_J2EE
297                 [MonoLimitation ("The 'Auto' value is the same as 'Debug'.")]
298 #endif
299                 public ScriptMode ScriptMode {
300                         get {
301                                 return _scriptMode;
302                         }
303                         set {
304                                 if (value == ScriptMode.Inherit)
305                                         value = ScriptMode.Auto;
306                                 _scriptMode = value;
307                         }
308                 }
309
310                 [DefaultValue ("")]
311                 [Category ("Behavior")]
312                 public string ScriptPath {
313                         get {
314                                 if (_scriptPath == null)
315                                         return String.Empty;
316                                 return _scriptPath;
317                         }
318                         set {
319                                 _scriptPath = value;
320                         }
321                 }
322
323                 [PersistenceMode (PersistenceMode.InnerProperty)]
324                 [DefaultValue ("")]
325                 [Category ("Behavior")]
326                 [MergableProperty (false)]
327                 public ScriptReferenceCollection Scripts {
328                         get {
329                                 if (_scripts == null)
330                                         _scripts = new ScriptReferenceCollection ();
331
332                                 return _scripts;
333                         }
334                 }
335
336                 [PersistenceMode (PersistenceMode.InnerProperty)]
337                 [DefaultValue ("")]
338                 [MergableProperty (false)]
339                 [Category ("Behavior")]
340                 public ServiceReferenceCollection Services {
341                         get {
342                                 if (_services == null)
343                                         _services = new ServiceReferenceCollection ();
344
345                                 return _services;
346                         }
347                 }
348
349                 [DefaultValue (true)]
350                 [Browsable (false)]
351                 public bool SupportsPartialRendering {
352                         get {
353                                 if (!_supportsPartialRendering.HasValue)
354                                         _supportsPartialRendering = CheckSupportsPartialRendering ();
355                                 return _supportsPartialRendering.Value;
356                         }
357                         set {
358                                 if (_init)
359                                         throw new InvalidOperationException ();
360                                 if (!EnablePartialRendering && value)
361                                         throw new InvalidOperationException ("The SupportsPartialRendering property cannot be set when EnablePartialRendering is false.");
362 #if TARGET_J2EE
363                                 if (!ServerSoftwareSupportsPartialRendering && value)
364                                         throw new InvalidOperationException ("The server software does not supports partial rendering.");
365 #endif
366
367                                 _supportsPartialRendering = value;
368                         }
369                 }
370
371                 bool CheckSupportsPartialRendering () {
372                         if (!EnablePartialRendering)
373                                 return false;
374 #if TARGET_J2EE
375                         if (!ServerSoftwareSupportsPartialRendering)
376                                 return false;
377 #endif
378                         // TODO: consider browser capabilities
379                         return true;
380                 }
381
382 #if TARGET_J2EE
383                 bool? _serverSoftwareSupportsPartialRendering;
384
385                 bool ServerSoftwareSupportsPartialRendering {
386                         get {
387                                 if (!_serverSoftwareSupportsPartialRendering.HasValue)
388                                         _serverSoftwareSupportsPartialRendering = CheckServerSoftwareSupportsPartialRendering ();
389                                 return _serverSoftwareSupportsPartialRendering.Value;
390                         }
391                 }
392
393                 bool CheckServerSoftwareSupportsPartialRendering () {
394                         string serverSoftware = Context.Request.ServerVariables ["SERVER_SOFTWARE"];
395                         if (!String.IsNullOrEmpty (serverSoftware)) {
396
397                                 if (serverSoftware.IndexOf ("WebSphere", StringComparison.OrdinalIgnoreCase) >= 0)
398                                         return false;
399
400                                 if (serverSoftware.IndexOf ("Jetspeed", StringComparison.OrdinalIgnoreCase) >= 0)
401                                         return false;
402                         }
403                         return true;
404                 }
405 #endif
406
407                 [EditorBrowsable (EditorBrowsableState.Never)]
408                 [Browsable (false)]
409                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
410                 public override bool Visible {
411                         get {
412                                 return true;
413                         }
414                         set {
415                                 throw new NotImplementedException ();
416                         }
417                 }
418
419                 [Category ("Action")]
420                 public event EventHandler<AsyncPostBackErrorEventArgs> AsyncPostBackError;
421
422                 [Category ("Action")]
423                 public event EventHandler<ScriptReferenceEventArgs> ResolveScriptReference;
424
425                 public static ScriptManager GetCurrent (Page page) {
426                         if (page == null)
427                                 throw new ArgumentNullException("page");
428                         return (ScriptManager) page.Items [ScriptManagerKey];
429                 }
430
431                 static void SetCurrent (Page page, ScriptManager instance) {
432                         page.Items [ScriptManagerKey] = instance;
433                 }
434
435                 protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection) {
436                         _isInAsyncPostBack = true;
437                         string arg = postCollection [postDataKey];
438                         if (!String.IsNullOrEmpty (arg)) {
439                                 string [] args = arg.Split ('|');
440                                 _panelToRefreshID = args [0];
441                                 _asyncPostBackSourceElementID = args [1];
442                                 return true;
443                         }
444                         return false;
445                 }
446
447                 protected internal virtual void OnAsyncPostBackError (AsyncPostBackErrorEventArgs e) {
448                         if (AsyncPostBackError != null)
449                                 AsyncPostBackError (this, e);
450                 }
451
452                 protected override void OnInit (EventArgs e) {
453                         base.OnInit (e);
454
455                         if (GetCurrent (Page) != null)
456                                 throw new InvalidOperationException ("Only one instance of a ScriptManager can be added to the page.");
457
458                         SetCurrent (Page, this);
459                         Page.Error += new EventHandler (OnPageError);
460                         _init = true;
461                 }
462
463                 void OnPageError (object sender, EventArgs e) {
464                         if (IsInAsyncPostBack)
465                                 OnAsyncPostBackError (new AsyncPostBackErrorEventArgs (Context.Error));
466                 }
467
468                 protected override void OnPreRender (EventArgs e) {
469                         base.OnPreRender (e);
470
471                         Page.PreRenderComplete += new EventHandler (OnPreRenderComplete);
472
473                         if (IsInAsyncPostBack) {
474                                 Page.SetRenderMethodDelegate (RenderPageCallback);
475                         }
476                         else {
477                                 if (EnableScriptGlobalization) {
478                                         CultureInfo culture = Thread.CurrentThread.CurrentCulture;
479                                         string script = String.Format ("var __cultureInfo = '{0}';", JavaScriptSerializer.DefaultSerializer.Serialize (new CultureInfoSerializer (culture)));
480                                         RegisterClientScriptBlock (this, typeof (ScriptManager), "ScriptGlobalization", script, true);
481                                 }
482
483                                 // Register dispose script
484                                 if (_disposeScripts != null && _disposeScripts.Count > 0) {
485                                         StringBuilder sb = new StringBuilder ();
486                                         sb.AppendLine ();
487                                         for (int i = 0; i < _disposeScripts.Count; i++) {
488                                                 DisposeScriptEntry entry = _disposeScripts [i];
489                                                 if (IsMultiForm)
490                                                         sb.Append ("Sys.WebForms.PageRequestManager.getInstance($get(\"" + Page.Form.ClientID + "\"))._registerDisposeScript(\"");
491                                                 else
492                                                 sb.Append ("Sys.WebForms.PageRequestManager.getInstance()._registerDisposeScript(\"");
493                                                 sb.Append (entry.UpdatePanel.ClientID);
494                                                 sb.Append ("\", ");
495                                                 sb.Append (JavaScriptSerializer.DefaultSerializer.Serialize (entry.Script)); //JavaScriptSerializer.Serialize used escape script literal 
496                                                 sb.AppendLine (");");
497                                         }
498                                         RegisterStartupScript (this, typeof (ExtenderControl), "disposeScripts;", sb.ToString (), true);
499                                 }
500
501 #if TARGET_DOTNET
502                                 // to cause webform client script being included
503                                 Page.ClientScript.GetPostBackEventReference (new PostBackOptions (this, null, null, false, false, false, true, true, null));
504 #else
505                                 Page.ClientScript.GetPostBackEventReference (this, null);
506 #endif
507                         }
508                 }
509
510                 void OnPreRenderComplete (object sender, EventArgs e) {
511                         // Resolve Scripts
512                         ScriptReference ajaxScript = new ScriptReference ("MicrosoftAjax.js", String.Empty);
513                         ajaxScript.NotifyScriptLoaded = false;
514                         OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxScript));
515
516                         ScriptReference ajaxWebFormsScript = new ScriptReference ("MicrosoftAjaxWebForms.js", String.Empty);
517                         ajaxWebFormsScript.NotifyScriptLoaded = false;
518                         OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxWebFormsScript));
519
520                         ScriptReference ajaxExtensionScript = null;
521                         ScriptReference ajaxWebFormsExtensionScript = null;
522                         if (IsMultiForm) {
523                                 ajaxExtensionScript = new ScriptReference ("MicrosoftAjaxExtension.js", String.Empty);
524                                 OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxExtensionScript));
525                                 
526                                 ajaxWebFormsExtensionScript = new ScriptReference ("MicrosoftAjaxWebFormsExtension.js", String.Empty);
527                                 OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxWebFormsExtensionScript));
528                         }
529
530                         foreach (ScriptReferenceEntry script in GetScriptReferences ()) {
531                                 OnResolveScriptReference (new ScriptReferenceEventArgs (script.ScriptReference));
532                                 if (!IsInAsyncPostBack || (script.Control != this && HasBeenRendered (script.Control))) {
533                                         if (_scriptToRegister == null)
534                                                 _scriptToRegister = new List<ScriptReferenceEntry> ();
535                                         _scriptToRegister.Add (script);
536                                 }
537                         }
538
539                         if (!IsInAsyncPostBack) {
540                                 // Register Ajax framework script.
541                                 RegisterScriptReference (ajaxScript, true);
542                                 if (IsMultiForm) {
543                                         RegisterScriptReference (ajaxExtensionScript, true);
544                                         RegisterClientScriptBlock (this, typeof (ScriptManager), "Sys.Application", "\nSys.Application._initialize(document.getElementById('" + Page.Form.ClientID + "'));\n", true);
545                                 }
546
547                                 StringBuilder sb = new StringBuilder ();
548                                 sb.AppendLine ("if (typeof(Sys) === 'undefined') throw new Error('ASP.NET Ajax client-side framework failed to load.');");
549
550                                 ScriptingProfileServiceSection profileService = (ScriptingProfileServiceSection) WebConfigurationManager.GetSection ("system.web.extensions/scripting/webServices/profileService");
551                                 if (profileService.Enabled)
552                                         sb.AppendLine ("Sys.Services._ProfileService.DefaultWebServicePath = '" + ResolveClientUrl ("~" + System.Web.Script.Services.ProfileService.DefaultWebServicePath) + "';");
553                                 if (_profileService != null && !String.IsNullOrEmpty (_profileService.Path))
554                                         sb.AppendLine ("Sys.Services.ProfileService.set_path('" + ResolveUrl (_profileService.Path) + "');");
555
556                                 ScriptingAuthenticationServiceSection authenticationService = (ScriptingAuthenticationServiceSection) WebConfigurationManager.GetSection ("system.web.extensions/scripting/webServices/authenticationService");
557                                 if (authenticationService.Enabled)
558                                         sb.AppendLine ("Sys.Services._AuthenticationService.DefaultWebServicePath = '" + ResolveClientUrl ("~/Authentication_JSON_AppService.axd") + "';");
559                                 if (_authenticationService != null && !String.IsNullOrEmpty (_authenticationService.Path))
560                                         sb.AppendLine ("Sys.Services.AuthenticationService.set_path('" + ResolveUrl (_authenticationService.Path) + "');");
561
562                                 RegisterClientScriptBlock (this, typeof (ScriptManager), "Framework", sb.ToString (), true);
563
564                                 RegisterScriptReference (ajaxWebFormsScript, true);
565
566                                 if (IsMultiForm)
567                                         RegisterScriptReference (ajaxWebFormsExtensionScript, true);
568                         }
569
570                         // Register Scripts
571                         if (_scriptToRegister != null)
572                                 for (int i = 0; i < _scriptToRegister.Count; i++)
573                                         RegisterScriptReference (_scriptToRegister [i].ScriptReference, _scriptToRegister [i].LoadScriptsBeforeUI);
574
575                         if (!IsInAsyncPostBack) {
576                                 // Register services
577                                 if (_services != null && _services.Count > 0) {
578                                         for (int i = 0; i < _services.Count; i++) {
579                                                 RegisterServiceReference (_services [i]);
580                                         }
581                                 }
582
583                                 if (EnablePageMethods) {
584                                         LogicalTypeInfo logicalTypeInfo = LogicalTypeInfo.GetLogicalTypeInfo (Page.GetType (), Page.Request.FilePath);
585                                         RegisterClientScriptBlock (this, typeof (ScriptManager), "PageMethods", logicalTypeInfo.Proxy, true);
586                                 }
587
588                                 // Register startup script
589                                 if (IsMultiForm)
590                                         RegisterStartupScript (this, typeof (ExtenderControl), "Sys.Application.initialize();", "Sys.Application.getInstance($get(\"" + Page.Form.ClientID + "\")).initialize();\n", true);
591                                 else
592                                 RegisterStartupScript (this, typeof (ExtenderControl), "Sys.Application.initialize();", "Sys.Application.initialize();\n", true);
593                         }
594                 }
595
596 #if TARGET_J2EE
597                 bool IsMultiForm {
598                         get {
599                                 Mainsoft.Web.Configuration.PagesSection pageSection = (Mainsoft.Web.Configuration.PagesSection) WebConfigurationManager.GetSection ("mainsoft.web/pages");
600                                 if (pageSection != null)
601                                         return pageSection.MultiForm;
602                                 return false;
603                         }
604                 }
605 #else
606                 bool IsMultiForm {
607                         get { return false; }
608                 }
609 #endif
610
611                 static bool HasBeenRendered (Control control) {
612                         if (control == null)
613                                 return false;
614
615                         UpdatePanel parent = control.Parent as UpdatePanel;
616                         if (parent != null && parent.RequiresUpdate)
617                                 return true;
618
619                         return HasBeenRendered (control.Parent);
620                 }
621
622                 IEnumerable<ScriptReferenceEntry> GetScriptReferences () {
623                         if (_scripts != null && _scripts.Count > 0) {
624                                 for (int i = 0; i < _scripts.Count; i++) {
625                                         yield return new ScriptReferenceEntry (this, _scripts [i], LoadScriptsBeforeUI);
626                                 }
627                         }
628
629                         if (_registeredScriptControls != null && _registeredScriptControls.Count > 0) {
630                                 for (int i = 0; i < _registeredScriptControls.Count; i++) {
631                                         IEnumerable<ScriptReference> scripts = _registeredScriptControls [i].GetScriptReferences ();
632                                         if (scripts != null)
633                                                 foreach (ScriptReference s in scripts)
634                                                         yield return new ScriptReferenceEntry ((Control) _registeredScriptControls [i], s, LoadScriptsBeforeUI);
635                                 }
636                         }
637
638                         if (_registeredExtenderControls != null && _registeredExtenderControls.Count > 0) {
639                                 foreach (IExtenderControl ex in _registeredExtenderControls.Keys) {
640                                         IEnumerable<ScriptReference> scripts = ex.GetScriptReferences ();
641                                         if (scripts != null)
642                                                 foreach (ScriptReference s in scripts)
643                                                         yield return new ScriptReferenceEntry ((Control) ex, s, LoadScriptsBeforeUI);
644                                 }
645                         }
646                 }
647
648                 protected virtual void OnResolveScriptReference (ScriptReferenceEventArgs e) {
649                         if (ResolveScriptReference != null)
650                                 ResolveScriptReference (this, e);
651                 }
652
653                 protected virtual void RaisePostDataChangedEvent () {
654                         UpdatePanel up = Page.FindControl (_panelToRefreshID) as UpdatePanel;
655                         if (up != null && up.ChildrenAsTriggers)
656                                 up.Update ();
657                 }
658
659                 public static void RegisterArrayDeclaration (Control control, string arrayName, string arrayValue) {
660                         RegisterArrayDeclaration (control.Page, arrayName, arrayValue);
661                 }
662
663                 public static void RegisterArrayDeclaration (Page page, string arrayName, string arrayValue) {
664                         ScriptManager sm = GetCurrent (page);
665                         if (sm.IsInAsyncPostBack)
666                                 sm.RegisterArrayDeclaration (arrayName, arrayValue);
667                         else
668                                 page.ClientScript.RegisterArrayDeclaration (arrayName, arrayValue);
669                 }
670
671                 void RegisterArrayDeclaration (string arrayName, string arrayValue) {
672                         if (_arrayDeclarations == null)
673                                 _arrayDeclarations = new List<ArrayDeclaration> ();
674
675                         _arrayDeclarations.Add (new ArrayDeclaration (arrayName, arrayValue));
676                 }
677
678                 public void RegisterAsyncPostBackControl (Control control) {
679                         if (control == null)
680                                 return;
681
682                         if (_asyncPostBackControls == null)
683                                 _asyncPostBackControls = new List<Control> ();
684
685                         if (_asyncPostBackControls.Contains (control))
686                                 return;
687
688                         _asyncPostBackControls.Add (control);
689                 }
690
691                 public static void RegisterClientScriptBlock (Control control, Type type, string key, string script, bool addScriptTags) {
692                         RegisterClientScriptBlock (control.Page, type, key, script, addScriptTags);
693                 }
694
695                 public static void RegisterClientScriptBlock (Page page, Type type, string key, string script, bool addScriptTags) {
696                         ScriptManager sm = GetCurrent (page);
697                         if (sm.IsInAsyncPostBack)
698                                 RegisterScript (ref sm._clientScriptBlocks, type, key, script, addScriptTags ? ScriptEntryType.ScriptContentNoTags : ScriptEntryType.ScriptContentWithTags);
699                         else
700                                 page.ClientScript.RegisterClientScriptBlock (type, key, script, addScriptTags);
701                 }
702
703                 public static void RegisterClientScriptInclude (Control control, Type type, string key, string url) {
704                         RegisterClientScriptInclude (control.Page, type, key, url);
705                 }
706
707                 public static void RegisterClientScriptInclude (Page page, Type type, string key, string url) {
708                         ScriptManager sm = GetCurrent (page);
709                         if (sm.IsInAsyncPostBack)
710                                 RegisterScript (ref sm._scriptIncludes, type, key, url, ScriptEntryType.ScriptPath);
711                         else
712                                 page.ClientScript.RegisterClientScriptInclude (type, key, url);
713                 }
714
715                 public static void RegisterClientScriptResource (Control control, Type type, string resourceName) {
716                         RegisterClientScriptResource (control.Page, type, resourceName);
717                 }
718
719                 public static void RegisterClientScriptResource (Page page, Type type, string resourceName) {
720                         RegisterClientScriptInclude (page, type, "resource-" + resourceName, ScriptResourceHandler.GetResourceUrl (type.Assembly, resourceName, true));
721                 }
722
723                 void RegisterScriptReference (ScriptReference script, bool loadScriptsBeforeUI) {
724
725                         bool isDebugMode = IsDeploymentRetail ? false : (script.ScriptModeInternal == ScriptMode.Inherit ? IsDebuggingEnabled : (script.ScriptModeInternal == ScriptMode.Debug));
726                         string url;
727                         if (!String.IsNullOrEmpty (script.Path)) {
728                                 url = GetScriptName (ResolveClientUrl (script.Path), isDebugMode, EnableScriptLocalization ? script.ResourceUICultures : null);
729                         }
730                         else if (!String.IsNullOrEmpty (script.Name)) {
731                                 Assembly assembly;
732                                 if (String.IsNullOrEmpty (script.Assembly))
733                                         assembly = typeof (ScriptManager).Assembly;
734                                 else
735                                         assembly = Assembly.Load (script.Assembly);
736                                 string name = GetScriptName (script.Name, isDebugMode, null);
737                                 if (script.IgnoreScriptPath || String.IsNullOrEmpty (ScriptPath))
738                                         url = ScriptResourceHandler.GetResourceUrl (assembly, name, script.NotifyScriptLoaded);
739                                 else {
740                                         AssemblyName an = assembly.GetName ();
741                                         url = ResolveClientUrl (String.Concat (VirtualPathUtility.AppendTrailingSlash (ScriptPath), an.Name, '/', an.Version, '/', name));
742                                 }
743                         }
744                         else {
745                                 throw new InvalidOperationException ("Name and Path cannot both be empty.");
746                         }
747
748                         if (loadScriptsBeforeUI)
749                                 RegisterClientScriptInclude (this, typeof (ScriptManager), url, url);
750                         else
751                                 RegisterStartupScript (this, typeof (ScriptManager), url, String.Format ("<script src=\"{0}\" type=\"text/javascript\"></script>", url), false);
752                 }
753
754                 static string GetScriptName (string releaseName, bool isDebugMode, string [] supportedUICultures) {
755                         if (!isDebugMode && (supportedUICultures == null || supportedUICultures.Length == 0))
756                                 return releaseName;
757
758                         if (releaseName.Length < 3 || !releaseName.EndsWith (".js", StringComparison.OrdinalIgnoreCase))
759                                 throw new InvalidOperationException (String.Format ("'{0}' is not a valid script path.  The path must end in '.js'.", releaseName));
760
761                         StringBuilder sb = new StringBuilder (releaseName);
762                         sb.Length -= 3;
763                         if (isDebugMode)
764                                 sb.Append (".debug");
765                         string culture = Thread.CurrentThread.CurrentUICulture.Name;
766                         if (supportedUICultures != null && Array.IndexOf<string> (supportedUICultures, culture) >= 0)
767                                 sb.AppendFormat (".{0}", culture);
768                         sb.Append (".js");
769
770                         return sb.ToString ();
771                 }
772
773                 void RegisterServiceReference (ServiceReference serviceReference) {
774                         if (serviceReference.InlineScript) {
775                                 string url = ResolveUrl (serviceReference.Path);
776                                 LogicalTypeInfo logicalTypeInfo = LogicalTypeInfo.GetLogicalTypeInfo (WebServiceParser.GetCompiledType (url, Context), url);
777                                 RegisterClientScriptBlock (this, typeof (ScriptManager), url, logicalTypeInfo.Proxy, true);
778                         }
779                         else {
780 #if TARGET_J2EE
781                                 string pathInfo = "/js.invoke";
782 #else
783                                 string pathInfo = "/js";
784 #endif
785                                 string url = String.Concat (ResolveClientUrl (serviceReference.Path), pathInfo);
786                                 RegisterClientScriptInclude (this, typeof (ScriptManager), url, url);
787                         }
788                 }
789
790                 public void RegisterDataItem (Control control, string dataItem) {
791                         RegisterDataItem (control, dataItem, false);
792                 }
793
794                 public void RegisterDataItem (Control control, string dataItem, bool isJsonSerialized) {
795                         if (!IsInAsyncPostBack)
796                                 throw new InvalidOperationException ("RegisterDataItem can only be called during an async postback.");
797                         if (control == null)
798                                 throw new ArgumentNullException ("control");
799
800                         if (_dataItems == null)
801                                 _dataItems = new Dictionary<Control, DataItemEntry> ();
802
803                         if (_dataItems.ContainsKey (control))
804                                 throw new ArgumentException (String.Format ("'{0}' already has a data item registered.", control.ID), "control");
805
806                         _dataItems.Add (control, new DataItemEntry (dataItem, isJsonSerialized));
807                 }
808
809                 public void RegisterDispose (Control control, string disposeScript) {
810                         if (control == null)
811                                 throw new ArgumentNullException ("control");
812                         if (disposeScript == null)
813                                 throw new ArgumentNullException ("disposeScript");
814
815                         UpdatePanel updatePanel = GetUpdatePanel (control);
816                         if (updatePanel == null)
817                                 return;
818
819                         if (_disposeScripts == null)
820                                 _disposeScripts = new List<DisposeScriptEntry> ();
821                         _disposeScripts.Add (new DisposeScriptEntry (updatePanel, disposeScript));
822                 }
823
824                 static UpdatePanel GetUpdatePanel (Control control) {
825                         if (control == null)
826                                 return null;
827
828                         UpdatePanel parent = control.Parent as UpdatePanel;
829                         if (parent != null)
830                                 return parent;
831
832                         return GetUpdatePanel (control.Parent);
833                 }
834
835                 public static void RegisterExpandoAttribute (Control control, string controlId, string attributeName, string attributeValue, bool encode) {
836                         Page page = control.Page;
837                         ScriptManager sm = GetCurrent (page);
838                         if (sm.IsInAsyncPostBack)
839                                 sm.RegisterExpandoAttribute (controlId, attributeName, attributeValue, encode);
840                         else
841                                 page.ClientScript.RegisterExpandoAttribute (controlId, attributeName, attributeValue, encode);
842                 }
843
844                 private void RegisterExpandoAttribute (string controlId, string attributeName, string attributeValue, bool encode) {
845                         // seems MS do nothing.
846                 }
847
848                 public static void RegisterHiddenField (Control control, string hiddenFieldName, string hiddenFieldInitialValue) {
849                         RegisterHiddenField (control.Page, hiddenFieldName, hiddenFieldInitialValue);
850                 }
851
852                 public static void RegisterHiddenField (Page page, string hiddenFieldName, string hiddenFieldInitialValue) {
853                         ScriptManager sm = GetCurrent (page);
854                         if (sm.IsInAsyncPostBack)
855                                 sm.RegisterHiddenField (hiddenFieldName, hiddenFieldInitialValue);
856                         else
857                                 page.ClientScript.RegisterHiddenField (hiddenFieldName, hiddenFieldInitialValue);
858                 }
859
860                 void RegisterHiddenField (string hiddenFieldName, string hiddenFieldInitialValue) {
861                         if (_hiddenFields == null)
862                                 _hiddenFields = new Hashtable ();
863
864                         if (!_hiddenFields.ContainsKey (hiddenFieldName))
865                                 _hiddenFields.Add (hiddenFieldName, hiddenFieldInitialValue);
866                 }
867
868                 public static void RegisterOnSubmitStatement (Control control, Type type, string key, string script) {
869                         RegisterOnSubmitStatement (control.Page, type, key, script);
870                 }
871
872                 public static void RegisterOnSubmitStatement (Page page, Type type, string key, string script) {
873                         ScriptManager sm = GetCurrent (page);
874                         if (sm.IsInAsyncPostBack)
875                                 RegisterScript (ref sm._onSubmitStatements, type, key, script, ScriptEntryType.OnSubmit);
876                         else
877                                 page.ClientScript.RegisterOnSubmitStatement (type, key, script);
878                 }
879
880                 public void RegisterPostBackControl (Control control) {
881                         if (control == null)
882                                 return;
883
884                         if (_postBackControls == null)
885                                 _postBackControls = new List<Control> ();
886
887                         if (_postBackControls.Contains (control))
888                                 return;
889
890                         _postBackControls.Add (control);
891                 }
892
893                 internal void RegisterUpdatePanel (UpdatePanel updatePanel) {
894                         if (_updatePanels == null)
895                                 _updatePanels = new List<UpdatePanel> ();
896
897                         if (_updatePanels.Contains (updatePanel))
898                                 return;
899
900                         _updatePanels.Add (updatePanel);
901                 }
902
903                 public void RegisterScriptDescriptors (IExtenderControl extenderControl) {
904                         if (extenderControl == null)
905                                 return;
906
907                         if (_registeredExtenderControls == null || !_registeredExtenderControls.ContainsKey (extenderControl))
908                                 return;
909
910                         Control targetControl = _registeredExtenderControls [extenderControl];
911                         RegisterScriptDescriptors (extenderControl.GetScriptDescriptors (targetControl));
912                 }
913
914                 public void RegisterScriptDescriptors (IScriptControl scriptControl) {
915                         if (scriptControl == null)
916                                 return;
917
918                         if (_registeredScriptControls == null || !_registeredScriptControls.Contains (scriptControl))
919                                 return;
920
921                         RegisterScriptDescriptors (scriptControl.GetScriptDescriptors ());
922                 }
923
924                 void RegisterScriptDescriptors (IEnumerable<ScriptDescriptor> scriptDescriptors) {
925                         if (scriptDescriptors == null)
926                                 return;
927                         if (IsInAsyncPostBack && !IsInPartialRendering)
928                                 return;
929
930                         StringBuilder sb = new StringBuilder ();
931                         foreach (ScriptDescriptor scriptDescriptor in scriptDescriptors) {
932                                 if (IsMultiForm) {
933                                         scriptDescriptor.FormID = Page.Form.ClientID;
934                                         sb.AppendLine ("Sys.Application.getInstance($get(\"" + Page.Form.ClientID + "\")).add_init(function() {");
935                                 }
936                                 else
937                                 sb.AppendLine ("Sys.Application.add_init(function() {");
938                                 sb.AppendLine (scriptDescriptor.GetScript ());
939                                 sb.AppendLine ("});");
940                         }
941                         string script = sb.ToString ();
942                         RegisterStartupScript (this, typeof (ExtenderControl), script, script, true);
943                 }
944
945                 public static void RegisterStartupScript (Control control, Type type, string key, string script, bool addScriptTags) {
946                         RegisterStartupScript (control.Page, type, key, script, addScriptTags);
947                 }
948
949                 public static void RegisterStartupScript (Page page, Type type, string key, string script, bool addScriptTags) {
950                         ScriptManager sm = GetCurrent (page);
951                         if (sm.IsInAsyncPostBack)
952                                 RegisterScript (ref sm._startupScriptBlocks, type, key, script, addScriptTags ? ScriptEntryType.ScriptContentNoTags : ScriptEntryType.ScriptContentWithTags);
953                         else
954                                 page.ClientScript.RegisterStartupScript (type, key, script, addScriptTags);
955                 }
956
957                 public void RegisterScriptControl<TScriptControl> (TScriptControl scriptControl) where TScriptControl : Control, IScriptControl {
958                         if (scriptControl == null)
959                                 throw new ArgumentNullException ("scriptControl");
960
961                         if (_registeredScriptControls == null)
962                                 _registeredScriptControls = new List<IScriptControl> ();
963
964                         if (!_registeredScriptControls.Contains (scriptControl))
965                                 _registeredScriptControls.Add (scriptControl);
966                 }
967
968                 public void RegisterExtenderControl<TExtenderControl> (TExtenderControl extenderControl, Control targetControl) where TExtenderControl : Control, IExtenderControl {
969                         if (extenderControl == null)
970                                 throw new ArgumentNullException ("extenderControl");
971                         if (targetControl == null)
972                                 throw new ArgumentNullException ("targetControl");
973
974                         if (_registeredExtenderControls == null)
975                                 _registeredExtenderControls = new Dictionary<IExtenderControl, Control> ();
976
977                         if (!_registeredExtenderControls.ContainsKey (extenderControl))
978                                 _registeredExtenderControls.Add (extenderControl, targetControl);
979                 }
980
981                 static void RegisterScript (ref ScriptEntry scriptList, Type type, string key, string script, ScriptEntryType scriptEntryType) {
982                         ScriptEntry last = null;
983                         ScriptEntry entry = scriptList;
984
985                         while (entry != null) {
986                                 if (entry.Type == type && entry.Key == key)
987                                         return;
988                                 last = entry;
989                                 entry = entry.Next;
990                         }
991
992                         entry = new ScriptEntry (type, key, script, scriptEntryType);
993
994                         if (last != null)
995                                 last.Next = entry;
996                         else
997                                 scriptList = entry;
998                 }
999
1000                 protected override void Render (HtmlTextWriter writer) {
1001                         // MSDN: This method is used by control developers to extend the ScriptManager control. 
1002                         // Notes to Inheritors: 
1003                         // When overriding this method, call the base Render(HtmlTextWriter) method 
1004                         // so that PageRequestManager is rendered on the page.
1005                         if (SupportsPartialRendering) {
1006                                 writer.WriteLine ("<script type=\"text/javascript\">");
1007                                 writer.WriteLine ("//<![CDATA[");
1008                                 writer.WriteLine ("Sys.WebForms.PageRequestManager._initialize('{0}', document.getElementById('{1}'));", UniqueID, Page.Form.ClientID);
1009                                 if (IsMultiForm)
1010                                         writer.WriteLine ("Sys.WebForms.PageRequestManager.getInstance($get(\"{0}\"))._updateControls([{1}], [{2}], [{3}], {4});", Page.Form.ClientID, FormatUpdatePanelIDs (_updatePanels, true), FormatListIDs (_asyncPostBackControls, true), FormatListIDs (_postBackControls, true), AsyncPostBackTimeout);
1011                                 else
1012                                 writer.WriteLine ("Sys.WebForms.PageRequestManager.getInstance()._updateControls([{0}], [{1}], [{2}], {3});", FormatUpdatePanelIDs (_updatePanels, true), FormatListIDs (_asyncPostBackControls, true), FormatListIDs (_postBackControls, true), AsyncPostBackTimeout);
1013                                 writer.WriteLine ("//]]");
1014                                 writer.WriteLine ("</script>");
1015                         }
1016                         base.Render (writer);
1017                 }
1018
1019                 static string FormatUpdatePanelIDs (List<UpdatePanel> list, bool useSingleQuote) {
1020                         if (list == null || list.Count == 0)
1021                                 return null;
1022
1023                         StringBuilder sb = new StringBuilder ();
1024                         for (int i = 0; i < list.Count; i++) {
1025                                 sb.AppendFormat ("{0}{1}{2}{0},", useSingleQuote ? "'" : String.Empty, list [i].ChildrenAsTriggers ? "t" : "f", list [i].UniqueID);
1026                         }
1027                         if (sb.Length > 0)
1028                                 sb.Length--;
1029
1030                         return sb.ToString ();
1031                 }
1032
1033                 static string FormatListIDs<T> (List<T> list, bool useSingleQuote) where T : Control {
1034                         if (list == null || list.Count == 0)
1035                                 return null;
1036
1037                         StringBuilder sb = new StringBuilder ();
1038                         for (int i = 0; i < list.Count; i++) {
1039                                 sb.AppendFormat ("{0}{1}{0},", useSingleQuote ? "'" : String.Empty, list [i].UniqueID);
1040                         }
1041                         if (sb.Length > 0)
1042                                 sb.Length--;
1043
1044                         return sb.ToString ();
1045                 }
1046
1047                 public void SetFocus (Control control) {
1048                         if (control == null)
1049                                 throw new ArgumentNullException ("control");
1050
1051                         if (IsInAsyncPostBack) {
1052                                 EnsureFocusClientScript ();
1053                                 _controlIDToFocus = control.ClientID;
1054                         }
1055                         else
1056                                 Page.SetFocus (control);
1057                 }
1058
1059                 public void SetFocus (string clientID) {
1060                         if (String.IsNullOrEmpty (clientID))
1061                                 throw new ArgumentNullException ("control");
1062
1063                         if (IsInAsyncPostBack) {
1064                                 EnsureFocusClientScript ();
1065                                 _controlIDToFocus = clientID;
1066                         }
1067                         else
1068                                 Page.SetFocus (clientID);
1069                 }
1070
1071                 void EnsureFocusClientScript () {
1072 #if     TARGET_DOTNET
1073                         RegisterClientScriptResource (this, typeof (ClientScriptManager), "Focus.js");
1074 #endif
1075                 }
1076
1077                 #region IPostBackDataHandler Members
1078
1079                 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection) {
1080                         return LoadPostData (postDataKey, postCollection);
1081                 }
1082
1083                 void IPostBackDataHandler.RaisePostDataChangedEvent () {
1084                         RaisePostDataChangedEvent ();
1085                 }
1086
1087                 #endregion
1088
1089                 internal void WriteCallbackException (TextWriter output, Exception ex, bool writeMessage) {
1090 #if TARGET_DOTNET
1091                         if (ex is HttpUnhandledException)
1092                                 ex = ex.InnerException;
1093 #endif
1094                         HttpException httpEx = ex as HttpException;
1095                         string message = AsyncPostBackErrorMessage;
1096                         if (String.IsNullOrEmpty (message) && writeMessage)
1097                                 message = ex.Message;
1098                         WriteCallbackOutput (output, error, httpEx == null ? "500" : httpEx.GetHttpCode ().ToString (), message);
1099                 }
1100
1101                 static internal void WriteCallbackRedirect (TextWriter output, string redirectUrl) {
1102                         WriteCallbackOutput (output, pageRedirect, null, redirectUrl);
1103                 }
1104
1105                 internal void WriteCallbackPanel (TextWriter output, UpdatePanel panel, StringBuilder panelOutput) {
1106                         if (_panelsToRefresh == null)
1107                                 _panelsToRefresh = new List<UpdatePanel> ();
1108                         _panelsToRefresh.Add (panel);
1109
1110                         WriteCallbackOutput (output, updatePanel, panel.ClientID, panelOutput);
1111                 }
1112
1113                 internal void RegisterChildUpdatePanel (UpdatePanel updatePanel) {
1114                         if (_childUpdatePanels == null)
1115                                 _childUpdatePanels = new List<UpdatePanel> ();
1116                         _childUpdatePanels.Add (updatePanel);
1117                 }
1118
1119                 static void WriteCallbackOutput (TextWriter output, string type, string name, object value) {
1120                         string str = value as string;
1121                         StringBuilder sb = value as StringBuilder;
1122                         int length = 0;
1123                         if (str != null)
1124                                 length = str.Length;
1125                         else if (sb != null)
1126                                 length = sb.Length;
1127
1128                         //output.Write ("{0}|{1}|{2}|{3}|", value == null ? 0 : value.Length, type, name, value);
1129                         output.Write (length);
1130                         output.Write ('|');
1131                         output.Write (type);
1132                         output.Write ('|');
1133                         output.Write (name);
1134                         output.Write ('|');
1135                         for (int i = 0; i < length; i++)
1136                                 if (str != null)
1137                                         output.Write (str [i]);
1138                                 else
1139                                         output.Write (sb [i]);
1140                         output.Write ('|');
1141                 }
1142
1143                 void RenderPageCallback (HtmlTextWriter output, Control container) {
1144                         Page page = (Page) container;
1145
1146                         page.Form.SetRenderMethodDelegate (RenderFormCallback);
1147                         HtmlTextParser parser = new HtmlTextParser (output);
1148                         page.Form.RenderControl (parser);
1149
1150                         WriteCallbackOutput (output, asyncPostBackControlIDs, null, FormatListIDs (_asyncPostBackControls, false));
1151                         WriteCallbackOutput (output, postBackControlIDs, null, FormatListIDs (_postBackControls, false));
1152                         WriteCallbackOutput (output, updatePanelIDs, null, FormatUpdatePanelIDs (_updatePanels, false));
1153                         WriteCallbackOutput (output, childUpdatePanelIDs, null, FormatListIDs (_childUpdatePanels, false));
1154                         WriteCallbackOutput (output, panelsToRefreshIDs, null, FormatListIDs (_panelsToRefresh, false));
1155                         WriteCallbackOutput (output, asyncPostBackTimeout, null, AsyncPostBackTimeout.ToString ());
1156                         if (!IsMultiForm)
1157                                 WriteCallbackOutput (output, pageTitle, null, Page.Title);
1158
1159                         if (_dataItems != null)
1160                                 foreach (Control control in _dataItems.Keys) {
1161                                         DataItemEntry entry = _dataItems [control];
1162                                         WriteCallbackOutput (output, entry.IsJsonSerialized ? dataItemJson : dataItem, control.ClientID, entry.DataItem);
1163                                 }
1164
1165                         WriteArrayDeclarations (output);
1166                         WriteScriptBlocks (output, _clientScriptBlocks);
1167                         WriteScriptBlocks (output, _scriptIncludes);
1168                         WriteScriptBlocks (output, _startupScriptBlocks);
1169                         WriteScriptBlocks (output, _onSubmitStatements);
1170                         WriteHiddenFields (output);
1171
1172                         if (!String.IsNullOrEmpty (_controlIDToFocus))
1173                                 WriteCallbackOutput (output, focus, null, _controlIDToFocus);
1174
1175                         if (_disposeScripts != null)
1176                                 for (int i = 0; i < _disposeScripts.Count; i++) {
1177                                         DisposeScriptEntry entry = _disposeScripts [i];
1178                                         if ((_panelsToRefresh != null && _panelsToRefresh.IndexOf (entry.UpdatePanel) >= 0) || (_childUpdatePanels != null && _childUpdatePanels.IndexOf (entry.UpdatePanel) >= 0))
1179                                                 WriteCallbackOutput (output, scriptDispose, entry.UpdatePanel.ClientID, entry.Script);
1180                                 }
1181                 }
1182
1183                 void WriteArrayDeclarations (HtmlTextWriter writer) {
1184                         if (_arrayDeclarations != null) {
1185                                 for (int i = 0; i < _arrayDeclarations.Count; i++) {
1186                                         ArrayDeclaration array = _arrayDeclarations [i];
1187                                         WriteCallbackOutput (writer, arrayDeclaration, array.ArrayName, array.ArrayValue);
1188                                 }
1189                         }
1190                 }
1191
1192                 void WriteScriptBlocks (HtmlTextWriter output, ScriptEntry scriptList) {
1193                         while (scriptList != null) {
1194                                 switch (scriptList.ScriptEntryType) {
1195                                 case ScriptEntryType.ScriptContentNoTags:
1196                                         WriteCallbackOutput (output, scriptBlock, scriptContentNoTags, scriptList.Script);
1197                                         break;
1198                                 case ScriptEntryType.ScriptContentWithTags:
1199                                         string script = SerializeScriptBlock (scriptList);
1200                                         WriteCallbackOutput (output, scriptBlock, scriptContentWithTags, script);
1201                                         break;
1202                                 case ScriptEntryType.ScriptPath:
1203                                         WriteCallbackOutput (output, scriptBlock, scriptPath, scriptList.Script);
1204                                         break;
1205                                 case ScriptEntryType.OnSubmit:
1206                                         WriteCallbackOutput (output, onSubmit, null, scriptList.Script);
1207                                         break;
1208                                 }
1209                                 scriptList = scriptList.Next;
1210                         }
1211                 }
1212
1213                 void WriteHiddenFields (HtmlTextWriter output) {
1214                         if (_hiddenFields == null)
1215                                 return;
1216                         foreach (string key in _hiddenFields.Keys) {
1217                                 string value = _hiddenFields [key] as string;
1218                                 WriteCallbackOutput (output, hiddenField, key, value);
1219                         }
1220                 }
1221
1222                 static string SerializeScriptBlock (ScriptEntry scriptList) {
1223                         try {
1224                                 XmlTextReader reader = new XmlTextReader (new StringReader (scriptList.Script));
1225                                 while (reader.Read ()) {
1226                                         switch (reader.NodeType) {
1227                                         case XmlNodeType.Element:
1228                                                 if (String.Compare ("script", reader.Name, StringComparison.OrdinalIgnoreCase) == 0) {
1229                                                         Dictionary<string, string> dic = new Dictionary<string, string> ();
1230                                                         while (reader.MoveToNextAttribute ()) {
1231                                                                 dic.Add (reader.Name, reader.Value);
1232                                                         }
1233                                                         reader.MoveToContent ();
1234                                                         dic.Add ("text", reader.ReadInnerXml ());
1235                                                         return JavaScriptSerializer.DefaultSerializer.Serialize (dic);
1236                                                 }
1237                                                 break;
1238                                         default:
1239                                                 continue;
1240                                         }
1241                                 }
1242                         }
1243                         catch {
1244                         }
1245                         throw new InvalidOperationException (String.Format ("The script tag registered for type '{0}' and key '{1}' has invalid characters outside of the script tags: {2}. Only properly formatted script tags can be registered.", scriptList.Type, scriptList.Key, scriptList.Script));
1246                 }
1247
1248                 void RenderFormCallback (HtmlTextWriter output, Control container) {
1249                         output = ((HtmlTextParser) output).ResponseOutput;
1250                         HtmlForm form = (HtmlForm) container;
1251                         HtmlTextWriter writer = new HtmlDropWriter (output);
1252                         if (form.HasControls ()) {
1253                                 for (int i = 0; i < form.Controls.Count; i++) {
1254                                         form.Controls [i].RenderControl (writer);
1255                                 }
1256                         }
1257                 }
1258
1259                 internal class AlternativeHtmlTextWriter : HtmlTextWriter
1260                 {
1261                         readonly HtmlTextWriter _responseOutput;
1262
1263                         public HtmlTextWriter ResponseOutput {
1264                                 get { return _responseOutput; }
1265                         }
1266
1267                         public AlternativeHtmlTextWriter (TextWriter writer, HtmlTextWriter responseOutput)
1268                                 : base (writer) {
1269                                 _responseOutput = responseOutput;
1270                         }
1271                 }
1272
1273                 sealed class HtmlTextParser : AlternativeHtmlTextWriter
1274                 {
1275                         bool _done;
1276
1277                         public HtmlTextParser (HtmlTextWriter responseOutput)
1278                                 : base (new TextParser (responseOutput), responseOutput) {
1279                         }
1280
1281                         public override void WriteAttribute (string name, string value) {
1282                                 if (!_done && String.Compare ("action", name, StringComparison.OrdinalIgnoreCase) == 0) {
1283                                         _done = true;
1284                                         ScriptManager.WriteCallbackOutput (ResponseOutput, formAction, null, value);
1285                                         return;
1286                                 }
1287                                 base.WriteAttribute (name, value);
1288                         }
1289                 }
1290
1291                 sealed class TextParser : TextWriter
1292                 {
1293                         int _state;
1294                         char _charState = (char) 255;
1295                         const char nullCharState = (char) 255;
1296                         StringBuilder _sb = new StringBuilder ();
1297                         Dictionary<string, string> _currentField;
1298                         string _currentAttribute;
1299                         readonly HtmlTextWriter _responseOutput;
1300
1301                         public override Encoding Encoding {
1302                                 get { return Encoding.UTF8; }
1303                         }
1304
1305                         public TextParser (HtmlTextWriter responseOutput) {
1306                                 _responseOutput = responseOutput;
1307                         }
1308
1309                         public override void Write (char value) {
1310                                 switch (_state) {
1311                                 case 0:
1312                                         ParseBeginTag (value);
1313                                         break;
1314                                 case 1:
1315                                         ParseAttributeName (value);
1316                                         break;
1317                                 case 2:
1318                                         ParseAttributeValue (value);
1319                                         break;
1320                                 }
1321                         }
1322
1323                         private void ParseAttributeValue (char value) {
1324                                 switch (value) {
1325                                 case '>':
1326                                         ResetState ();
1327                                         break;
1328                                 case '"':
1329                                         _currentField.Add (_currentAttribute, _sb.ToString ());
1330                                         _state = 1;
1331                                         _sb.Length = 0;
1332                                         ProbeWriteOutput ();
1333                                         break;
1334                                 default:
1335                                         _sb.Append (value);
1336                                         break;
1337                                 }
1338                         }
1339
1340                         private void ParseAttributeName (char value) {
1341                                 switch (value) {
1342                                 case '>':
1343                                         ResetState ();
1344                                         break;
1345                                 case ' ':
1346                                 case '=':
1347                                         break;
1348                                 case '"':
1349                                         _currentAttribute = _sb.ToString ();
1350                                         _state = 2;
1351                                         _sb.Length = 0;
1352                                         break;
1353                                 default:
1354                                         _sb.Append (value);
1355                                         break;
1356                                 }
1357                         }
1358
1359                         void ParseBeginTag (char value) {
1360                                 switch (_charState) {
1361                                 case nullCharState:
1362                                         if (value == '<')
1363                                                 _charState = value;
1364                                         break;
1365                                 case '<':
1366                                         if (value == 'i')
1367                                                 _charState = value;
1368                                         else
1369                                                 ResetState ();
1370                                         break;
1371                                 case 'i':
1372                                         if (value == 'n')
1373                                                 _charState = value;
1374                                         else
1375                                                 ResetState ();
1376                                         break;
1377                                 case 'n':
1378                                         if (value == 'p')
1379                                                 _charState = value;
1380                                         else
1381                                                 ResetState ();
1382                                         break;
1383                                 case 'p':
1384                                         if (value == 'u')
1385                                                 _charState = value;
1386                                         else
1387                                                 ResetState ();
1388                                         break;
1389                                 case 'u':
1390                                         if (value == 't')
1391                                                 _charState = value;
1392                                         else
1393                                                 ResetState ();
1394                                         break;
1395                                 case 't':
1396                                         if (value == ' ') {
1397                                                 _state = 1;
1398                                                 _currentField = new Dictionary<string, string> ();
1399                                         }
1400                                         else
1401                                                 ResetState ();
1402                                         break;
1403                                 }
1404                         }
1405
1406                         private void ResetState () {
1407                                 _charState = nullCharState;
1408                                 _state = 0;
1409                                 _sb.Length = 0;
1410                         }
1411
1412                         private void ProbeWriteOutput () {
1413                                 if (!_currentField.ContainsKey ("name"))
1414                                         return;
1415                                 if (!_currentField.ContainsKey ("value"))
1416                                         return;
1417
1418                                 string value = _currentField ["value"];
1419                                 if (String.IsNullOrEmpty (value))
1420                                         return;
1421
1422                                 ScriptManager.WriteCallbackOutput (_responseOutput, hiddenField, _currentField ["name"], HttpUtility.HtmlDecode (value));
1423                         }
1424                 }
1425
1426                 sealed class HtmlDropWriter : AlternativeHtmlTextWriter
1427                 {
1428                         public HtmlDropWriter (HtmlTextWriter responseOutput)
1429                                 : base (new DropWriter (), responseOutput) {
1430                         }
1431                 }
1432
1433                 sealed class DropWriter : TextWriter
1434                 {
1435                         public override Encoding Encoding {
1436                                 get { return Encoding.UTF8; }
1437                         }
1438                 }
1439
1440                 sealed class ScriptEntry
1441                 {
1442                         readonly public Type Type;
1443                         readonly public string Key;
1444                         readonly public string Script;
1445                         readonly public ScriptEntryType ScriptEntryType;
1446                         public ScriptEntry Next;
1447
1448                         public ScriptEntry (Type type, string key, string script, ScriptEntryType scriptEntryType) {
1449                                 Key = key;
1450                                 Type = type;
1451                                 Script = script;
1452                                 ScriptEntryType = scriptEntryType;
1453                         }
1454                 }
1455
1456                 enum ScriptEntryType
1457                 {
1458                         ScriptContentNoTags,
1459                         ScriptContentWithTags,
1460                         ScriptPath,
1461                         OnSubmit
1462                 }
1463
1464                 sealed class ArrayDeclaration
1465                 {
1466                         readonly public string ArrayName;
1467                         readonly public string ArrayValue;
1468
1469                         public ArrayDeclaration (string arrayName, string arrayValue) {
1470                                 ArrayName = arrayName;
1471                                 ArrayValue = arrayValue;
1472                         }
1473                 }
1474
1475                 sealed class CultureInfoSerializer : JavaScriptSerializer.LazyDictionary
1476                 {
1477                         readonly CultureInfo _ci;
1478                         public CultureInfoSerializer (CultureInfo ci) {
1479                                 if (ci == null)
1480                                         throw new ArgumentNullException ("ci");
1481                                 _ci = ci;
1482                         }
1483                         protected override IEnumerator<KeyValuePair<string, object>> GetEnumerator () {
1484                                 yield return new KeyValuePair<string, object> ("name", _ci.Name);
1485                                 yield return new KeyValuePair<string, object> ("numberFormat", _ci.NumberFormat);
1486                                 yield return new KeyValuePair<string, object> ("dateTimeFormat", _ci.DateTimeFormat);
1487                         }
1488                 }
1489
1490                 sealed class ScriptReferenceEntry
1491                 {
1492                         readonly Control _control;
1493                         readonly ScriptReference _scriptReference;
1494                         readonly bool _loadBeforeUI;
1495
1496                         public Control Control { get { return _control; } }
1497                         public ScriptReference ScriptReference { get { return _scriptReference; } }
1498                         public bool LoadScriptsBeforeUI { get { return _loadBeforeUI; } }
1499
1500                         public ScriptReferenceEntry (Control control, ScriptReference scriptReference, bool loadBeforeUI) {
1501                                 _control = control;
1502                                 _scriptReference = scriptReference;
1503                                 _loadBeforeUI = loadBeforeUI;
1504                         }
1505                 }
1506
1507                 sealed class DataItemEntry
1508                 {
1509                         readonly string _dataItem;
1510                         readonly bool _isJsonSerialized;
1511
1512                         public string DataItem { get { return _dataItem; } }
1513                         public bool IsJsonSerialized { get { return _isJsonSerialized; } }
1514
1515                         public DataItemEntry (string dataItem, bool isJsonSerialized) {
1516                                 _dataItem = dataItem;
1517                                 _isJsonSerialized = isJsonSerialized;
1518                         }
1519                 }
1520
1521                 sealed class DisposeScriptEntry
1522                 {
1523                         readonly UpdatePanel _updatePanel;
1524                         readonly string _script;
1525
1526                         public UpdatePanel UpdatePanel { get { return _updatePanel; } }
1527                         public string Script { get { return _script; } }
1528
1529                         public DisposeScriptEntry (UpdatePanel updatePanel, string script) {
1530                                 _updatePanel = updatePanel;
1531                                 _script = script;
1532                         }
1533                 }
1534         }
1535 }