2005-02-10 Lluis Sanchez Gual <lluis@novell.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 //
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 #if !NET_2_0
54 [RootDesignerSerializer ("Microsoft.VSDesigner.WebForms.RootCodeDomSerializer, " + Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design, true)]
55 #endif
56 [DefaultEvent ("Load"), DesignerCategory ("ASPXCodeBehind")]
57 [ToolboxItem (false)]
58 [Designer ("System.Web.UI.Design.ControlDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))]
59 public class Page : TemplateControl, IHttpHandler
60 {
61         private bool _viewState = true;
62         private bool _viewStateMac;
63         private string _errorPage;
64         private bool _isValid;
65         private bool _smartNavigation;
66         private int _transactionMode;
67         private HttpContext _context;
68         private ValidatorCollection _validators;
69         private bool renderingForm;
70         private object _savedViewState;
71         private ArrayList _requiresPostBack;
72         private ArrayList _requiresPostBackCopy;
73         private ArrayList requiresPostDataChanged;
74         private IPostBackEventHandler requiresRaiseEvent;
75         private NameValueCollection secondPostData;
76         private bool requiresPostBackScript;
77         private bool postBackScriptRendered;
78         bool handleViewState;
79         string viewStateUserKey;
80         NameValueCollection _requestValueCollection;
81         string clientTarget;
82         ClientScriptManager scriptManager = new ClientScriptManager ();
83
84         [EditorBrowsable (EditorBrowsableState.Never)]
85         protected const string postEventArgumentID = "__EVENTARGUMENT";
86         [EditorBrowsable (EditorBrowsableState.Never)]
87         protected const string postEventSourceID = "__EVENTTARGET";
88
89 #if NET_2_0
90         private const string callbackArgumentID = "__CALLBACKARGUMENT";
91         private const string callbackSourceID = "__CALLBACKTARGET";
92         private const string previousPageID = "__PREVIOUSPAGE";
93         
94         IPageHeader htmlHeader;
95         
96         MasterPage masterPage;
97         string masterPageFile;
98         
99         Page previousPage;
100         bool isCrossPagePostBack;
101         ArrayList requireStateControls;
102         Hashtable _validatorsByGroup;
103 #endif
104
105         #region Constructor
106         public Page ()
107         {
108                 Page = this;
109         }
110
111         #endregion              
112
113         #region Properties
114
115         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
116         [Browsable (false)]
117         public HttpApplicationState Application
118         {
119                 get { return _context.Application; }
120         }
121
122         [EditorBrowsable (EditorBrowsableState.Never)]
123 #if NET_2_0
124         public bool AspCompatMode
125         {
126                 get { return false; }
127                 set { throw new NotImplementedException (); }
128         }
129 #else
130         protected bool AspCompatMode
131         {
132                 set { throw new NotImplementedException (); }
133         }
134 #endif
135
136         [EditorBrowsable (EditorBrowsableState.Never)]
137 #if NET_2_0
138     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
139     [BrowsableAttribute (false)]
140         public bool Buffer
141         {
142                 get { return Response.BufferOutput; }
143                 set { Response.BufferOutput = value; }
144         }
145 #else
146         protected bool Buffer
147         {
148                 set { Response.BufferOutput = value; }
149         }
150 #endif
151
152         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
153         [Browsable (false)]
154         public Cache Cache
155         {
156                 get { return _context.Cache; }
157         }
158
159 #if NET_2_0
160     [EditorBrowsableAttribute (EditorBrowsableState.Advanced)]
161 #endif
162         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
163         [Browsable (false), DefaultValue ("")]
164         [WebSysDescription ("Value do override the automatic browser detection and force the page to use the specified browser.")]
165         public string ClientTarget
166         {
167                 get { return (clientTarget == null) ? "" : clientTarget; }
168                 set {
169                         clientTarget = value;
170                         if (value == "")
171                                 clientTarget = null;
172                 }
173         }
174
175         [EditorBrowsable (EditorBrowsableState.Never)]
176 #if NET_2_0
177     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
178     [BrowsableAttribute (false)]
179         public int CodePage
180         {
181                 get { return Response.ContentEncoding.CodePage; }
182                 set { Response.ContentEncoding = Encoding.GetEncoding (value); }
183         }
184 #else
185         protected int CodePage
186         {
187                 set { Response.ContentEncoding = Encoding.GetEncoding (value); }
188         }
189 #endif
190
191         [EditorBrowsable (EditorBrowsableState.Never)]
192 #if NET_2_0
193     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
194     [BrowsableAttribute (false)]
195         public string ContentType
196         {
197                 get { return Response.ContentType; }
198                 set { Response.ContentType = value; }
199         }
200 #else
201         protected string ContentType
202         {
203                 set { Response.ContentType = value; }
204         }
205 #endif
206
207         protected override HttpContext Context
208         {
209                 get {
210                         if (_context == null)
211                                 return HttpContext.Current;
212
213                         return _context;
214                 }
215         }
216
217         [EditorBrowsable (EditorBrowsableState.Never)]
218 #if NET_2_0
219     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
220     [BrowsableAttribute (false)]
221         public string Culture
222         {
223                 get { return Thread.CurrentThread.CurrentCulture.Name; }
224                 set { Thread.CurrentThread.CurrentCulture = new CultureInfo (value); }
225         }
226 #else
227         protected string Culture
228         {
229                 set { Thread.CurrentThread.CurrentCulture = new CultureInfo (value); }
230         }
231 #endif
232
233         [Browsable (false)]
234         public override bool EnableViewState
235         {
236                 get { return _viewState; }
237                 set { _viewState = value; }
238         }
239
240 #if NET_2_0
241     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
242     [BrowsableAttribute (false)]
243 #endif
244         [EditorBrowsable (EditorBrowsableState.Never)]
245         protected bool EnableViewStateMac
246         {
247                 get { return _viewStateMac; }
248                 set { _viewStateMac = value; }
249         }
250
251         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
252         [Browsable (false), DefaultValue ("")]
253         [WebSysDescription ("The URL of a page used for error redirection.")]
254         public string ErrorPage
255         {
256                 get { return _errorPage; }
257                 set {
258                         _errorPage = value;
259                         if (_context != null)
260                                 _context.ErrorPage = value;
261                 }
262         }
263
264 #if NET_2_0
265         [Obsolete]
266 #endif
267         [EditorBrowsable (EditorBrowsableState.Never)]
268         protected ArrayList FileDependencies
269         {
270                 set {
271                         if (Response != null)
272                                 Response.AddFileDependencies (value);
273                 }
274         }
275
276         [Browsable (false)]
277         public override string ID
278         {
279                 get { return base.ID; }
280                 set { base.ID = value; }
281         }
282
283         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
284         [Browsable (false)]
285         public bool IsPostBack
286         {
287                 get {
288                         return _requestValueCollection != null;
289                 }
290         }
291
292         [EditorBrowsable (EditorBrowsableState.Never), Browsable (false)]
293         public bool IsReusable {
294                 get { return false; }
295         }
296
297         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
298         [Browsable (false)]
299         public bool IsValid
300         {
301                 get { return _isValid; }
302         }
303
304         [EditorBrowsable (EditorBrowsableState.Never)]
305 #if NET_2_0
306     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
307     [BrowsableAttribute (false)]
308         public int LCID {
309                 get { return Thread.CurrentThread.CurrentCulture.LCID; }
310                 set { Thread.CurrentThread.CurrentCulture = new CultureInfo (value); }
311         }
312 #else
313         protected int LCID {
314                 set { Thread.CurrentThread.CurrentCulture = new CultureInfo (value); }
315         }
316 #endif
317
318         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
319         [Browsable (false)]
320         public HttpRequest Request
321         {
322                 get { return _context.Request; }
323         }
324
325         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
326         [Browsable (false)]
327         public HttpResponse Response
328         {
329                 get { return _context.Response; }
330         }
331
332         [EditorBrowsable (EditorBrowsableState.Never)]
333 #if NET_2_0
334     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
335     [BrowsableAttribute (false)]
336         public string ResponseEncoding
337         {
338                 get { return Response.ContentEncoding.WebName; }
339                 set { Response.ContentEncoding = Encoding.GetEncoding (value); }
340         }
341 #else
342         protected string ResponseEncoding
343         {
344                 set { Response.ContentEncoding = Encoding.GetEncoding (value); }
345         }
346 #endif
347
348         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
349         [Browsable (false)]
350         public HttpServerUtility Server
351         {
352                 get {
353                         return Context.Server;
354                 }
355         }
356
357         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
358         [Browsable (false)]
359         public virtual HttpSessionState Session
360         {
361                 get {
362                         if (_context.Session == null)
363                                 throw new HttpException ("Session state can only be used " +
364                                                 "when enableSessionState is set to true, either " +
365                                                 "in a configuration file or in the Page directive.");
366
367                         return _context.Session;
368                 }
369         }
370
371 #if NET_2_0
372     [FilterableAttribute (false)]
373 #endif
374         [Browsable (false)]
375         public bool SmartNavigation
376         {
377                 get { return _smartNavigation; }
378                 set { _smartNavigation = value; }
379         }
380
381         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
382         [Browsable (false)]
383         public TraceContext Trace
384         {
385                 get { return Context.Trace; }
386         }
387
388         [EditorBrowsable (EditorBrowsableState.Never)]
389 #if NET_2_0
390     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
391     [BrowsableAttribute (false)]
392         public bool TraceEnabled
393         {
394                 get { return Trace.IsEnabled; }
395                 set { Trace.IsEnabled = value; }
396         }
397 #else
398         protected bool TraceEnabled
399         {
400                 set { Trace.IsEnabled = value; }
401         }
402 #endif
403
404         [EditorBrowsable (EditorBrowsableState.Never)]
405 #if NET_2_0
406     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
407     [BrowsableAttribute (false)]
408         public TraceMode TraceModeValue
409         {
410                 get { return Trace.TraceMode; }
411                 set { Trace.TraceMode = value; }
412         }
413 #else
414         protected TraceMode TraceModeValue
415         {
416                 set { Trace.TraceMode = value; }
417         }
418 #endif
419
420         [EditorBrowsable (EditorBrowsableState.Never)]
421 #if NET_2_0
422         public int TransactionMode
423         {
424                 get { return _transactionMode; }
425                 set { _transactionMode = value; }
426         }
427 #else
428         protected int TransactionMode
429         {
430                 set { _transactionMode = value; }
431         }
432 #endif
433
434         [EditorBrowsable (EditorBrowsableState.Never)]
435 #if NET_2_0
436     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
437     [BrowsableAttribute (false)]
438         public string UICulture
439         {
440                 get { return Thread.CurrentThread.CurrentUICulture.Name; }
441                 set { Thread.CurrentThread.CurrentUICulture = new CultureInfo (value); }
442         }
443 #else
444         protected string UICulture
445         {
446                 set { Thread.CurrentThread.CurrentUICulture = new CultureInfo (value); }
447         }
448 #endif
449
450         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
451         [Browsable (false)]
452         public IPrincipal User
453         {
454                 get { return _context.User; }
455         }
456
457         [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
458         [Browsable (false)]
459         public ValidatorCollection Validators
460         {
461                 get { 
462                         if (_validators == null)
463                                 _validators = new ValidatorCollection ();
464                         return _validators;
465                 }
466         }
467
468         [MonoTODO ("Use this when encrypting/decrypting ViewState")]
469         [Browsable (false)]
470         public string ViewStateUserKey {
471                 get { return viewStateUserKey; }
472                 set { viewStateUserKey = value; }
473         }
474
475         [Browsable (false)]
476         public override bool Visible
477         {
478                 get { return base.Visible; }
479                 set { base.Visible = value; }
480         }
481
482         #endregion
483
484         #region Methods
485
486         [EditorBrowsable (EditorBrowsableState.Never)]
487         protected IAsyncResult AspCompatBeginProcessRequest (HttpContext context,
488                                                              AsyncCallback cb, 
489                                                              object extraData)
490         {
491                 throw new NotImplementedException ();
492         }
493
494         [EditorBrowsable (EditorBrowsableState.Never)]
495         protected void AspCompatEndProcessRequest (IAsyncResult result)
496         {
497                 throw new NotImplementedException ();
498         }
499         
500         [EditorBrowsable (EditorBrowsableState.Advanced)]
501         protected virtual HtmlTextWriter CreateHtmlTextWriter (TextWriter tw)
502         {
503                 return new HtmlTextWriter (tw);
504         }
505
506         [EditorBrowsable (EditorBrowsableState.Never)]
507         public void DesignerInitialize ()
508         {
509                 InitRecursive (null);
510         }
511
512         [EditorBrowsable (EditorBrowsableState.Advanced)]
513         protected virtual NameValueCollection DeterminePostBackMode ()
514         {
515                 if (_context == null)
516                         return null;
517
518                 HttpRequest req = _context.Request;
519                 if (req == null)
520                         return null;
521
522                 NameValueCollection coll = null;
523                 if (0 == String.Compare (Request.HttpMethod, "POST", true))
524                         coll =  req.Form;
525                 else 
526                         coll = req.QueryString;
527
528                 
529                 if (coll == null || coll ["__VIEWSTATE"] == null)
530                         return null;
531
532                 return coll;
533         }
534         
535         [EditorBrowsable (EditorBrowsableState.Advanced)]
536         public string GetPostBackClientEvent (Control control, string argument)
537         {
538                 return GetPostBackEventReference (control, argument);
539         }
540
541         [EditorBrowsable (EditorBrowsableState.Advanced)]
542         public string GetPostBackClientHyperlink (Control control, string argument)
543         {
544                 return "javascript:" + GetPostBackEventReference (control, argument);
545         }
546
547         [EditorBrowsable (EditorBrowsableState.Advanced)]
548         public string GetPostBackEventReference (Control control)
549         {
550                 return GetPostBackEventReference (control, "");
551         }
552
553         [EditorBrowsable (EditorBrowsableState.Advanced)]
554         public string GetPostBackEventReference (Control control, string argument)
555         {
556                 RequiresPostBackScript ();
557                 return String.Format ("__doPostBack('{0}','{1}')", control.UniqueID, argument);
558         }
559
560         internal void RequiresPostBackScript ()
561         {
562                 requiresPostBackScript = true;
563         }
564
565         [EditorBrowsable (EditorBrowsableState.Never)]
566         public virtual int GetTypeHashCode ()
567         {
568                 return 0;
569         }
570
571         [EditorBrowsable (EditorBrowsableState.Never)]
572         protected virtual void InitOutputCache (int duration,
573                                                 string varyByHeader,
574                                                 string varyByCustom,
575                                                 OutputCacheLocation location,
576                                                 string varyByParam)
577         {
578                 HttpCachePolicy cache = _context.Response.Cache;
579                 bool set_vary = false;
580
581                 switch (location) {
582                 case OutputCacheLocation.Any:
583                         cache.SetCacheability (HttpCacheability.Public);
584                         cache.SetMaxAge (new TimeSpan (0, 0, duration));                
585                         cache.SetLastModified (_context.Timestamp);
586                         set_vary = true;
587                         break;
588                 case OutputCacheLocation.Client:
589                         cache.SetCacheability (HttpCacheability.Private);
590                         cache.SetMaxAge (new TimeSpan (0, 0, duration));                
591                         cache.SetLastModified (_context.Timestamp);
592                         break;
593                 case OutputCacheLocation.Downstream:
594                         cache.SetCacheability (HttpCacheability.Public);
595                         cache.SetMaxAge (new TimeSpan (0, 0, duration));                
596                         cache.SetLastModified (_context.Timestamp);
597                         break;
598                 case OutputCacheLocation.Server:                        
599                         cache.SetCacheability (HttpCacheability.Server);
600                         set_vary = true;
601                         break;
602                 case OutputCacheLocation.None:
603                         break;
604                 }
605
606                 if (set_vary) {
607                         if (varyByCustom != null)
608                                 cache.SetVaryByCustom (varyByCustom);
609
610                         if (varyByParam != null && varyByParam.Length > 0) {
611                                 string[] prms = varyByParam.Split (';');
612                                 foreach (string p in prms)
613                                         cache.VaryByParams [p.Trim ()] = true;
614                                 cache.VaryByParams.IgnoreParams = false;
615                         } else {
616                                 cache.VaryByParams.IgnoreParams = true;
617                         }
618                         
619                         if (varyByHeader != null && varyByHeader.Length > 0) {
620                                 string[] hdrs = varyByHeader.Split (';');
621                                 foreach (string h in hdrs)
622                                         cache.VaryByHeaders [h.Trim ()] = true;
623                         }
624                 }
625                         
626                 cache.Duration = duration;
627                 cache.SetExpires (_context.Timestamp.AddSeconds (duration));
628         }
629
630 #if NET_2_0
631         [Obsolete]
632 #else
633         [EditorBrowsable (EditorBrowsableState.Advanced)]
634 #endif
635         public bool IsClientScriptBlockRegistered (string key)
636         {
637                 return scriptManager.IsClientScriptBlockRegistered (key);
638         }
639
640 #if NET_2_0
641         [Obsolete]
642 #else
643         [EditorBrowsable (EditorBrowsableState.Advanced)]
644 #endif
645         public bool IsStartupScriptRegistered (string key)
646         {
647                 return scriptManager.IsStartupScriptRegistered (key);
648         }
649
650         public string MapPath (string virtualPath)
651         {
652                 return Request.MapPath (virtualPath);
653         }
654         
655         private void RenderPostBackScript (HtmlTextWriter writer, string formUniqueID)
656         {
657                 writer.WriteLine ("<input type=\"hidden\" name=\"{0}\" value=\"\" />", postEventSourceID);
658                 writer.WriteLine ("<input type=\"hidden\" name=\"{0}\" value=\"\" />", postEventArgumentID);
659                 writer.WriteLine ();
660                 writer.WriteLine ("<script language=\"javascript\">");
661                 writer.WriteLine ("<!--");
662
663                 if (Request.Browser.Browser == ("Netscape") && Request.Browser.MajorVersion == 4)
664                         writer.WriteLine ("\tvar theForm = document.{0};", formUniqueID);
665                 else
666                         writer.WriteLine ("\tvar theForm = document.getElementById ('{0}');", formUniqueID);
667
668                 writer.WriteLine ("\tfunction __doPostBack(eventTarget, eventArgument) {");
669                 writer.WriteLine ("\t\ttheForm.{0}.value = eventTarget;", postEventSourceID);
670                 writer.WriteLine ("\t\ttheForm.{0}.value = eventArgument;", postEventArgumentID);
671                 writer.WriteLine ("\t\ttheForm.submit();");
672                 writer.WriteLine ("\t}");
673                 writer.WriteLine ("// -->");
674                 writer.WriteLine ("</script>");
675         }
676
677         internal void OnFormRender (HtmlTextWriter writer, string formUniqueID)
678         {
679                 if (renderingForm)
680                         throw new HttpException ("Only 1 HtmlForm is allowed per page.");
681
682                 renderingForm = true;
683                 writer.WriteLine ();
684                 scriptManager.WriteHiddenFields (writer);
685                 if (requiresPostBackScript) {
686                         RenderPostBackScript (writer, formUniqueID);
687                         postBackScriptRendered = true;
688                 }
689
690                 if (handleViewState) {
691                         string vs = GetViewStateString ();
692                         writer.Write ("<input type=\"hidden\" name=\"__VIEWSTATE\" ");
693                         writer.WriteLine ("value=\"{0}\" />", vs);
694                 }
695
696                 scriptManager.WriteClientScriptBlocks (writer);
697         }
698
699         internal string GetViewStateString ()
700         {
701                 if (_savedViewState == null)
702                         return null;
703                 StringWriter sr = new StringWriter ();
704                 LosFormatter fmt = new LosFormatter ();
705                 fmt.Serialize (sr, _savedViewState);
706                 return sr.GetStringBuilder ().ToString ();
707         }
708
709         internal void OnFormPostRender (HtmlTextWriter writer, string formUniqueID)
710         {
711                 scriptManager.WriteArrayDeclares (writer);
712
713                 if (!postBackScriptRendered && requiresPostBackScript)
714                         RenderPostBackScript (writer, formUniqueID);
715
716                 scriptManager.WriteHiddenFields (writer);
717                 scriptManager.WriteClientScriptIncludes (writer);
718                 scriptManager.WriteStartupScriptBlocks (writer);
719                 renderingForm = false;
720                 postBackScriptRendered = false;
721         }
722
723         private void ProcessPostData (NameValueCollection data, bool second)
724         {
725                 if (data == null)
726                         return;
727
728                 if (_requiresPostBackCopy == null && _requiresPostBack != null)
729                         _requiresPostBackCopy = (ArrayList) _requiresPostBack.Clone ();
730
731                 Hashtable used = new Hashtable ();
732                 foreach (string id in data.AllKeys){
733                         if (id == "__VIEWSTATE" || id == postEventSourceID || id == postEventArgumentID)
734                                 continue;
735
736                         string real_id = id;
737                         int dot = real_id.IndexOf ('.');
738                         if (dot >= 1)
739                                 real_id = real_id.Substring (0, dot);
740                         
741                         if (real_id == null || used.ContainsKey (real_id))
742                                 continue;
743
744                         used.Add (real_id, real_id);
745
746                         Control ctrl = FindControl (real_id);
747                         if (ctrl != null){
748                                 IPostBackDataHandler pbdh = ctrl as IPostBackDataHandler;
749                                 IPostBackEventHandler pbeh = ctrl as IPostBackEventHandler;
750
751                                 if (pbdh == null) {
752                                         if (pbeh != null)
753                                                 RegisterRequiresRaiseEvent (pbeh);
754                                         continue;
755                                 }
756                 
757                                 if (pbdh.LoadPostData (real_id, data) == true) {
758                                         if (requiresPostDataChanged == null)
759                                                 requiresPostDataChanged = new ArrayList ();
760                                         requiresPostDataChanged.Add (pbdh);
761                                         if (_requiresPostBackCopy != null)
762                                                 _requiresPostBackCopy.Remove (ctrl.UniqueID);
763                                 }
764                         } else if (!second) {
765                                 if (secondPostData == null)
766                                         secondPostData = new NameValueCollection ();
767                                 secondPostData.Add (real_id, data [id]);
768                         }
769                 }
770
771                 ArrayList list1 = null;
772                 if (_requiresPostBackCopy != null && _requiresPostBackCopy.Count > 0) {
773                         string [] handlers = (string []) _requiresPostBackCopy.ToArray (typeof (string));
774                         foreach (string id in handlers) {
775                                 IPostBackDataHandler pbdh = FindControl (id) as IPostBackDataHandler;
776                                 if (pbdh != null) {                     
777                                         _requiresPostBackCopy.Remove (id);
778                                         if (pbdh.LoadPostData (id, data)) {
779                                                 if (requiresPostDataChanged == null)
780                                                         requiresPostDataChanged = new ArrayList ();
781         
782                                                 requiresPostDataChanged.Add (pbdh);
783                                         }
784                                 } else if (second) {
785                                         if (list1 == null)
786                                                 list1 = new ArrayList ();
787                                         list1.Add (id);
788                                 }
789                         }
790                         _requiresPostBack = list1;
791                 }
792         }
793
794         [EditorBrowsable (EditorBrowsableState.Never)]
795         public void ProcessRequest (HttpContext context)
796         {
797                 _context = context;
798                 if (clientTarget != null)
799                         Request.ClientTarget = clientTarget;
800
801                 WireupAutomaticEvents ();
802                 //-- Control execution lifecycle in the docs
803
804                 // Save culture information because it can be modified in FrameworkInitialize()
805                 CultureInfo culture = Thread.CurrentThread.CurrentCulture;
806                 CultureInfo uiculture = Thread.CurrentThread.CurrentUICulture;
807                 FrameworkInitialize ();
808                 context.ErrorPage = _errorPage;
809
810                 try {
811                         InternalProcessRequest ();
812                 } finally {
813                         try {
814                                 UnloadRecursive (true);
815                         } catch {}
816                         Thread.CurrentThread.CurrentCulture = culture;
817                         Thread.CurrentThread.CurrentUICulture = uiculture;
818                 }
819         }
820         
821 #if NET_2_0
822         internal void ProcessCrossPagePostBack (HttpContext context)
823         {
824                 isCrossPagePostBack = true;
825                 ProcessRequest (context);
826         }
827 #endif
828
829         void InternalProcessRequest ()
830         {
831                 _requestValueCollection = this.DeterminePostBackMode();
832
833 #if NET_2_0
834                 if (!IsCrossPagePostBack)
835                         LoadPreviousPageReference ();
836 #endif
837                 Trace.Write ("aspx.page", "Begin Init");
838                 InitRecursive (null);
839                 Trace.Write ("aspx.page", "End Init");
840
841 #if NET_2_0
842                 if (masterPageFile != null) {
843                         Controls.Add (Master);
844                         Master.FillPlaceHolders ();
845                 }
846 #endif
847                         
848                 renderingForm = false;  
849                 if (IsPostBack) {
850                         Trace.Write ("aspx.page", "Begin LoadViewState");
851                         LoadPageViewState ();
852                         Trace.Write ("aspx.page", "End LoadViewState");
853                         Trace.Write ("aspx.page", "Begin ProcessPostData");
854                         ProcessPostData (_requestValueCollection, false);
855                         Trace.Write ("aspx.page", "End ProcessPostData");
856                 }
857                 
858 #if NET_2_0
859                 if (IsCrossPagePostBack)
860                         return;
861 #endif
862
863                 LoadRecursive ();
864                 if (IsPostBack) {
865                         Trace.Write ("aspx.page", "Begin ProcessPostData Second Try");
866                         ProcessPostData (secondPostData, true);
867                         Trace.Write ("aspx.page", "End ProcessPostData Second Try");
868                         Trace.Write ("aspx.page", "Begin Raise ChangedEvents");
869                         RaiseChangedEvents ();
870                         Trace.Write ("aspx.page", "End Raise ChangedEvents");
871                         Trace.Write ("aspx.page", "Begin Raise PostBackEvent");
872                         RaisePostBackEvents ();
873                         Trace.Write ("aspx.page", "End Raise PostBackEvent");
874                 }
875                 
876 #if NET_2_0
877                 if (IsCallback) {
878                         string result = ProcessCallbackData ();
879                         HtmlTextWriter callbackOutput = new HtmlTextWriter (_context.Response.Output);
880                         callbackOutput.Write (result);
881                         callbackOutput.Flush ();
882                         return;
883                 }
884 #endif
885                 
886                 Trace.Write ("aspx.page", "Begin PreRender");
887                 PreRenderRecursiveInternal ();
888                 Trace.Write ("aspx.page", "End PreRender");
889
890                 Trace.Write ("aspx.page", "Begin SaveViewState");
891                 SavePageViewState ();
892                 Trace.Write ("aspx.page", "End SaveViewState");
893                 
894                 //--
895                 Trace.Write ("aspx.page", "Begin Render");
896                 HtmlTextWriter output = new HtmlTextWriter (_context.Response.Output);
897                 RenderControl (output);
898                 Trace.Write ("aspx.page", "End Render");
899                 
900                 RenderTrace (output);
901         }
902
903         private void RenderTrace (HtmlTextWriter output)
904         {
905                 TraceManager traceManager = HttpRuntime.TraceManager;
906
907                 if (Trace.HaveTrace && !Trace.IsEnabled || !Trace.HaveTrace && !traceManager.Enabled)
908                         return;
909                 
910                 Trace.SaveData ();
911
912                 if (!Trace.HaveTrace && traceManager.Enabled && !traceManager.PageOutput) 
913                         return;
914
915                 if (!traceManager.LocalOnly || Context.Request.IsLocal)
916                         Trace.Render (output);
917         }
918         
919         internal void RaisePostBackEvents ()
920         {
921                 if (requiresRaiseEvent != null) {
922                         RaisePostBackEvent (requiresRaiseEvent, null);
923                         return;
924                 }
925
926                 NameValueCollection postdata = _requestValueCollection;
927                 if (postdata == null)
928                         return;
929
930                 string eventTarget = postdata [postEventSourceID];
931                 if (eventTarget == null || eventTarget.Length == 0) {
932                         Validate ();
933                         return;
934                 }
935
936                 IPostBackEventHandler target = FindControl (eventTarget) as IPostBackEventHandler;
937                 if (target == null)
938                         return;
939
940                 string eventArgument = postdata [postEventArgumentID];
941                 RaisePostBackEvent (target, eventArgument);
942         }
943
944         internal void RaiseChangedEvents ()
945         {
946                 if (requiresPostDataChanged == null)
947                         return;
948
949                 foreach (IPostBackDataHandler ipdh in requiresPostDataChanged)
950                         ipdh.RaisePostDataChangedEvent ();
951
952                 requiresPostDataChanged = null;
953         }
954
955         [EditorBrowsable (EditorBrowsableState.Advanced)]
956         protected virtual void RaisePostBackEvent (IPostBackEventHandler sourceControl, string eventArgument)
957         {
958                 sourceControl.RaisePostBackEvent (eventArgument);
959         }
960         
961 #if NET_2_0
962         [Obsolete]
963 #endif
964         [EditorBrowsable (EditorBrowsableState.Advanced)]
965         public void RegisterArrayDeclaration (string arrayName, string arrayValue)
966         {
967                 scriptManager.RegisterArrayDeclaration (arrayName, arrayValue);
968         }
969
970 #if NET_2_0
971         [Obsolete]
972 #endif
973         [EditorBrowsable (EditorBrowsableState.Advanced)]
974         public virtual void RegisterClientScriptBlock (string key, string script)
975         {
976                 scriptManager.RegisterClientScriptBlock (key, script);
977         }
978
979 #if NET_2_0
980         [Obsolete]
981 #endif
982         [EditorBrowsable (EditorBrowsableState.Advanced)]
983         public virtual void RegisterHiddenField (string hiddenFieldName, string hiddenFieldInitialValue)
984         {
985                 scriptManager.RegisterHiddenField (hiddenFieldName, hiddenFieldInitialValue);
986         }
987
988         [MonoTODO("Used in HtmlForm")]
989         internal void RegisterClientScriptFile (string a, string b, string c)
990         {
991                 throw new NotImplementedException ();
992         }
993
994 #if NET_2_0
995         [Obsolete]
996 #endif
997         [EditorBrowsable (EditorBrowsableState.Advanced)]
998         public void RegisterOnSubmitStatement (string key, string script)
999         {
1000                 scriptManager.RegisterOnSubmitStatement (key, script);
1001         }
1002
1003         [EditorBrowsable (EditorBrowsableState.Advanced)]
1004         public void RegisterRequiresPostBack (Control control)
1005         {
1006                 if (_requiresPostBack == null)
1007                         _requiresPostBack = new ArrayList ();
1008
1009                 _requiresPostBack.Add (control.UniqueID);
1010         }
1011
1012         [EditorBrowsable (EditorBrowsableState.Advanced)]
1013         public virtual void RegisterRequiresRaiseEvent (IPostBackEventHandler control)
1014         {
1015                 requiresRaiseEvent = control;
1016         }
1017
1018 #if NET_2_0
1019         [Obsolete]
1020 #endif
1021         [EditorBrowsable (EditorBrowsableState.Advanced)]
1022         public virtual void RegisterStartupScript (string key, string script)
1023         {
1024                 scriptManager.RegisterStartupScript (key, script);
1025         }
1026
1027         [EditorBrowsable (EditorBrowsableState.Advanced)]
1028         public void RegisterViewStateHandler ()
1029         {
1030                 handleViewState = true;
1031         }
1032
1033         [EditorBrowsable (EditorBrowsableState.Advanced)]
1034         protected virtual void SavePageStateToPersistenceMedium (object viewState)
1035         {
1036                 _savedViewState = viewState;
1037         }
1038
1039         [EditorBrowsable (EditorBrowsableState.Advanced)]
1040         protected virtual object LoadPageStateFromPersistenceMedium ()
1041         {
1042                 NameValueCollection postdata = _requestValueCollection;
1043                 string view_state;
1044                 if (postdata == null || (view_state = postdata ["__VIEWSTATE"]) == null)
1045                         return null;
1046
1047                 _savedViewState = null;
1048                 LosFormatter fmt = new LosFormatter ();
1049
1050                 try { 
1051                         _savedViewState = fmt.Deserialize (view_state);
1052                 } catch (Exception e) {
1053                         throw new HttpException ("Error restoring page viewstate.\n", e);
1054                 }
1055
1056                 return _savedViewState;
1057         }
1058
1059         internal void LoadPageViewState()
1060         {
1061                 object sState = LoadPageStateFromPersistenceMedium ();
1062                 if (sState != null) {
1063 #if NET_2_0
1064                         Triplet data = (Triplet) sState;
1065                         LoadViewStateRecursive (data.First);
1066                         _requiresPostBack = data.Second as ArrayList;
1067                         LoadPageControlState (data.Third);
1068 #else
1069                         Pair pair = (Pair) sState;
1070                         LoadViewStateRecursive (pair.First);
1071                         _requiresPostBack = pair.Second as ArrayList;
1072 #endif
1073                 }
1074         }
1075
1076         internal void SavePageViewState ()
1077         {
1078                 if (!handleViewState)
1079                         return;
1080
1081                 object viewState = SaveViewStateRecursive ();
1082                 object reqPostback = (_requiresPostBack != null && _requiresPostBack.Count > 0) ? _requiresPostBack : null;
1083
1084 #if NET_2_0
1085                 Triplet triplet = new Triplet ();
1086                 triplet.First = viewState;
1087                 triplet.Second = reqPostback;
1088                 triplet.Third = SavePageControlState ();
1089
1090                 if (triplet.First == null && triplet.Second == null && triplet.Third == null)
1091                         triplet = null;
1092                         
1093                 SavePageStateToPersistenceMedium (triplet);
1094 #else
1095                 Pair pair = new Pair ();
1096                 pair.First = viewState;
1097                 pair.Second = reqPostback;
1098
1099                 if (pair.First == null && pair.Second == null)
1100                         pair = null;
1101                         
1102                 SavePageStateToPersistenceMedium (pair);
1103 #endif
1104         }
1105
1106         public virtual void Validate ()
1107         {
1108                 ValidateCollection (_validators);
1109         }
1110         
1111         void ValidateCollection (ValidatorCollection validators)
1112         {
1113                 if (validators == null || validators.Count == 0){
1114                         _isValid = true;
1115                         return;
1116                 }
1117
1118                 bool all_valid = true;
1119                 foreach (IValidator v in validators){
1120                         v.Validate ();
1121                         if (v.IsValid == false)
1122                                 all_valid = false;
1123                 }
1124
1125                 if (all_valid)
1126                         _isValid = true;
1127         }
1128
1129         [EditorBrowsable (EditorBrowsableState.Advanced)]
1130         public virtual void VerifyRenderingInServerForm (Control control)
1131         {
1132                 if (!renderingForm)
1133                         throw new HttpException ("Control '" + control.ClientID + " " + control.GetType () + 
1134                                                  "' must be rendered within a HtmlForm");
1135         }
1136         
1137         #endregion
1138         
1139         #if NET_2_0
1140         public
1141         #else
1142         internal
1143         #endif
1144                 ClientScriptManager ClientScript {
1145                 get { return scriptManager; }
1146         }
1147         
1148         #if NET_2_0
1149         public string GetWebResourceUrl(Type type, string resourceName)
1150         {
1151                 if (type == null)
1152                         throw new ArgumentNullException ("type");
1153         
1154                 if (resourceName == null || resourceName.Length == 0)
1155                         throw new ArgumentNullException ("type");
1156         
1157                 return System.Web.Handlers.AssemblyResourceLoader.GetResourceUrl (type, resourceName); 
1158         }
1159         
1160         Stack dataItemCtx;
1161         
1162         internal void PushDataItemContext (object o)
1163         {
1164                 if (dataItemCtx == null)
1165                         dataItemCtx = new Stack ();
1166                 
1167                 dataItemCtx.Push (o);
1168         }
1169         
1170         internal void PopDataItemContext ()
1171         {
1172                 if (dataItemCtx == null)
1173                         throw new InvalidOperationException ();
1174                 
1175                 dataItemCtx.Pop ();
1176         }
1177         
1178         internal object CurrentDataItem {
1179                 get {
1180                         if (dataItemCtx == null)
1181                                 throw new InvalidOperationException ("No data item");
1182                         
1183                         return dataItemCtx.Peek ();
1184                 }
1185         }
1186         
1187         protected object Eval (string expression)
1188         {
1189                 return DataBinder.Eval (CurrentDataItem, expression);
1190         }
1191         
1192         protected object Eval (string expression, string format)
1193         {
1194                 return DataBinder.Eval (CurrentDataItem, expression, format);
1195         }
1196         
1197         protected object XPath (string xpathexpression)
1198         {
1199                 return XPathBinder.Eval (CurrentDataItem, xpathexpression);
1200         }
1201         
1202         protected object XPath (string xpathexpression, string format)
1203         {
1204                 return XPathBinder.Eval (CurrentDataItem, xpathexpression, format);
1205         }
1206         
1207         protected IEnumerable XPathSelect (string xpathexpression)
1208         {
1209                 return XPathBinder.Select (CurrentDataItem, xpathexpression);
1210         }
1211         
1212         [EditorBrowsable (EditorBrowsableState.Advanced)]
1213         public string GetCallbackEventReference (Control control, string argument, string clientCallback, string context)
1214         {
1215                 return GetCallbackEventReference (control, argument, clientCallback, context, null);
1216         }
1217         
1218         [EditorBrowsable (EditorBrowsableState.Advanced)]
1219         public string GetCallbackEventReference (Control control, string argument, string clientCallback, string context, string clientErrorCallback)
1220         {
1221                 if (!ClientScript.IsClientScriptIncludeRegistered (typeof(Page), "callback"))
1222                         ClientScript.RegisterClientScriptInclude (typeof(Page), "callback", GetWebResourceUrl (typeof(Page), "callback.js"));
1223                 
1224                 return string.Format ("WebForm_DoCallback ('{0}', {1}, {2}, {3}, {4})", control.UniqueID, argument, clientCallback, context, clientErrorCallback);
1225         }
1226         
1227         [EditorBrowsable (EditorBrowsableState.Advanced)]
1228         public string GetPostBackEventReference (PostBackOptions options)
1229         {
1230                 if (!ClientScript.IsClientScriptIncludeRegistered (typeof(Page), "webform")) {
1231                         ClientScript.RegisterClientScriptInclude (typeof(Page), "webform", GetWebResourceUrl (typeof(Page), "webform.js"));
1232                 }
1233                 
1234                 if (options.ActionUrl != null)
1235                         ClientScript.RegisterHiddenField (previousPageID, _context.Request.FilePath);
1236                 
1237                 if (options.ClientSubmit || options.ActionUrl != null)
1238                         RequiresPostBackScript ();
1239                 
1240                 return String.Format ("{0}WebForm_DoPostback({1},{2},{3},{4},{5},{6},{7},{8})", 
1241                                 options.RequiresJavaScriptProtocol ? "javascript:" : "",
1242                                 ClientScriptManager.GetScriptLiteral (options.TargetControl.UniqueID), 
1243                                 ClientScriptManager.GetScriptLiteral (options.Argument),
1244                                 ClientScriptManager.GetScriptLiteral (options.ActionUrl),
1245                                 ClientScriptManager.GetScriptLiteral (options.AutoPostBack),
1246                                 ClientScriptManager.GetScriptLiteral (options.PerformValidation),
1247                                 ClientScriptManager.GetScriptLiteral (options.TrackFocus),
1248                                 ClientScriptManager.GetScriptLiteral (options.ClientSubmit),
1249                                 ClientScriptManager.GetScriptLiteral (options.ValidationGroup)
1250                         );
1251         }
1252         
1253     [BrowsableAttribute (false)]
1254     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1255         public Page PreviousPage {
1256                 get { return previousPage; }
1257         }
1258
1259         
1260     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1261     [BrowsableAttribute (false)]
1262         public bool IsCallback {
1263                 get { return _requestValueCollection != null && _requestValueCollection [callbackArgumentID] != null; }
1264         }
1265         
1266     [BrowsableAttribute (false)]
1267     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1268         public bool IsCrossPagePostBack {
1269                 get { return _requestValueCollection != null && isCrossPagePostBack; }
1270         }
1271         
1272         string ProcessCallbackData ()
1273         {
1274                 string callbackTarget = _requestValueCollection [callbackSourceID];
1275                 if (callbackTarget == null || callbackTarget.Length == 0)
1276                         throw new HttpException ("Callback target not provided.");
1277
1278                 ICallbackEventHandler target = FindControl (callbackTarget) as ICallbackEventHandler;
1279                 if (target == null)
1280                         throw new HttpException (string.Format ("Invalid callback target '{0}'.", callbackTarget));
1281
1282                 string callbackArgument = _requestValueCollection [callbackArgumentID];
1283                 return target.RaiseCallbackEvent (callbackArgument);
1284         }
1285
1286     [BrowsableAttribute (false)]
1287     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1288         public IPageHeader Header {
1289                 get { return htmlHeader; }
1290         }
1291         
1292         internal void SetHeader (IPageHeader header)
1293         {
1294                 htmlHeader = header;
1295         }
1296         
1297     [DefaultValueAttribute ("")]
1298         public string MasterPageFile {
1299                 get { return masterPageFile; }
1300                 set { masterPageFile = value; masterPage = null; }
1301         }
1302         
1303     [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1304     [BrowsableAttribute (false)]
1305         public MasterPage Master {
1306                 get {
1307                         if (masterPage == null)
1308                                 masterPage = MasterPageParser.GetCompiledMasterInstance (masterPageFile, Server.MapPath (masterPageFile), Context);
1309                         return masterPage;
1310                 }
1311         }
1312         
1313         [EditorBrowsable (EditorBrowsableState.Advanced)]
1314         public void RegisterRequiresControlState (Control control)
1315         {
1316                 if (requireStateControls == null) requireStateControls = new ArrayList ();
1317                 requireStateControls.Add (control);
1318         }
1319         
1320         public ValidatorCollection GetValidators (string validationGroup)
1321         {
1322                 if (validationGroup == null || validationGroup == "")
1323                         return Validators;
1324
1325                 if (_validatorsByGroup == null) _validatorsByGroup = new Hashtable ();
1326                 ValidatorCollection col = _validatorsByGroup [validationGroup] as ValidatorCollection;
1327                 if (col == null) {
1328                         col = new ValidatorCollection ();
1329                         _validatorsByGroup [validationGroup] = col;
1330                 }
1331                 return col;
1332         }
1333         
1334         public virtual void Validate (string validationGroup)
1335         {
1336                 if (validationGroup == null || validationGroup == "")
1337                         ValidateCollection (_validators);
1338                 else {
1339                         if (_validatorsByGroup != null) {
1340                                 ValidateCollection (_validatorsByGroup [validationGroup] as ValidatorCollection);
1341                         } else {
1342                                 _isValid = true;
1343                         }
1344                 }
1345         }
1346         
1347         object SavePageControlState ()
1348         {
1349                 if (requireStateControls == null) return null;
1350                 object[] state = new object [requireStateControls.Count];
1351                 
1352                 bool allNull = true;
1353                 for (int n=0; n<state.Length; n++) {
1354                         state [n] = ((Control) requireStateControls [n]).SaveControlState ();
1355                         if (state [n] != null) allNull = false;
1356                 }
1357                 if (allNull) return null;
1358                 else return state;
1359         }
1360         
1361         void LoadPageControlState (object data)
1362         {
1363                 if (requireStateControls == null) return;
1364
1365                 object[] state = (object[]) data;
1366                 int max = Math.Min (requireStateControls.Count, state != null ? state.Length : requireStateControls.Count);
1367                 for (int n=0; n < max; n++) {
1368                         Control ctl = (Control) requireStateControls [n];
1369                         ctl.LoadControlState (state != null ? state [n] : null);
1370                 }
1371         }
1372
1373         void LoadPreviousPageReference ()
1374         {
1375                 if (_requestValueCollection != null) {
1376                         string prevPage = _requestValueCollection [previousPageID];
1377                         if (prevPage != null) {
1378                                 previousPage = (Page) PageParser.GetCompiledPageInstance (prevPage, Server.MapPath (prevPage), Context);
1379                                 previousPage.ProcessCrossPagePostBack (_context);
1380                         } else {
1381                                 previousPage = _context.LastPage;
1382                         }
1383                 }
1384                 _context.LastPage = this;
1385         }
1386
1387
1388         #endif
1389 }
1390 }