2003-12-17 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.UI / Page.cs
1 //
2 // System.Web.UI.Page.cs
3 //
4 // Authors:
5 //   Duncan Mak  (duncan@ximian.com)
6 //   Gonzalo Paniagua (gonzalo@ximian.com)
7 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
8 //
9 // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
10 // (c) 2003 Novell, Inc. (http://www.novell.com)
11 //
12
13 using System;
14 using System.Collections;
15 using System.Collections.Specialized;
16 using System.ComponentModel;
17 using System.ComponentModel.Design;
18 using System.ComponentModel.Design.Serialization;
19 using System.Globalization;
20 using System.IO;
21 using System.Security.Principal;
22 using System.Text;
23 using System.Threading;
24 using System.Web;
25 using System.Web.Caching;
26 using System.Web.SessionState;
27 using System.Web.Util;
28
29 namespace System.Web.UI
30 {
31
32 // TODO FIXME missing the IRootDesigner Attribute
33 [DefaultEvent ("Load"), DesignerCategory ("ASPXCodeBehind")]
34 [ToolboxItem (false)]
35 [Designer ("System.Web.UI.Design.ControlDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
36 [RootDesignerSerializer ("Microsoft.VSDesigner.WebForms.RootCodeDomSerializer, " + Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design, true)]
37 public class Page : TemplateControl, IHttpHandler
38 {
39         private bool _viewState = true;
40         private bool _viewStateMac;
41         private string _errorPage;
42         private bool _isValid;
43         private bool _smartNavigation;
44         private int _transactionMode;
45         private HttpContext _context;
46         private ValidatorCollection _validators;
47         private bool renderingForm;
48         private object _savedViewState;
49         private ArrayList _requiresPostBack;
50         private ArrayList _requiresPostBackCopy;
51         private ArrayList requiresPostDataChanged;
52         private IPostBackEventHandler requiresRaiseEvent;
53         private NameValueCollection secondPostData;
54         private bool requiresPostBackScript;
55         private bool postBackScriptRendered;
56         private Hashtable registeredArrayDeclares;
57         Hashtable clientScriptBlocks;
58         Hashtable startupScriptBlocks;
59         Hashtable hiddenFields;
60         internal Hashtable submitStatements;
61         bool handleViewState;
62
63         [EditorBrowsable (EditorBrowsableState.Never)]
64         protected const string postEventArgumentID = "__EVENTARGUMENT";
65         [EditorBrowsable (EditorBrowsableState.Never)]
66         protected const string postEventSourceID = "__EVENTTARGET";
67
68         #region Constructor
69         public Page ()
70         {
71                 Page = this;
72         }
73
74         #endregion              
75
76         #region Properties
77
78         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
79         [Browsable (false)]
80         public HttpApplicationState Application
81         {
82                 get { return _context.Application; }
83         }
84
85         [EditorBrowsable (EditorBrowsableState.Never)]
86         protected bool AspCompatMode
87         {
88                 set { throw new NotImplementedException (); }
89         }
90
91         [EditorBrowsable (EditorBrowsableState.Never)]
92         protected bool Buffer
93         {
94                 set { Response.BufferOutput = value; }
95         }
96
97         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
98         [Browsable (false)]
99         public Cache Cache
100         {
101                 get { return _context.Cache; }
102         }
103
104         [MonoTODO]
105         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
106         [Browsable (false), DefaultValue ("")]
107         [WebSysDescription ("Value do override the automatic browser detection and force the page to use the specified browser.")]
108         public string ClientTarget
109         {
110                 get { throw new NotImplementedException (); }
111                 set { throw new NotImplementedException (); }
112         }
113
114         [EditorBrowsable (EditorBrowsableState.Never)]
115         protected int CodePage
116         {
117                 set { Response.ContentEncoding = Encoding.GetEncoding (value); }
118         }
119
120         [EditorBrowsable (EditorBrowsableState.Never)]
121         protected string ContentType
122         {
123                 set { Response.ContentType = value; }
124         }
125
126         protected override HttpContext Context
127         {
128                 get { return _context; }
129         }
130
131         [EditorBrowsable (EditorBrowsableState.Never)]
132         protected string Culture
133         {
134                 set { Thread.CurrentThread.CurrentCulture = new CultureInfo (value); }
135         }
136
137         [Browsable (false)]
138         public override bool EnableViewState
139         {
140                 get { return _viewState; }
141                 set { _viewState = value; }
142         }
143
144         [EditorBrowsable (EditorBrowsableState.Never)]
145         protected bool EnableViewStateMac
146         {
147                 get { return _viewStateMac; }
148                 set { _viewStateMac = value; }
149         }
150
151         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
152         [Browsable (false), DefaultValue ("")]
153         [WebSysDescription ("The URL of a page used for error redirection.")]
154         public string ErrorPage
155         {
156                 get { return _errorPage; }
157                 set {
158                         _errorPage = value;
159                         if (_context != null)
160                                 _context.ErrorPage = value;
161                 }
162         }
163
164         [EditorBrowsable (EditorBrowsableState.Never)]
165         protected ArrayList FileDependencies
166         {
167                 set {
168                         if (Response != null)
169                                 Response.AddFileDependencies (value);
170                 }
171         }
172
173         [Browsable (false)]
174         public override string ID
175         {
176                 get { return base.ID; }
177                 set { base.ID = value; }
178         }
179
180         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
181         [Browsable (false)]
182         public bool IsPostBack
183         {
184                 get {
185                         return (0 == String.Compare (Request.HttpMethod, "POST", true));
186                 }
187         }
188
189         [EditorBrowsable (EditorBrowsableState.Never), Browsable (false)]
190         public bool IsReusable {
191                 get { return false; }
192         }
193
194         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
195         [Browsable (false)]
196         public bool IsValid
197         {
198                 get { return _isValid; }
199         }
200
201         [EditorBrowsable (EditorBrowsableState.Never)]
202         protected int LCID {
203                 set { Thread.CurrentThread.CurrentCulture = new CultureInfo (value); }
204         }
205
206         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
207         [Browsable (false)]
208         public HttpRequest Request
209         {
210                 get { return _context.Request; }
211         }
212
213         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
214         [Browsable (false)]
215         public HttpResponse Response
216         {
217                 get { return _context.Response; }
218         }
219
220         [EditorBrowsable (EditorBrowsableState.Never)]
221         protected string ResponseEncoding
222         {
223                 set { Response.ContentEncoding = Encoding.GetEncoding (value); }
224         }
225
226         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
227         [Browsable (false)]
228         public HttpServerUtility Server
229         {
230                 get {
231                         return Context.Server;
232                 }
233         }
234
235         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
236         [Browsable (false)]
237         public virtual HttpSessionState Session
238         {
239                 get { return _context.Session; }
240         }
241
242         [Browsable (false)]
243         public bool SmartNavigation
244         {
245                 get { return _smartNavigation; }
246                 set { _smartNavigation = value; }
247         }
248
249         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
250         [Browsable (false)]
251         public TraceContext Trace
252         {
253                 get { return Context.Trace; }
254         }
255
256         [EditorBrowsable (EditorBrowsableState.Never)]
257         protected bool TraceEnabled
258         {
259                 set { Trace.IsEnabled = value; }
260         }
261
262         [EditorBrowsable (EditorBrowsableState.Never)]
263         protected TraceMode TraceModeValue
264         {
265                 set { Trace.TraceMode = value; }
266         }
267
268         [EditorBrowsable (EditorBrowsableState.Never)]
269         protected int TransactionMode
270         {
271                 set { _transactionMode = value; }
272         }
273
274         [EditorBrowsable (EditorBrowsableState.Never)]
275         protected string UICulture
276         {
277                 set { Thread.CurrentThread.CurrentUICulture = new CultureInfo (value); }
278         }
279
280         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
281         [Browsable (false)]
282         public IPrincipal User
283         {
284                 get { return _context.User; }
285         }
286
287         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
288         [Browsable (false)]
289         public ValidatorCollection Validators
290         {
291                 get { 
292                         if (_validators == null)
293                                 _validators = new ValidatorCollection ();
294                         return _validators;
295                 }
296         }
297
298         [Browsable (false)]
299         public override bool Visible
300         {
301                 get { return base.Visible; }
302                 set { base.Visible = value; }
303         }
304
305         #endregion
306
307         #region Methods
308
309         [MonoTODO]
310         [EditorBrowsable (EditorBrowsableState.Never)]
311         protected IAsyncResult AspCompatBeginProcessRequest (HttpContext context,
312                                                              AsyncCallback cb, 
313                                                              object extraData)
314         {
315                 throw new NotImplementedException ();
316         }
317
318         [MonoTODO]
319         [EditorBrowsable (EditorBrowsableState.Never)]
320         protected void AspCompatEndProcessRequest (IAsyncResult result)
321         {
322                 throw new NotImplementedException ();
323         }
324         
325         [EditorBrowsable (EditorBrowsableState.Advanced)]
326         protected virtual HtmlTextWriter CreateHtmlTextWriter (TextWriter tw)
327         {
328                 return new HtmlTextWriter (tw);
329         }
330
331         [MonoTODO]
332         [EditorBrowsable (EditorBrowsableState.Never)]
333         public void DesignerInitialize ()
334         {
335                 throw new NotImplementedException ();
336         }
337
338         [EditorBrowsable (EditorBrowsableState.Advanced)]
339         protected virtual NameValueCollection DeterminePostBackMode ()
340         {
341                 if (_context == null)
342                         return null;
343
344                 HttpRequest req = _context.Request;
345                 if (req == null)
346                         return null;
347
348                 NameValueCollection coll = null;
349                 if (IsPostBack)
350                         coll =  req.Form;
351                 else 
352                         coll = req.QueryString;
353
354                 
355                 if (coll == null || coll ["__VIEWSTATE"] == null)
356                         return null;
357
358                 return coll;
359         }
360         
361         [EditorBrowsable (EditorBrowsableState.Advanced)]
362         public string GetPostBackClientEvent (Control control, string argument)
363         {
364                 return GetPostBackEventReference (control, argument);
365         }
366
367         [EditorBrowsable (EditorBrowsableState.Advanced)]
368         public string GetPostBackClientHyperlink (Control control, string argument)
369         {
370                 return "javascript:" + GetPostBackEventReference (control, argument);
371         }
372
373         [EditorBrowsable (EditorBrowsableState.Advanced)]
374         public string GetPostBackEventReference (Control control)
375         {
376                 return GetPostBackEventReference (control, "");
377         }
378
379         [EditorBrowsable (EditorBrowsableState.Advanced)]
380         public string GetPostBackEventReference (Control control, string argument)
381         {
382                 RequiresPostBackScript ();
383                 return String.Format ("__doPostBack('{0}','{1}')", control.UniqueID, argument);
384         }
385
386         internal void RequiresPostBackScript ()
387         {
388                 requiresPostBackScript = true;
389         }
390
391         [EditorBrowsable (EditorBrowsableState.Never)]
392         public virtual int GetTypeHashCode ()
393         {
394                 return 0;
395         }
396
397         [MonoTODO]
398         [EditorBrowsable (EditorBrowsableState.Never)]
399         protected virtual void InitOutputCache (int duration,
400                                                 string varyByHeader,
401                                                 string varyByCustom,
402                                                 OutputCacheLocation location,
403                                                 string varyByParam)
404         {
405                 HttpCachePolicy cache = _context.Response.Cache;
406
407                 switch (location) {
408                 case OutputCacheLocation.Any:
409                         cache.SetCacheability (HttpCacheability.Public);
410                         cache.SetMaxAge (new TimeSpan (0, 0, duration));                
411                         cache.SetLastModified (_context.Timestamp);
412                         goto case OutputCacheLocation.Server;
413                 case OutputCacheLocation.Client:
414                         cache.SetCacheability (HttpCacheability.Private);
415                         cache.SetMaxAge (new TimeSpan (0, 0, duration));                
416                         cache.SetLastModified (_context.Timestamp);
417                         break;
418                 case OutputCacheLocation.Downstream:
419                         cache.SetCacheability (HttpCacheability.Public);
420                         cache.SetMaxAge (new TimeSpan (0, 0, duration));                
421                         cache.SetLastModified (_context.Timestamp);
422                         break;
423                 case OutputCacheLocation.Server:
424                         if (varyByCustom != null)
425                                 cache.SetVaryByCustom (varyByCustom);
426                         
427                         if (varyByParam.Length > 0) {
428                                 string[] prms = varyByParam.Split (';');
429                                 foreach (string p in prms)
430                                         cache.VaryByParams [p.Trim ()] = true;
431                                 cache.VaryByParams.IgnoreParams = false;
432                         } else {
433                                 cache.VaryByParams.IgnoreParams = true;
434                         }
435                         
436                         if (varyByHeader != null) {
437                                 string[] hdrs = varyByHeader.Split (';');
438                                 foreach (string h in hdrs)
439                                         cache.VaryByHeaders [h.Trim ()] = true;
440                         }
441                         _context.Response.CacheResponse (_context.Request);
442                         break;
443                 case OutputCacheLocation.None:
444                         break;
445                 }
446                 cache.SetExpires (_context.Timestamp.AddSeconds (duration));
447         }
448
449         [EditorBrowsable (EditorBrowsableState.Advanced)]
450         public bool IsClientScriptBlockRegistered (string key)
451         {
452                 if (clientScriptBlocks == null)
453                         return false;
454
455                 return clientScriptBlocks.ContainsKey (key);
456         }
457
458         [EditorBrowsable (EditorBrowsableState.Advanced)]
459         public bool IsStartupScriptRegistered (string key)
460         {
461                 if (startupScriptBlocks == null)
462                         return false;
463
464                 return startupScriptBlocks.ContainsKey (key);
465         }
466
467         public string MapPath (string virtualPath)
468         {
469                 return Request.MapPath (virtualPath);
470         }
471         
472         private void RenderPostBackScript (HtmlTextWriter writer, string formUniqueID)
473         {
474                 writer.WriteLine ("<input type=\"hidden\" name=\"{0}\" value=\"\" />", postEventSourceID);
475                 writer.WriteLine ("<input type=\"hidden\" name=\"{0}\" value=\"\" />", postEventArgumentID);
476                 writer.WriteLine ();
477                 writer.WriteLine ("<script language=\"javascript\">");
478                 writer.WriteLine ("<!--");
479                 writer.WriteLine ("\tfunction __doPostBack(eventTarget, eventArgument) {");
480                 writer.WriteLine ("\t\tvar theform = document.getElementById ('{0}');", formUniqueID);
481                 writer.WriteLine ("\t\ttheform.{0}.value = eventTarget;", postEventSourceID);
482                 writer.WriteLine ("\t\ttheform.{0}.value = eventArgument;", postEventArgumentID);
483                 writer.WriteLine ("\t\ttheform.submit();");
484                 writer.WriteLine ("\t}");
485                 writer.WriteLine ("// -->");
486                 writer.WriteLine ("</script>");
487         }
488
489         static void WriteScripts (HtmlTextWriter writer, Hashtable scripts)
490         {
491                 if (scripts == null)
492                         return;
493
494                 foreach (string key in scripts.Values)
495                         writer.WriteLine (key);
496         }
497         
498         void WriteHiddenFields (HtmlTextWriter writer)
499         {
500                 if (hiddenFields == null)
501                         return;
502
503                 foreach (string key in hiddenFields.Keys) {
504                         string value = hiddenFields [key] as string;
505                         writer.WriteLine ("\n<input type=\"hidden\" name=\"{0}\" value=\"{1}\" />", key, value);
506                 }
507
508                 hiddenFields = null;
509         }
510
511         internal void OnFormRender (HtmlTextWriter writer, string formUniqueID)
512         {
513                 if (renderingForm)
514                         throw new HttpException ("Only 1 HtmlForm is allowed per page.");
515
516                 renderingForm = true;
517                 writer.WriteLine ();
518                 WriteHiddenFields (writer);
519                 if (requiresPostBackScript) {
520                         RenderPostBackScript (writer, formUniqueID);
521                         postBackScriptRendered = true;
522                 }
523
524                 if (handleViewState) {
525                         writer.Write ("<input type=\"hidden\" name=\"__VIEWSTATE\" ");
526                         writer.WriteLine ("value=\"{0}\" />", GetViewStateString ());
527                 }
528
529                 WriteScripts (writer, clientScriptBlocks);
530         }
531
532         internal string GetViewStateString ()
533         {
534                 StringWriter sr = new StringWriter ();
535                 LosFormatter fmt = new LosFormatter ();
536                 fmt.Serialize (sr, _savedViewState);
537                 return sr.GetStringBuilder ().ToString ();
538         }
539
540         internal void OnFormPostRender (HtmlTextWriter writer, string formUniqueID)
541         {
542                 if (registeredArrayDeclares != null) {
543                         writer.WriteLine();
544                         writer.WriteLine("<script language=\"javascript\">");
545                         writer.WriteLine("<!--");
546                         IDictionaryEnumerator arrayEnum = registeredArrayDeclares.GetEnumerator();
547                         while (arrayEnum.MoveNext()) {
548                                 writer.Write("\tvar ");
549                                 writer.Write(arrayEnum.Key);
550                                 writer.Write(" =  new Array(");
551                                 IEnumerator arrayListEnum = ((ArrayList) arrayEnum.Value).GetEnumerator();
552                                 bool isFirst = true;
553                                 while (arrayListEnum.MoveNext()) {
554                                         if (isFirst)
555                                                 isFirst = false;
556                                         else
557                                                 writer.Write(", ");
558                                         writer.Write(arrayListEnum.Current);
559                                 }
560                                 writer.WriteLine(");");
561                         }
562                         writer.WriteLine("// -->");
563                         writer.WriteLine("</script>");
564                         writer.WriteLine();
565                 }
566
567                 if (!postBackScriptRendered && requiresPostBackScript)
568                         RenderPostBackScript (writer, formUniqueID);
569
570                 WriteHiddenFields (writer);
571                 WriteScripts (writer, startupScriptBlocks);
572                 renderingForm = false;
573                 postBackScriptRendered = false;
574         }
575
576         private void ProcessPostData (NameValueCollection data, bool second)
577         {
578                 if (data == null)
579                         return;
580
581                 if (_requiresPostBackCopy == null && _requiresPostBack != null)
582                         _requiresPostBackCopy = (ArrayList) _requiresPostBack.Clone ();
583
584                 Hashtable used = new Hashtable ();
585                 foreach (string id in data.AllKeys){
586                         if (id == "__VIEWSTATE" || id == postEventSourceID || id == postEventArgumentID)
587                                 continue;
588
589                         string real_id = id;
590                         int dot = real_id.IndexOf ('.');
591                         if (dot >= 1)
592                                 real_id = real_id.Substring (0, dot);
593                         
594                         if (real_id == null || used.ContainsKey (real_id))
595                                 continue;
596
597                         used.Add (real_id, real_id);
598
599                         Control ctrl = FindControl (real_id);
600                         if (ctrl != null){
601                                 IPostBackDataHandler pbdh = ctrl as IPostBackDataHandler;
602                                 IPostBackEventHandler pbeh = ctrl as IPostBackEventHandler;
603
604                                 if (pbdh == null) {
605                                         if (pbeh != null)
606                                                 RegisterRequiresRaiseEvent (pbeh);
607                                         continue;
608                                 }
609                 
610                                 if (pbdh.LoadPostData (real_id, data) == true) {
611                                         if (requiresPostDataChanged == null)
612                                                 requiresPostDataChanged = new ArrayList ();
613                                         requiresPostDataChanged.Add (pbdh);
614                                         if (_requiresPostBackCopy != null)
615                                                 _requiresPostBackCopy.Remove (ctrl.UniqueID);
616                                 }
617                         } else if (!second) {
618                                 if (secondPostData == null)
619                                         secondPostData = new NameValueCollection ();
620                                 secondPostData.Add (real_id, data [id]);
621                         }
622                 }
623
624                 if (_requiresPostBackCopy != null && _requiresPostBackCopy.Count > 0) {
625                         string [] handlers = (string []) _requiresPostBackCopy.ToArray (typeof (string));
626                         foreach (string id in handlers) {
627                                 IPostBackDataHandler pbdh = FindControl (id) as IPostBackDataHandler;
628                                 if (pbdh == null)
629                                         continue;
630                         
631                                 _requiresPostBackCopy.Remove (id);
632                                 if (pbdh.LoadPostData (id, data)) {
633                                         if (requiresPostDataChanged == null)
634                                                 requiresPostDataChanged = new ArrayList ();
635
636                                         requiresPostDataChanged.Add (pbdh);
637                                 }
638                         }
639                 }
640         }
641
642         [EditorBrowsable (EditorBrowsableState.Never)]
643         public void ProcessRequest (HttpContext context)
644         {
645                 _context = context;
646                 WireupAutomaticEvents ();
647                 //-- Control execution lifecycle in the docs
648
649                 // Save culture information because it can be modified in FrameworkInitialize()
650                 CultureInfo culture = Thread.CurrentThread.CurrentCulture;
651                 CultureInfo uiculture = Thread.CurrentThread.CurrentUICulture;
652                 FrameworkInitialize ();
653                 context.ErrorPage = _errorPage;
654
655                 try {
656                         InternalProcessRequest ();
657                 } finally {
658                         Thread.CurrentThread.CurrentCulture = culture;
659                         Thread.CurrentThread.CurrentUICulture = uiculture;
660                 }
661         }
662
663         void InternalProcessRequest ()
664         {
665                 InitRecursive (null);
666                 renderingForm = false;  
667                 if (IsPostBack) {
668                         LoadPageViewState ();
669                         ProcessPostData (DeterminePostBackMode (), false);
670                 }
671
672                 LoadRecursive ();
673                 if (IsPostBack) {
674                         ProcessPostData (secondPostData, true);
675                         RaiseChangedEvents ();
676                         RaisePostBackEvents ();
677                 }
678                 PreRenderRecursiveInternal ();
679
680                 SavePageViewState ();
681                 //--
682                 HtmlTextWriter output = new HtmlTextWriter (_context.Response.Output);
683                 RenderControl (output);
684                 RenderTrace (output);
685                 _context = null;
686                 UnloadRecursive (true);
687         }
688
689         private void RenderTrace (HtmlTextWriter output)
690         {
691                 if (!Trace.IsEnabled)
692                         return;
693                 Trace.Render (output);
694         }
695         
696         internal void RaisePostBackEvents ()
697         {
698                 if (requiresRaiseEvent != null) {
699                         RaisePostBackEvent (requiresRaiseEvent, null);
700                         return;
701                 }
702
703                 NameValueCollection postdata = DeterminePostBackMode ();
704                 if (postdata == null)
705                         return;
706
707                 string eventTarget = postdata [postEventSourceID];
708                 if (eventTarget == null || eventTarget.Length == 0)
709                         return;
710
711                 IPostBackEventHandler target = FindControl (eventTarget) as IPostBackEventHandler;
712                 if (target == null)
713                         return;
714
715                 string eventArgument = postdata [postEventArgumentID];
716                 RaisePostBackEvent (target, eventArgument);
717         }
718
719         internal void RaiseChangedEvents ()
720         {
721                 if (requiresPostDataChanged == null)
722                         return;
723
724                 foreach (IPostBackDataHandler ipdh in requiresPostDataChanged)
725                         ipdh.RaisePostDataChangedEvent ();
726
727                 requiresPostDataChanged = null;
728         }
729
730         [EditorBrowsable (EditorBrowsableState.Advanced)]
731         protected virtual void RaisePostBackEvent (IPostBackEventHandler sourceControl, string eventArgument)
732         {
733                 sourceControl.RaisePostBackEvent (eventArgument);
734         }
735         
736         [EditorBrowsable (EditorBrowsableState.Advanced)]
737         public void RegisterArrayDeclaration (string arrayName, string arrayValue)
738         {
739                 if (registeredArrayDeclares == null)
740                         registeredArrayDeclares = new Hashtable();
741
742                 if (!registeredArrayDeclares.ContainsKey (arrayName))
743                         registeredArrayDeclares.Add (arrayName, new ArrayList());
744
745                 ((ArrayList) registeredArrayDeclares[arrayName]).Add(arrayValue);
746         }
747
748         [EditorBrowsable (EditorBrowsableState.Advanced)]
749         public virtual void RegisterClientScriptBlock (string key, string script)
750         {
751                 if (IsClientScriptBlockRegistered (key))
752                         return;
753
754                 if (clientScriptBlocks == null)
755                         clientScriptBlocks = new Hashtable ();
756
757                 clientScriptBlocks.Add (key, script);
758         }
759
760         [EditorBrowsable (EditorBrowsableState.Advanced)]
761         public virtual void RegisterHiddenField (string hiddenFieldName, string hiddenFieldInitialValue)
762         {
763                 if (hiddenFields == null)
764                         hiddenFields = new Hashtable ();
765
766                 if (!hiddenFields.ContainsKey (hiddenFieldName))
767                         hiddenFields.Add (hiddenFieldName, hiddenFieldInitialValue);
768         }
769         
770         [MonoTODO]
771         public void RegisterClientScriptFile (string a, string b, string c)
772         {
773                 throw new NotImplementedException ();
774         }
775
776         [MonoTODO]
777         [EditorBrowsable (EditorBrowsableState.Advanced)]
778         public void RegisterOnSubmitStatement (string key, string script)
779         {
780                 if (submitStatements == null)
781                         submitStatements = new Hashtable ();
782
783                 if (submitStatements.ContainsKey (key))
784                         return;
785
786                 submitStatements.Add (key, script);
787         }
788
789         [EditorBrowsable (EditorBrowsableState.Advanced)]
790         public void RegisterRequiresPostBack (Control control)
791         {
792                 if (_requiresPostBack == null)
793                         _requiresPostBack = new ArrayList ();
794
795                 _requiresPostBack.Add (control.UniqueID);
796         }
797
798         [EditorBrowsable (EditorBrowsableState.Advanced)]
799         public virtual void RegisterRequiresRaiseEvent (IPostBackEventHandler control)
800         {
801                 requiresRaiseEvent = control;
802         }
803
804         [EditorBrowsable (EditorBrowsableState.Advanced)]
805         public virtual void RegisterStartupScript (string key, string script)
806         {
807                 if (IsStartupScriptRegistered (key))
808                         return;
809
810                 if (startupScriptBlocks == null)
811                         startupScriptBlocks = new Hashtable ();
812
813                 startupScriptBlocks.Add (key, script);
814         }
815
816         [EditorBrowsable (EditorBrowsableState.Advanced)]
817         public void RegisterViewStateHandler ()
818         {
819                 handleViewState = true;
820         }
821
822         [EditorBrowsable (EditorBrowsableState.Advanced)]
823         protected virtual void SavePageStateToPersistenceMedium (object viewState)
824         {
825                 _savedViewState = viewState;
826         }
827
828         [EditorBrowsable (EditorBrowsableState.Advanced)]
829         protected virtual object LoadPageStateFromPersistenceMedium ()
830         {
831                 NameValueCollection postdata = DeterminePostBackMode ();
832                 string view_state;
833                 if (postdata == null || (view_state = postdata ["__VIEWSTATE"]) == null)
834                         return null;
835
836                 _savedViewState = null;
837                 LosFormatter fmt = new LosFormatter ();
838
839                 try { 
840                         _savedViewState = fmt.Deserialize (view_state);
841                 } catch (Exception e) {
842                         throw new HttpException ("Error restoring page viewstate.\n", e);
843                 }
844
845                 return _savedViewState;
846         }
847
848         internal void LoadPageViewState()
849         {
850                 object sState = LoadPageStateFromPersistenceMedium ();
851                 if (sState != null) {
852                         Pair pair = (Pair) sState;
853                         LoadViewStateRecursive (pair.First);
854                         _requiresPostBack = pair.Second as ArrayList;
855                 }
856         }
857
858         internal void SavePageViewState ()
859         {
860                 if (!handleViewState)
861                         return;
862
863                 Pair pair = new Pair ();
864                 pair.First = SaveViewStateRecursive ();
865                 if (_requiresPostBack != null && _requiresPostBack.Count > 0)
866                         pair.Second = _requiresPostBack;
867
868                 if (pair.First == null && pair.Second == null)
869                         pair = null;
870
871                 SavePageStateToPersistenceMedium (pair);
872         }
873
874         public virtual void Validate ()
875         {
876                 if (_validators == null || _validators.Count == 0){
877                         _isValid = true;
878                         return;
879                 }
880
881                 bool all_valid = true;
882                 foreach (IValidator v in _validators){
883                         v.Validate ();
884                         if (v.IsValid == false)
885                                 all_valid = false;
886                 }
887
888                 if (all_valid)
889                         _isValid = true;
890         }
891
892         [EditorBrowsable (EditorBrowsableState.Advanced)]
893         public virtual void VerifyRenderingInServerForm (Control control)
894         {
895                 if (!renderingForm)
896                         throw new HttpException ("Control '" + control.ClientID + " " + control.GetType () + 
897                                                  "' must be rendered within a HtmlForm");
898         }
899
900         #endregion
901         
902         #if NET_1_2
903         public string GetWebResourceUrl(Type type, string resourceName)
904         {
905                 if (type == null)
906                         throw new ArgumentNullException ("type");
907         
908                 if (resourceName == null || resourceName.Length == 0)
909                         throw new ArgumentNullException ("type");
910         
911                 return System.Web.Handlers.AssemblyResourceLoader.GetResourceUrl (type, resourceName); 
912         }
913         
914         Stack dataItemCtx;
915         
916         internal void PushDataItemContext (object o)
917         {
918                 if (dataItemCtx == null)
919                         dataItemCtx = new Stack ();
920                 
921                 dataItemCtx.Push (o);
922         }
923         
924         internal void PopDataItemContext ()
925         {
926                 if (dataItemCtx == null)
927                         throw new InvalidOperationException ();
928                 
929                 dataItemCtx.Pop ();
930         }
931         
932         internal object CurrentDataItem {
933                 get {
934                         if (dataItemCtx == null)
935                                 throw new InvalidOperationException ("No data item");
936                         
937                         return dataItemCtx.Peek ();
938                 }
939         }
940         
941         protected object Eval (string expression)
942         {
943                 return DataBinder.Eval (CurrentDataItem, expression);
944         }
945         
946         protected object Eval (string expression, string format)
947         {
948                 return DataBinder.Eval (CurrentDataItem, expression, format);
949         }
950         
951         protected object XPath (string xpathexpression)
952         {
953                 return XPathBinder.Eval (CurrentDataItem, xpathexpression);
954         }
955         
956         protected object XPath (string xpathexpression, string format)
957         {
958                 return XPathBinder.Eval (CurrentDataItem, xpathexpression, format);
959         }
960         
961         protected IEnumerable XPathSelect (string xpathexpression)
962         {
963                 return XPathBinder.Select (CurrentDataItem, xpathexpression);
964         }
965         
966         #endif
967 }
968 }