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