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