2007-07-24 Igor Zelmanovich <igorz@mainsoft.com>
[mono.git] / mcs / class / System.Web / System.Web.UI / Page.cs
index 5d09965c419cbca7e1aa3433014021ae20cba6bd..9714b9c35edcc3489eca8ae593160b9d567f12e1 100644 (file)
@@ -51,6 +51,8 @@ using System.Web.UI.HtmlControls;
 using System.Web.UI.WebControls;
 #if NET_2_0
 using System.Web.UI.Adapters;
+using System.Collections.Generic;
+using System.Reflection;
 #endif
 
 namespace System.Web.UI
@@ -68,10 +70,16 @@ namespace System.Web.UI
 #else
 [Designer ("Microsoft.VSDesigner.WebForms.WebFormDesigner, " + Consts.AssemblyMicrosoft_VSDesigner, typeof (IRootDesigner))]
 #endif
-public class Page : TemplateControl, IHttpHandler
+public partial class Page : TemplateControl, IHttpHandler
 {
+       static string machineKeyConfigPath = "system.web/machineKey";
 #if NET_2_0
+       private PageLifeCycle _lifeCycle = PageLifeCycle.Unknown;
        private bool _eventValidation = true;
+       private object [] _savedControlState;
+       private bool _doLoadPreviousPage;
+       string _focusedControlID;
+       bool _hasEnabledControlArray;
 #endif
        private bool _viewState = true;
        private bool _viewStateMac;
@@ -82,7 +90,7 @@ public class Page : TemplateControl, IHttpHandler
        private HttpContext _context;
        private ValidatorCollection _validators;
        private bool renderingForm;
-       private object _savedViewState;
+       private string _savedViewState;
        private ArrayList _requiresPostBack;
        private ArrayList _requiresPostBackCopy;
        private ArrayList requiresPostDataChanged;
@@ -96,6 +104,7 @@ public class Page : TemplateControl, IHttpHandler
        string clientTarget;
        ClientScriptManager scriptManager;
        bool allow_load; // true when the Form collection belongs to this page (GetTypeHashCode)
+       PageStatePersister page_state_persister;
 
        [EditorBrowsable (EditorBrowsableState.Never)]
 #if NET_2_0
@@ -116,13 +125,15 @@ public class Page : TemplateControl, IHttpHandler
 #if NET_2_0
        const string ScrollPositionXID = "__SCROLLPOSITIONX";
        const string ScrollPositionYID = "__SCROLLPOSITIONY";
+       const string EnabledControlArrayID = "__enabledControlArray";
 #endif
 
 #if NET_2_0
+       internal const string LastFocusID = "__LASTFOCUS";
        internal const string CallbackArgumentID = "__CALLBACKARGUMENT";
        internal const string CallbackSourceID = "__CALLBACKTARGET";
        internal const string PreviousPageID = "__PREVIOUSPAGE";
-       
+
        HtmlHead htmlHeader;
        
        MasterPage masterPage;
@@ -142,6 +153,15 @@ public class Page : TemplateControl, IHttpHandler
        Hashtable items;
 
        bool _maintainScrollPositionOnPostBack;
+
+       private bool asyncMode = false;
+       private TimeSpan asyncTimeout;
+       private const double DefaultAsyncTimeout = 45.0;
+       private List<PageAsyncTask> parallelTasks;
+       private List<PageAsyncTask> serialTasks;
+
+       private ViewStateEncryptionMode viewStateEncryptionMode;
+       private bool controlRegisteredForViewStateEncryption = false;
 #endif
 
        #region Constructor
@@ -150,6 +170,16 @@ public class Page : TemplateControl, IHttpHandler
                scriptManager = new ClientScriptManager (this);
                Page = this;
                ID = "__Page";
+#if NET_2_0
+               PagesSection ps = WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
+               if (ps != null) {
+                       asyncTimeout = ps.AsyncTimeout;
+                       viewStateEncryptionMode = ps.ViewStateEncryptionMode;
+               } else {
+                       asyncTimeout = TimeSpan.FromSeconds (DefaultAsyncTimeout);
+                       viewStateEncryptionMode = ViewStateEncryptionMode.Auto;
+               }
+#endif
        }
 
        #endregion              
@@ -268,7 +298,7 @@ public class Page : TemplateControl, IHttpHandler
        public string Culture
        {
                get { return Thread.CurrentThread.CurrentCulture.Name; }
-               set { Thread.CurrentThread.CurrentCulture = new CultureInfo (value); }
+               set { Thread.CurrentThread.CurrentCulture = GetPageCulture (value, Thread.CurrentThread.CurrentCulture); }
        }
 #else
        [EditorBrowsable (EditorBrowsableState.Never)]
@@ -281,7 +311,15 @@ public class Page : TemplateControl, IHttpHandler
 #if NET_2_0
        public virtual bool EnableEventValidation {
                get { return _eventValidation; }
-               set { _eventValidation = value;}
+               set {
+                       if (_lifeCycle > PageLifeCycle.Init)
+                               throw new InvalidOperationException ("The 'EnableEventValidation' property can be set only in the Page_init, the Page directive or in the <pages> configuration section.");
+                       _eventValidation = value;
+               }
+       }
+
+       internal PageLifeCycle LifeCycle {
+               get { return _lifeCycle; }
        }
 #endif
 
@@ -308,6 +346,13 @@ public class Page : TemplateControl, IHttpHandler
                set { _viewStateMac = value; }
        }
 
+#if NET_1_1
+       internal bool EnableViewStateMacInternal {
+               get { return _viewStateMac; }
+               set { _viewStateMac = value; }
+       }
+#endif
+       
        [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
        [Browsable (false), DefaultValue ("")]
        [WebSysDescription ("The URL of a page used for error redirection.")]
@@ -419,6 +464,18 @@ public class Page : TemplateControl, IHttpHandler
        }
 #endif
 
+#if !TARGET_J2EE
+       internal string theForm {
+               get {
+                       return "theForm";
+               }
+       }
+       
+       internal bool IsMultiForm {
+               get { return false; }
+       }
+#endif
+
        [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
        [Browsable (false)]
        public HttpRequest Request
@@ -523,7 +580,7 @@ public class Page : TemplateControl, IHttpHandler
                                _styleSheetTheme = ps.StyleSheetTheme;
                }
                if (_styleSheetTheme != null && _styleSheetTheme != "")
-                       _styleSheetPageTheme = ThemeDirectoryCompiler.GetCompiledInstance ("~/App_Themes/" + _styleSheetTheme + "/", _context);
+                       _styleSheetPageTheme = ThemeDirectoryCompiler.GetCompiledInstance (_styleSheetTheme, _context);
        }
 
        void InitializeTheme ()
@@ -534,7 +591,8 @@ public class Page : TemplateControl, IHttpHandler
                                _theme = ps.Theme;
                }
                if (_theme != null && _theme != "") {
-                       _pageTheme = ThemeDirectoryCompiler.GetCompiledInstance ("~/App_Themes/" + _theme + "/", _context);
+                       _pageTheme = ThemeDirectoryCompiler.GetCompiledInstance (_theme, _context);
+                       _pageTheme.SetPage (this);
                }
        }
 
@@ -607,6 +665,17 @@ public class Page : TemplateControl, IHttpHandler
                set { _transactionMode = value; }
        }
 
+#if !NET_2_0
+       //
+       // This method is here just to remove the warning about "_transactionMode" not being
+       // used.  We probably will use it internally at some point.
+       //
+       internal int GetTransactionMode ()
+       {
+               return _transactionMode;
+       }
+#endif
+       
 #if NET_2_0
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
@@ -614,7 +683,7 @@ public class Page : TemplateControl, IHttpHandler
        public string UICulture
        {
                get { return Thread.CurrentThread.CurrentUICulture.Name; }
-               set { Thread.CurrentThread.CurrentUICulture = new CultureInfo (value); }
+               set { Thread.CurrentThread.CurrentUICulture = GetPageCulture (value, Thread.CurrentThread.CurrentUICulture); }
        }
 #else
        [EditorBrowsable (EditorBrowsableState.Never)]
@@ -660,6 +729,33 @@ public class Page : TemplateControl, IHttpHandler
 
        #region Methods
 
+#if NET_2_0
+       CultureInfo GetPageCulture (string culture, CultureInfo deflt)
+       {
+               if (culture == null)
+                       return deflt;
+               CultureInfo ret = null;
+               if (culture.StartsWith ("auto", StringComparison.InvariantCultureIgnoreCase)) {
+#if TARGET_J2EE
+                       if (Context.IsPortletRequest)
+                               return deflt;
+#endif
+                       string[] languages = Request.UserLanguages;
+                       try {
+                               if (languages != null && languages.Length > 0)
+                                       ret = CultureInfo.CreateSpecificCulture (languages[0]);
+                       } catch {
+                       }
+                       
+                       if (ret == null)
+                               ret = deflt;
+               } else
+                       ret = CultureInfo.CreateSpecificCulture (culture);
+
+               return ret;
+       }
+#endif
+
        [EditorBrowsable (EditorBrowsableState.Never)]
        protected IAsyncResult AspCompatBeginProcessRequest (HttpContext context,
                                                             AsyncCallback cb, 
@@ -697,18 +793,21 @@ public class Page : TemplateControl, IHttpHandler
                        return null;
 
                NameValueCollection coll = null;
-               if (0 == String.Compare (Request.HttpMethod, "POST", true, CultureInfo.InvariantCulture)) {
-                       coll =  req.Form;
-                       WebROCollection c = (WebROCollection) coll;
-                       allow_load = !c.GotID;
-                       if (allow_load) {
-                               c.ID = GetTypeHashCode ();
-                       } else {
-                               allow_load = (c.ID == GetTypeHashCode ());
-                       }
-               } else  {
+               if (0 == String.Compare (Request.HttpMethod, "POST", true, CultureInfo.InvariantCulture))
+                       coll = req.Form;
+#if TARGET_J2EE
+               else if (IsPortletRender && req.Form ["__VIEWSTATE"] != null)
+                       coll = req.Form;
+#endif
+               else
                        coll = req.QueryString;
-               }
+
+               WebROCollection c = (WebROCollection) coll;
+               allow_load = !c.GotID;
+               if (allow_load)
+                       c.ID = GetTypeHashCode ();
+               else
+                       allow_load = (c.ID == GetTypeHashCode ());
 
                if (coll != null && coll ["__VIEWSTATE"] == null && coll ["__EVENTTARGET"] == null)
                        return null;
@@ -763,6 +862,12 @@ public class Page : TemplateControl, IHttpHandler
 
        internal void RequiresPostBackScript ()
        {
+#if NET_2_0
+               if (requiresPostBackScript)
+                       return;
+               ClientScript.RegisterHiddenField (postEventSourceID, String.Empty);
+               ClientScript.RegisterHiddenField (postEventArgumentID, String.Empty);
+#endif
                requiresPostBackScript = true;
        }
 
@@ -872,11 +977,7 @@ public class Page : TemplateControl, IHttpHandler
 #if NET_2_0
        protected internal override void Render (HtmlTextWriter writer) {
                if (MaintainScrollPositionOnPostBack) {
-                       RequiresPostBackScript ();
-
-                       string scriptUrl = ClientScript.GetWebResourceUrl (typeof (Page), "MaintainScrollPositionOnPostBack.js");
-
-                       ClientScript.RegisterClientScriptInclude (typeof (Page), "MaintainScrollPositionOnPostBack.js", scriptUrl);
+                       ClientScript.RegisterWebFormClientScript ();
 
                        ClientScript.RegisterHiddenField (ScrollPositionXID, Request [ScrollPositionXID]);
                        ClientScript.RegisterHiddenField (ScrollPositionYID, Request [ScrollPositionYID]);
@@ -884,13 +985,13 @@ public class Page : TemplateControl, IHttpHandler
                        StringBuilder script = new StringBuilder ();
                        script.AppendLine ("<script type=\"text/javascript\">");
                        script.AppendLine ("<!--");
-                       script.AppendLine ("theForm.oldSubmit = theForm.submit");
-                       script.AppendLine ("theForm.submit = WebForm_SaveScrollPositionSubmit");
-                       script.AppendLine ("theForm.oldOnSubmit = theForm.onsubmit");
-                       script.AppendLine ("theForm.onsubmit = WebForm_SaveScrollPositionOnSubmit");
+                       script.AppendLine (theForm + ".oldSubmit = " + theForm + ".submit;");
+                       script.AppendLine (theForm + ".submit = WebForm_SaveScrollPositionSubmit;");
+                       script.AppendLine (theForm + ".oldOnSubmit = " + theForm + ".onsubmit;");
+                       script.AppendLine (theForm + ".onsubmit = WebForm_SaveScrollPositionOnSubmit;");
                        if (IsPostBack) {
-                               script.AppendLine ("theForm.oldOnLoad = window.onload");
-                               script.AppendLine ("window.onload = WebForm_RestoreScrollPosition");
+                               script.AppendLine (theForm + ".oldOnLoad = window.onload;");
+                               script.AppendLine ("window.onload = function () { WebForm_RestoreScrollPosition (" + theForm + "); };");
                        }
                        script.AppendLine ("// -->");
                        script.AppendLine ("</script>");
@@ -903,21 +1004,46 @@ public class Page : TemplateControl, IHttpHandler
 
        private void RenderPostBackScript (HtmlTextWriter writer, string formUniqueID)
        {
+#if ONLY_1_1
                writer.WriteLine ("<input type=\"hidden\" name=\"{0}\" value=\"\" />", postEventSourceID);
                writer.WriteLine ("<input type=\"hidden\" name=\"{0}\" value=\"\" />", postEventArgumentID);
+#endif
                writer.WriteLine ();
-               writer.WriteLine ("<script language=\"javascript\">");
-               writer.WriteLine ("<!--");
+               
+               ClientScriptManager.WriteBeginScriptBlock (writer);
 
-               writer.WriteLine ("\tvar theForm;\n\tif (document.getElementById) {{ theForm = document.getElementById ('{0}'); }}", formUniqueID);
-               writer.WriteLine ("\telse {{ theForm = document.{0}; }}", formUniqueID);
-               writer.WriteLine ("\tfunction __doPostBack(eventTarget, eventArgument) {");
-               writer.WriteLine ("\t\ttheForm.{0}.value = eventTarget;", postEventSourceID);
-               writer.WriteLine ("\t\ttheForm.{0}.value = eventArgument;", postEventArgumentID);
-               writer.WriteLine ("\t\ttheForm.submit();");
-               writer.WriteLine ("\t}");
-               writer.WriteLine ("// -->");
-               writer.WriteLine ("</script>");
+#if ONLY_1_1
+               RenderClientScriptFormDeclaration (writer, formUniqueID);
+#endif
+               if (IsMultiForm) {
+                       writer.WriteLine ("{0}._form = {0};", theForm);
+                       writer.Write (theForm + ".");
+               }
+               else {
+                       writer.WriteLine ("window._form = {0};", theForm);
+               }
+               writer.WriteLine ("__doPostBack = function (eventTarget, eventArgument) {");
+#if NET_2_0
+               writer.WriteLine ("\tif(this._form.onsubmit && this._form.onsubmit() == false) return;");
+#else
+               writer.WriteLine ("\tif(document.ValidatorOnSubmit && !ValidatorOnSubmit()) return;");
+#endif
+               writer.WriteLine ("\tthis._form.{0}.value = eventTarget;", postEventSourceID);
+               writer.WriteLine ("\tthis._form.{0}.value = eventArgument;", postEventArgumentID);
+               writer.WriteLine ("\tthis._form.submit();");
+               writer.WriteLine ("}");
+               ClientScriptManager.WriteEndScriptBlock (writer);
+       }
+
+       void RenderClientScriptFormDeclaration (HtmlTextWriter writer, string formUniqueID)
+       {
+               writer.WriteLine ("\tvar {0};\n\tif (document.getElementById) {{ {0} = document.getElementById ('{1}'); }}", theForm, formUniqueID);
+               writer.WriteLine ("\telse {{ {0} = document.{1}; }}", theForm, formUniqueID);
+               writer.WriteLine ("\t{0}._instanceVariableName = '{0}';", theForm);
+#if TARGET_J2EE
+               string serverUrl = Context.ServletResponse.encodeURL (Request.RawUrl);
+               writer.WriteLine ("\t{0}.serverURL = {1};", theForm, ClientScriptManager.GetScriptLiteral (serverUrl));
+#endif
        }
 
        internal void OnFormRender (HtmlTextWriter writer, string formUniqueID)
@@ -927,65 +1053,51 @@ public class Page : TemplateControl, IHttpHandler
 
                renderingForm = true;
                writer.WriteLine ();
+
+#if NET_2_0
+               ClientScriptManager.WriteBeginScriptBlock (writer);
+               RenderClientScriptFormDeclaration (writer, formUniqueID);
+               ClientScriptManager.WriteEndScriptBlock (writer);
+#endif
+
+               if (handleViewState)
+                       scriptManager.RegisterHiddenField ("__VIEWSTATE", _savedViewState);
+
                scriptManager.WriteHiddenFields (writer);
                if (requiresPostBackScript) {
                        RenderPostBackScript (writer, formUniqueID);
                        postBackScriptRendered = true;
                }
-
-               if (handleViewState) {
-                       string vs = GetViewStateString ();
-                       writer.Write ("<input type=\"hidden\" name=\"__VIEWSTATE\" ");
-                       writer.WriteLine ("value=\"{0}\" />", vs);
-               }
-
-               scriptManager.WriteClientScriptBlocks (writer);
-       }
-
-       LosFormatter GetFormatter ()
-       {
 #if NET_2_0
-               PagesSection config = (PagesSection) WebConfigurationManager.GetSection ("system.web/pages");
-#else
-               PagesConfiguration config = PagesConfiguration.GetInstance (_context);
-#endif
-               byte [] vkey = null;
-               if (config.EnableViewStateMac) {
-#if NET_2_0
-                       MachineKeySection mconfig = (MachineKeySection) WebConfigurationManager.GetSection ("system.web/machineKey");
-                       vkey = mconfig.ValidationKeyBytes;
-#else
-                       MachineKeyConfig mconfig = HttpContext.GetAppConfig ("system.web/machineKey") as MachineKeyConfig;
-                       vkey = mconfig.ValidationKey;
+               scriptManager.WriteWebFormClientScript (writer);
 #endif
-               }
-
-               return new LosFormatter (config.EnableViewStateMac, vkey);
+               scriptManager.WriteClientScriptBlocks (writer);
        }
 
-       string GetViewStateString ()
+       internal IStateFormatter GetFormatter ()
        {
-               if (_savedViewState == null)
-                       return null;
-
-               LosFormatter fmt = GetFormatter ();
-               return fmt.SerializeToBase64 (_savedViewState);
+               return new ObjectStateFormatter (this);
        }
 
-       internal object GetSavedViewState ()
+       internal string GetSavedViewState ()
        {
                return _savedViewState;
        }
 
        internal void OnFormPostRender (HtmlTextWriter writer, string formUniqueID)
        {
-               scriptManager.WriteArrayDeclares (writer);
-
+#if NET_2_0
+               scriptManager.SaveEventValidationState ();
+               scriptManager.WriteExpandoAttributes (writer);
+#endif
+               scriptManager.WriteHiddenFields (writer);
                if (!postBackScriptRendered && requiresPostBackScript)
                        RenderPostBackScript (writer, formUniqueID);
+#if NET_2_0
+               scriptManager.WriteWebFormClientScript (writer);
+#endif
 
-               scriptManager.WriteHiddenFields (writer);
-               scriptManager.WriteClientScriptIncludes (writer);
+               scriptManager.WriteArrayDeclares (writer);
                scriptManager.WriteStartupScriptBlocks (writer);
                renderingForm = false;
                postBackScriptRendered = false;
@@ -993,49 +1105,47 @@ public class Page : TemplateControl, IHttpHandler
 
        private void ProcessPostData (NameValueCollection data, bool second)
        {
-               if (data == null)
-                       return;
-
-               if (_requiresPostBackCopy == null && _requiresPostBack != null)
-                       _requiresPostBackCopy = (ArrayList) _requiresPostBack.Clone ();
-
-               Hashtable used = new Hashtable ();
-               foreach (string id in data.AllKeys){
-                       if (id == "__VIEWSTATE" || id == postEventSourceID || id == postEventArgumentID)
-                               continue;
+               if (data != null) {
+                       Hashtable used = new Hashtable ();
+                       foreach (string id in data.AllKeys){
+                               if (id == "__VIEWSTATE" || id == postEventSourceID || id == postEventArgumentID)
+                                       continue;
 
-                       string real_id = id;
-                       int dot = real_id.IndexOf ('.');
-                       if (dot >= 1)
-                               real_id = real_id.Substring (0, dot);
+                               string real_id = id;
+                               int dot = real_id.IndexOf ('.');
+                               if (dot >= 1)
+                                       real_id = real_id.Substring (0, dot);
                        
-                       if (real_id == null || used.ContainsKey (real_id))
-                               continue;
+                               if (real_id == null || used.ContainsKey (real_id))
+                                       continue;
 
-                       used.Add (real_id, real_id);
+                               used.Add (real_id, real_id);
 
-                       Control ctrl = FindControl (real_id);
-                       if (ctrl != null){
-                               IPostBackDataHandler pbdh = ctrl as IPostBackDataHandler;
-                               IPostBackEventHandler pbeh = ctrl as IPostBackEventHandler;
+                               Control ctrl = FindControl (real_id);
+                               if (ctrl != null){
+                                       IPostBackDataHandler pbdh = ctrl as IPostBackDataHandler;
+                                       IPostBackEventHandler pbeh = ctrl as IPostBackEventHandler;
 
-                               if (pbdh == null) {
-                                       if (pbeh != null)
-                                               RegisterRequiresRaiseEvent (pbeh);
-                                       continue;
-                               }
+                                       if (pbdh == null) {
+                                               if (pbeh != null)
+                                                       RegisterRequiresRaiseEvent (pbeh);
+                                               continue;
+                                       }
                
-                               if (pbdh.LoadPostData (real_id, data) == true) {
-                                       if (requiresPostDataChanged == null)
-                                               requiresPostDataChanged = new ArrayList ();
-                                       requiresPostDataChanged.Add (pbdh);
+                                       if (pbdh.LoadPostData (real_id, data) == true) {
+                                               if (requiresPostDataChanged == null)
+                                                       requiresPostDataChanged = new ArrayList ();
+                                               requiresPostDataChanged.Add (pbdh);
+                                       }
+                               
                                        if (_requiresPostBackCopy != null)
-                                               _requiresPostBackCopy.Remove (ctrl.UniqueID);
+                                               _requiresPostBackCopy.Remove (real_id);
+
+                               } else if (!second) {
+                                       if (secondPostData == null)
+                                               secondPostData = new NameValueCollection ();
+                                       secondPostData.Add (real_id, data [id]);
                                }
-                       } else if (!second) {
-                               if (secondPostData == null)
-                                       secondPostData = new NameValueCollection ();
-                               secondPostData.Add (real_id, data [id]);
                        }
                }
 
@@ -1052,23 +1162,28 @@ public class Page : TemplateControl, IHttpHandler
        
                                                requiresPostDataChanged.Add (pbdh);
                                        }
-                               } else if (second) {
+                               } else if (!second) {
                                        if (list1 == null)
                                                list1 = new ArrayList ();
                                        list1.Add (id);
                                }
                        }
                }
-               _requiresPostBack = list1;
+               _requiresPostBackCopy = second ? null : list1;
+               if (second)
+                       secondPostData = null;
        }
 
        [EditorBrowsable (EditorBrowsableState.Never)]
-#if NET_2_0 || TARGET_JVM
+#if NET_2_0
        public virtual void ProcessRequest (HttpContext context)
 #else
        public void ProcessRequest (HttpContext context)
 #endif
        {
+#if NET_2_0
+               _lifeCycle = PageLifeCycle.Unknown;
+#endif
                _context = context;
                if (clientTarget != null)
                        Request.ClientTarget = clientTarget;
@@ -1096,8 +1211,14 @@ public class Page : TemplateControl, IHttpHandler
                        throw;
                } finally {
                        try {
+#if NET_2_0
+                               _lifeCycle = PageLifeCycle.Unload;
+#endif
                                RenderTrace ();
                                UnloadRecursive (true);
+#if NET_2_0
+                               _lifeCycle = PageLifeCycle.End;
+#endif
                        } catch {}
                        if (Thread.CurrentThread.CurrentCulture.Equals (culture) == false)
                                Thread.CurrentThread.CurrentCulture = culture;
@@ -1108,6 +1229,65 @@ public class Page : TemplateControl, IHttpHandler
        }
        
 #if NET_2_0
+       delegate void ProcessRequestDelegate (HttpContext context);
+
+       private sealed class DummyAsyncResult : IAsyncResult
+       {
+               readonly object state;
+               readonly WaitHandle asyncWaitHandle;
+               readonly bool completedSynchronously;
+               readonly bool isCompleted;
+
+               public DummyAsyncResult (bool isCompleted, bool completedSynchronously, object state) 
+               {
+                       this.isCompleted = isCompleted;
+                       this.completedSynchronously = completedSynchronously;
+                       this.state = state;
+                       if (isCompleted) {
+                               asyncWaitHandle = new ManualResetEvent (true);
+                       }
+                       else {
+                               asyncWaitHandle = new ManualResetEvent (false);
+                       }
+               }
+
+               #region IAsyncResult Members
+
+               public object AsyncState {
+                       get { return state; }
+               }
+
+               public WaitHandle AsyncWaitHandle {
+                       get { return asyncWaitHandle; }
+               }
+
+               public bool CompletedSynchronously {
+                       get { return completedSynchronously; }
+               }
+
+               public bool IsCompleted {
+                       get { return isCompleted; }
+               }
+
+               #endregion
+       }
+
+       protected IAsyncResult AsyncPageBeginProcessRequest (HttpContext context, AsyncCallback callback, object extraData) 
+       {
+               ProcessRequest (context);
+               DummyAsyncResult asyncResult = new DummyAsyncResult (true, true, extraData);
+
+               if (callback != null) {
+                       callback (asyncResult);
+               }
+               
+               return asyncResult;
+       }
+
+       protected void AsyncPageEndProcessRequest (IAsyncResult result) 
+       {
+       }
+
        internal void ProcessCrossPagePostBack (HttpContext context)
        {
                isCrossPagePostBack = true;
@@ -1120,46 +1300,79 @@ public class Page : TemplateControl, IHttpHandler
                _requestValueCollection = this.DeterminePostBackMode();
 
 #if NET_2_0
+               _lifeCycle = PageLifeCycle.Start;
                // http://msdn2.microsoft.com/en-us/library/ms178141.aspx
                if (_requestValueCollection != null) {
                        if (!isCrossPagePostBack && _requestValueCollection [PreviousPageID] != null && _requestValueCollection [PreviousPageID] != Request.FilePath) {
-                               LoadPreviousPageReference ();
+                               _doLoadPreviousPage = true;
                        }
                        else {
                                isCallback = _requestValueCollection [CallbackArgumentID] != null;
-                               isPostBack = !isCallback;
+                               // LAMESPEC: on Callback IsPostBack is set to false, but true.
+                               //isPostBack = !isCallback;
+                               isPostBack = true;
+                       }
+                       string lastFocus = _requestValueCollection [LastFocusID];
+                       if (!String.IsNullOrEmpty (lastFocus)) {
+                               _focusedControlID = UniqueID2ClientID (lastFocus);
                        }
                }
+               
+               // if request was transfered from other page - track Prev. Page
+               previousPage = _context.LastPage;
+               _context.LastPage = this;
 
+               _lifeCycle = PageLifeCycle.PreInit;
                OnPreInit (EventArgs.Empty);
 
                InitializeTheme ();
                ApplyMasterPage ();
+               _lifeCycle = PageLifeCycle.Init;
 #endif
                Trace.Write ("aspx.page", "Begin Init");
                InitRecursive (null);
                Trace.Write ("aspx.page", "End Init");
 
 #if NET_2_0
+               _lifeCycle = PageLifeCycle.InitComplete;
                OnInitComplete (EventArgs.Empty);
 #endif
                        
                renderingForm = false;  
+#if NET_2_0
+               if (IsPostBack || IsCallback) {
+                       _lifeCycle = PageLifeCycle.PreLoad;
+                       if (_requestValueCollection != null)
+                               scriptManager.RestoreEventValidationState (_requestValueCollection [scriptManager.EventStateFieldName]);
+#else
                if (IsPostBack) {
+#endif
                        Trace.Write ("aspx.page", "Begin LoadViewState");
                        LoadPageViewState ();
                        Trace.Write ("aspx.page", "End LoadViewState");
                        Trace.Write ("aspx.page", "Begin ProcessPostData");
+#if TARGET_J2EE
+                       if (!IsGetBack)
+#endif
                        ProcessPostData (_requestValueCollection, false);
                        Trace.Write ("aspx.page", "End ProcessPostData");
                }
 
 #if NET_2_0
                OnPreLoad (EventArgs.Empty);
+               _lifeCycle = PageLifeCycle.Load;
 #endif
 
                LoadRecursive ();
+#if NET_2_0
+#if TARGET_J2EE
+               if (!IsGetBack)
+#endif
+               if (IsPostBack || IsCallback) {
+                       _lifeCycle = PageLifeCycle.ControlEvents;
+#else
                if (IsPostBack) {
+#endif
                        Trace.Write ("aspx.page", "Begin ProcessPostData Second Try");
                        ProcessPostData (secondPostData, true);
                        Trace.Write ("aspx.page", "End ProcessPostData Second Try");
@@ -1172,6 +1385,7 @@ public class Page : TemplateControl, IHttpHandler
                }
                
 #if NET_2_0
+               _lifeCycle = PageLifeCycle.LoadComplete;
                OnLoadComplete (EventArgs.Empty);
 
                if (IsCrossPagePostBack)
@@ -1184,6 +1398,8 @@ public class Page : TemplateControl, IHttpHandler
                        callbackOutput.Flush ();
                        return;
                }
+
+               _lifeCycle = PageLifeCycle.PreRender;
 #endif
                
                Trace.Write ("aspx.page", "Begin PreRender");
@@ -1191,6 +1407,9 @@ public class Page : TemplateControl, IHttpHandler
                Trace.Write ("aspx.page", "End PreRender");
                
 #if NET_2_0
+               ExecuteRegisteredAsyncTasks ();
+
+               _lifeCycle = PageLifeCycle.PreRenderComplete;
                OnPreRenderComplete (EventArgs.Empty);
 #endif
 
@@ -1199,7 +1418,17 @@ public class Page : TemplateControl, IHttpHandler
                Trace.Write ("aspx.page", "End SaveViewState");
                
 #if NET_2_0
+               _lifeCycle = PageLifeCycle.SaveStateComplete;
                OnSaveStateComplete (EventArgs.Empty);
+#if TARGET_J2EE
+               if (OnSaveStateCompleteForPortlet ())
+                       return;
+#endif // TARGET_J2EE
+#endif // NET_2_0
+
+#if NET_2_0
+               _lifeCycle = PageLifeCycle.Render;
+               scriptManager.ResetEventValidationState ();
 #endif
                
                //--
@@ -1227,8 +1456,25 @@ public class Page : TemplateControl, IHttpHandler
                }
        }
        
+#if NET_2_0
+       bool CheckForValidationSupport (Control targetControl)
+       {
+               if (targetControl == null)
+                       return false;
+               Type type = targetControl.GetType ();
+               object[] attributes = type.GetCustomAttributes (false);
+               foreach (object attr in attributes)
+                       if (attr is SupportsEventValidationAttribute)
+                               return true;
+               return false;
+       }
+#endif
+       
        void RaisePostBackEvents ()
        {
+#if NET_2_0
+               Control targetControl;
+#endif
                if (requiresRaiseEvent != null) {
                        RaisePostBackEvent (requiresRaiseEvent, null);
                        return;
@@ -1244,7 +1490,13 @@ public class Page : TemplateControl, IHttpHandler
                        return;
                 }
 
+#if NET_2_0
+               targetControl = FindControl (eventTarget);
+               IPostBackEventHandler target = targetControl as IPostBackEventHandler;
+#else
                IPostBackEventHandler target = FindControl (eventTarget) as IPostBackEventHandler;
+#endif
+                       
                if (target == null)
                        return;
 
@@ -1266,6 +1518,11 @@ public class Page : TemplateControl, IHttpHandler
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        protected virtual void RaisePostBackEvent (IPostBackEventHandler sourceControl, string eventArgument)
        {
+#if NET_2_0
+               Control targetControl = sourceControl as Control;
+               if (targetControl != null && CheckForValidationSupport (targetControl))
+                       scriptManager.ValidateEvent (targetControl.UniqueID, eventArgument);
+#endif
                sourceControl.RaisePostBackEvent (eventArgument);
        }
        
@@ -1296,7 +1553,7 @@ public class Page : TemplateControl, IHttpHandler
                scriptManager.RegisterHiddenField (hiddenFieldName, hiddenFieldInitialValue);
        }
 
-       [MonoTODO("Used in HtmlForm")]
+       [MonoTODO("Not implemented, Used in HtmlForm")]
        internal void RegisterClientScriptFile (string a, string b, string c)
        {
                throw new NotImplementedException ();
@@ -1319,9 +1576,17 @@ public class Page : TemplateControl, IHttpHandler
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        public void RegisterRequiresPostBack (Control control)
        {
+#if NET_2_0
+               if (!(control is IPostBackDataHandler))
+                       throw new HttpException ("The control to register does not implement the IPostBackDataHandler interface.");
+#endif
+               
                if (_requiresPostBack == null)
                        _requiresPostBack = new ArrayList ();
 
+               if (_requiresPostBack.Contains (control.UniqueID))
+                       return;
+
                _requiresPostBack.Add (control.UniqueID);
        }
 
@@ -1349,48 +1614,69 @@ public class Page : TemplateControl, IHttpHandler
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        protected virtual void SavePageStateToPersistenceMedium (object viewState)
        {
-               _savedViewState = viewState;
+               PageStatePersister persister = this.PageStatePersister;
+               if (persister == null)
+                       return;
+               Pair pair = viewState as Pair;
+               if (pair != null) {
+                       persister.ViewState = pair.First;
+                       persister.ControlState = pair.Second;
+               } else
+                       persister.ViewState = viewState;
+               persister.Save ();
        }
 
+       internal string RawViewState {
+               get {
+                       NameValueCollection postdata = _requestValueCollection;
+                       string view_state;
+                       if (postdata == null || (view_state = postdata ["__VIEWSTATE"]) == null)
+                               return null;
+
+                       if (view_state == "")
+                               return null;
+                       return view_state;
+               }
+               set { _savedViewState = value; }
+       }
+
+#if NET_2_0
+       protected virtual 
+#else
+       internal
+#endif
+       PageStatePersister PageStatePersister {
+               get {
+                       if (page_state_persister == null)
+                               page_state_persister = new HiddenFieldPageStatePersister (this);
+                       return page_state_persister;
+               }
+       }
+       
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        protected virtual object LoadPageStateFromPersistenceMedium ()
        {
-               NameValueCollection postdata = _requestValueCollection;
-               string view_state;
-               if (postdata == null || (view_state = postdata ["__VIEWSTATE"]) == null)
-                       return null;
-
-               _savedViewState = null;
-               if (view_state == "")
+               PageStatePersister persister = this.PageStatePersister;
+               if (persister == null)
                        return null;
-
-               LosFormatter fmt = GetFormatter ();
-               try {
-                       _savedViewState = fmt.Deserialize (view_state);
-               } catch (Exception e) {
-                       throw new HttpException ("Error restoring page viewstate.", e);
-               }
-               return _savedViewState;
+               persister.Load ();
+               return new Pair (persister.ViewState, persister.ControlState);
        }
 
        internal void LoadPageViewState()
        {
-               object sState = LoadPageStateFromPersistenceMedium ();
+               Pair sState = LoadPageStateFromPersistenceMedium () as Pair;
                if (sState != null) {
-#if NET_2_0
-                       Triplet data = (Triplet) sState;
-                       if (allow_load) {
-                               LoadPageControlState (data.Third);
-                               LoadViewStateRecursive (data.First);
-                               _requiresPostBack = data.Second as ArrayList;
-                       }
-#else
-                       Pair pair = (Pair) sState;
                        if (allow_load) {
-                               LoadViewStateRecursive (pair.First);
-                               _requiresPostBack = pair.Second as ArrayList;
-                       }
+#if NET_2_0
+                               LoadPageControlState (sState.Second);
 #endif
+                               Pair vsr = sState.First as Pair;
+                               if (vsr != null) {
+                                       LoadViewStateRecursive (vsr.First);
+                                       _requiresPostBackCopy = vsr.Second as ArrayList;
+                               }
+                       }
                }
        }
 
@@ -1405,27 +1691,23 @@ public class Page : TemplateControl, IHttpHandler
 
                object viewState = SaveViewStateRecursive ();
                object reqPostback = (_requiresPostBack != null && _requiresPostBack.Count > 0) ? _requiresPostBack : null;
+               Pair vsr = null;
 
-#if NET_2_0
-               Triplet triplet = new Triplet ();
-               triplet.First = viewState;
-               triplet.Second = reqPostback;
-               triplet.Third = controlState;
-
-               if (triplet.First == null && triplet.Second == null && triplet.Third == null)
-                       triplet = null;
-                       
-               SavePageStateToPersistenceMedium (triplet);
-#else
+               if (viewState != null || reqPostback != null)
+                       vsr = new Pair (viewState, reqPostback);
                Pair pair = new Pair ();
-               pair.First = viewState;
-               pair.Second = reqPostback;
 
-               if (pair.First == null && pair.Second == null)
-                       pair = null;
-                       
-               SavePageStateToPersistenceMedium (pair);
+               pair.First = vsr;
+#if NET_2_0
+               pair.Second = controlState;
+#else
+               pair.Second = null;
 #endif
+               if (pair.First == null && pair.Second == null)
+                       SavePageStateToPersistenceMedium (null);
+               else
+                       SavePageStateToPersistenceMedium (pair);                
+
        }
 
        public virtual void Validate ()
@@ -1488,7 +1770,10 @@ public class Page : TemplateControl, IHttpHandler
        {
                if (_context == null)
                        return;
-
+#if NET_2_0
+               if (IsCallback)
+                       return;
+#endif
                if (!renderingForm)
                        throw new HttpException ("Control '" +
                                                 control.ClientID +
@@ -1623,6 +1908,41 @@ public class Page : TemplateControl, IHttpHandler
                        EventHandler eh = (EventHandler) (Events [PreRenderCompleteEvent]);
                        if (eh != null) eh (this, e);
                }
+
+               if (Form == null)
+                       return;
+               if (!Form.DetermineRenderUplevel ())
+                       return;
+
+               /* figure out if we have some control we're going to focus */
+               if (String.IsNullOrEmpty (_focusedControlID)) {
+                       _focusedControlID = Form.DefaultFocus;
+                       if (String.IsNullOrEmpty (_focusedControlID))
+                               _focusedControlID = Form.DefaultButton;
+               }
+
+                       if (!String.IsNullOrEmpty (_focusedControlID)) {
+                               ClientScript.RegisterWebFormClientScript ();
+                               ClientScript.RegisterStartupScript ("HtmlForm-DefaultButton-StartupScript",
+                                                                        String.Format ("<script type=\"text/javascript\">\n" +
+                                                                                       "<!--\n" +
+                                                                                       "WebForm_AutoFocus('{0}');// -->\n" +
+                                                                                       "</script>\n", _focusedControlID));
+                       }
+
+                       if (Form.SubmitDisabledControls && _hasEnabledControlArray) {
+                               ClientScript.RegisterWebFormClientScript ();
+                               ClientScript.RegisterOnSubmitStatement ("HtmlForm-SubmitDisabledControls-SubmitStatement",
+                                                                                "WebForm_ReEnableControls(this);");
+                       }
+       }
+
+       internal void RegisterEnabledControl (Control control)
+       {
+               if (Form == null || !Page.Form.SubmitDisabledControls || !Page.Form.DetermineRenderUplevel ())
+                       return;
+               _hasEnabledControlArray = true;
+               Page.ClientScript.RegisterArrayDeclaration (EnabledControlArrayID, String.Format ("'{0}'", control.ClientID));
        }
        
        protected virtual void OnSaveStateComplete (EventArgs e)
@@ -1645,7 +1965,13 @@ public class Page : TemplateControl, IHttpHandler
        [BrowsableAttribute (false)]
        [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
        public Page PreviousPage {
-               get { return previousPage; }
+               get {
+                       if (_doLoadPreviousPage) {
+                               _doLoadPreviousPage = false;
+                               LoadPreviousPageReference ();
+                       }
+                       return previousPage;
+               }
        }
 
        
@@ -1660,6 +1986,13 @@ public class Page : TemplateControl, IHttpHandler
        public bool IsCrossPagePostBack {
                get { return isCrossPagePostBack; }
        }
+
+       public new virtual char IdSeparator {
+               get {
+                       //TODO: why override?
+                       return base.IdSeparator;
+               }
+       }
        
        string ProcessCallbackData ()
        {
@@ -1667,13 +2000,31 @@ public class Page : TemplateControl, IHttpHandler
                if (callbackTarget == null || callbackTarget.Length == 0)
                        throw new HttpException ("Callback target not provided.");
 
-               ICallbackEventHandler target = FindControl (callbackTarget) as ICallbackEventHandler;
+               Control targetControl = FindControl (callbackTarget);
+               ICallbackEventHandler target = targetControl as ICallbackEventHandler;
                if (target == null)
                        throw new HttpException (string.Format ("Invalid callback target '{0}'.", callbackTarget));
 
+               string callbackEventError = String.Empty;
+               string callBackResult;
                string callbackArgument = _requestValueCollection [CallbackArgumentID];
-               target.RaiseCallbackEvent (callbackArgument);
-               return target.GetCallbackResult ();
+
+               try {
+                       target.RaiseCallbackEvent (callbackArgument);
+               }
+               catch (Exception ex) {
+                       callbackEventError = String.Format ("e{0}", ex.Message);
+               }
+               
+               try {
+                       callBackResult = target.GetCallbackResult ();
+               }
+               catch (Exception ex) {
+                       return String.Format ("e{0}", ex.Message);
+               }
+               
+               string eventValidation = ClientScript.GetEventValidationStateFormatted ();
+               return String.Format ("{0}{1}|{2}{3}", callbackEventError, eventValidation == null ? 0 : eventValidation.Length, eventValidation, callBackResult);
        }
 
        [BrowsableAttribute (false)]
@@ -1690,7 +2041,305 @@ public class Page : TemplateControl, IHttpHandler
                        _title = null;
                }
        }
+
+       protected bool AsyncMode {
+               get { return asyncMode; }
+               set { asyncMode = value; }
+       }
+
+       public TimeSpan AsyncTimeout {
+               get { return asyncTimeout; }
+               set { asyncTimeout = value; }
+       }
+
+       public bool IsAsync {
+               get { return AsyncMode; }
+       }
        
+       [MonoTODO ("Not Implemented")]
+       protected internal virtual string UniqueFilePathSuffix {
+               get {
+                       throw new NotImplementedException ();
+               }
+       }
+
+       [MonoTODO ("Not Implemented")]
+       public int MaxPageStateFieldLength {
+               get {
+                       throw new NotImplementedException ();
+               }
+               set {
+                       throw new NotImplementedException ();
+               }
+       }
+
+       public void AddOnPreRenderCompleteAsync (BeginEventHandler beginHandler, EndEventHandler endHandler)
+       {
+               AddOnPreRenderCompleteAsync (beginHandler, endHandler, null);
+       }
+
+       public void AddOnPreRenderCompleteAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, Object state)
+       {
+               if (!IsAsync) {
+                       throw new InvalidOperationException ("AddOnPreRenderCompleteAsync called and Page.IsAsync == false");
+               }
+
+               if (_lifeCycle >= PageLifeCycle.PreRender) {
+                       throw new InvalidOperationException ("AddOnPreRenderCompleteAsync can only be called before PreRender.");
+               }
+
+               if (beginHandler == null) {
+                       throw new ArgumentNullException ("beginHandler");
+               }
+
+               if (endHandler == null) {
+                       throw new ArgumentNullException ("endHandler");
+               }
+
+               RegisterAsyncTask (new PageAsyncTask (beginHandler, endHandler, null, state, false));
+       }
+
+       private List<PageAsyncTask> ParallelTasks {
+               get
+               {
+                       if (parallelTasks == null) {
+                               parallelTasks = new List<PageAsyncTask>();
+                       }
+                       return parallelTasks;
+               }
+       }
+
+       private List<PageAsyncTask> SerialTasks {
+               get {
+                       if (serialTasks == null) {
+                               serialTasks = new List<PageAsyncTask> ();
+                       }
+                       return serialTasks;
+               }
+       }
+
+       public void RegisterAsyncTask (PageAsyncTask task) 
+       {
+               if (task == null) {
+                       throw new ArgumentNullException ("task");
+               }
+
+               if (task.ExecuteInParallel) {
+                       ParallelTasks.Add (task);
+               }
+               else {
+                       SerialTasks.Add (task);
+               }
+       }
+
+       public void ExecuteRegisteredAsyncTasks ()
+       {
+               if ((parallelTasks == null || parallelTasks.Count == 0) &&
+                       (serialTasks == null || serialTasks.Count == 0)){
+                       return;
+               }
+
+               if (parallelTasks != null) {
+                       DateTime startExecution = DateTime.Now;
+                       List<PageAsyncTask> localParallelTasks = parallelTasks;
+                       parallelTasks = null; // Shouldn't execute tasks twice
+                       List<IAsyncResult> asyncResults = new List<IAsyncResult>();
+                       foreach (PageAsyncTask parallelTask in localParallelTasks) {
+                               IAsyncResult result = parallelTask.BeginHandler (this, EventArgs.Empty, new AsyncCallback (EndAsyncTaskCallback), parallelTask.State);
+                               if (result.CompletedSynchronously) {
+                                       parallelTask.EndHandler (result);
+                               }
+                               else {
+                                       asyncResults.Add (result);
+                               }
+                       }
+
+                       if (asyncResults.Count > 0) {
+#if TARGET_JVM
+                               TimeSpan timeout = AsyncTimeout;
+                               long t1 = DateTime.Now.Ticks;
+                               bool signalled = true;
+                               for (int i = 0; i < asyncResults.Count; i++) {
+                                       if (asyncResults [i].IsCompleted)
+                                               continue;
+
+                                       if (signalled)
+                                               signalled = asyncResults [i].AsyncWaitHandle.WaitOne (timeout, false);
+
+                                       if (signalled) {
+                                               long t2 = DateTime.Now.Ticks;
+                                               timeout = AsyncTimeout - TimeSpan.FromTicks (t2 - t1);
+                                               if (timeout.Ticks <= 0)
+                                                       signalled = false;
+                                       }
+                                       else {
+                                               localParallelTasks [i].TimeoutHandler (asyncResults [i]);
+                                       }
+                               }
+#else
+                               WaitHandle [] waitArray = new WaitHandle [asyncResults.Count];
+                               int i = 0;
+                               for (i = 0; i < asyncResults.Count; i++) {
+                                       waitArray [i] = asyncResults [i].AsyncWaitHandle;
+                               }
+                               bool allSignalled = WaitHandle.WaitAll (waitArray, AsyncTimeout, false);
+                               if (!allSignalled) {
+                                       for (i = 0; i < asyncResults.Count; i++) {
+                                               if (!asyncResults [i].IsCompleted) {
+                                                       localParallelTasks [i].TimeoutHandler (asyncResults [i]);
+                                               }
+                                       }
+                               }
+#endif
+                       }
+                       DateTime endWait = DateTime.Now;
+                       TimeSpan elapsed = endWait - startExecution;
+                       if (elapsed <= AsyncTimeout) {
+                               AsyncTimeout -= elapsed;
+                       }
+                       else {
+                               AsyncTimeout = TimeSpan.FromTicks(0);
+                       }
+               }
+
+               if (serialTasks != null) {
+                       List<PageAsyncTask> localSerialTasks = serialTasks;
+                       serialTasks = null; // Shouldn't execute tasks twice
+                       foreach (PageAsyncTask serialTask in localSerialTasks) {
+                               DateTime startExecution = DateTime.Now;
+
+                               IAsyncResult result = serialTask.BeginHandler (this, EventArgs.Empty, new AsyncCallback (EndAsyncTaskCallback), serialTask);
+                               if (result.CompletedSynchronously) {
+                                       serialTask.EndHandler (result);
+                               }
+                               else {
+                                       bool done = result.AsyncWaitHandle.WaitOne (AsyncTimeout, false);
+                                       if (!done && !result.IsCompleted) {
+                                               serialTask.TimeoutHandler (result);
+                                       }
+                               }
+                               DateTime endWait = DateTime.Now;
+                               TimeSpan elapsed = endWait - startExecution;
+                               if (elapsed <= AsyncTimeout) {
+                                       AsyncTimeout -= elapsed;
+                               }
+                               else {
+                                       AsyncTimeout = TimeSpan.FromTicks (0);
+                               }
+                       }
+               }
+               AsyncTimeout = TimeSpan.FromSeconds (DefaultAsyncTimeout);
+       }
+
+       void EndAsyncTaskCallback (IAsyncResult result) 
+       {
+               PageAsyncTask task = (PageAsyncTask)result.AsyncState;
+               task.EndHandler (result);
+       }
+
+       public static HtmlTextWriter CreateHtmlTextWriterFromType (TextWriter tw, Type writerType)
+       {
+               Type htmlTextWriterType = typeof (HtmlTextWriter);
+               
+               if (!htmlTextWriterType.IsAssignableFrom (writerType)) {
+                       throw new HttpException (String.Format ("Type '{0}' cannot be assigned to HtmlTextWriter", writerType.FullName));
+               }
+
+               ConstructorInfo constructor = writerType.GetConstructor (new Type [] { typeof (TextWriter) });
+               if (constructor == null) {
+                       throw new HttpException (String.Format ("Type '{0}' does not have a consturctor that takes a TextWriter as parameter", writerType.FullName));
+               }
+
+               return (HtmlTextWriter) Activator.CreateInstance(writerType, tw);
+       }
+
+       public ViewStateEncryptionMode ViewStateEncryptionMode {
+               get { return viewStateEncryptionMode; }
+               set { viewStateEncryptionMode = value; }
+       }
+
+       public void RegisterRequiresViewStateEncryption ()
+       {
+               controlRegisteredForViewStateEncryption = true;
+       }
+
+       private static byte [] AES_IV = null;
+       private static byte [] TripleDES_IV = null;
+       private static object locker = new object ();
+       private static bool isEncryptionInitialized = false;
+
+       private static void InitializeEncryption () 
+       {
+               if (isEncryptionInitialized) {
+                       return;
+               }
+
+               lock (locker) {
+                       if (isEncryptionInitialized) {
+                               return;
+                       }
+
+                       string iv_string = "0BA48A9E-736D-40f8-954B-B2F62241F282";
+                       AES_IV = new byte [16];
+                       TripleDES_IV = new byte [8];
+
+                       int i;
+                       for (i = 0; i < AES_IV.Length; i++) {
+                               AES_IV [i] = (byte) iv_string [i];
+                       }
+
+                       for (i = 0; i < TripleDES_IV.Length; i++) {
+                               TripleDES_IV [i] = (byte) iv_string [i];
+                       }
+
+                       isEncryptionInitialized = true;
+               }
+       }
+
+       internal ICryptoTransform GetCryptoTransform (CryptoStreamMode cryptoStreamMode) 
+       {
+               ICryptoTransform transform = null;
+               MachineKeySection config = (MachineKeySection) WebConfigurationManager.GetSection (machineKeyConfigPath);
+               byte [] vk = config.ValidationKeyBytes;
+
+               switch (config.Validation) {
+               case MachineKeyValidation.SHA1:
+                       transform = SHA1.Create ();
+                       break;
+
+               case MachineKeyValidation.MD5:
+                       transform = MD5.Create ();
+                       break;
+
+               case MachineKeyValidation.AES:
+                       if (cryptoStreamMode == CryptoStreamMode.Read){
+                               transform = Rijndael.Create().CreateDecryptor(vk, AES_IV);
+                       } else {
+                               transform = Rijndael.Create().CreateEncryptor(vk, AES_IV);
+                       }
+                       break;
+
+               case MachineKeyValidation.TripleDES:
+                       if (cryptoStreamMode == CryptoStreamMode.Read){
+                               transform = TripleDES.Create().CreateDecryptor(vk, TripleDES_IV);
+                       } else {
+                               transform = TripleDES.Create().CreateEncryptor(vk, TripleDES_IV);
+                       }
+                       break;
+               }
+
+               return transform;
+       }
+
+       internal bool NeedViewStateEncryption {
+               get {
+                       return (ViewStateEncryptionMode == ViewStateEncryptionMode.Always ||
+                                       (ViewStateEncryptionMode == ViewStateEncryptionMode.Auto &&
+                                        controlRegisteredForViewStateEncryption));
+
+               }
+       }
+
        void ApplyMasterPage ()
        {
                if (masterPageFile != null && masterPageFile.Length > 0) {
@@ -1719,6 +2368,9 @@ public class Page : TemplateControl, IHttpHandler
        [BrowsableAttribute (false)]
        public MasterPage Master {
                get {
+                       if (Context == null || String.IsNullOrEmpty (masterPageFile))
+                               return null;
+
                        if (masterPage == null)
                                masterPage = MasterPage.CreateMasterPage (this, Context, masterPageFile, contentTemplates);
 
@@ -1726,11 +2378,51 @@ public class Page : TemplateControl, IHttpHandler
                }
        }
        
+       public void SetFocus (string clientID)
+       {
+               if (String.IsNullOrEmpty (clientID))
+                       throw new ArgumentNullException ("control");
+
+               if (_lifeCycle > PageLifeCycle.PreRender)
+                       throw new InvalidOperationException ("SetFocus can only be called before and during PreRender.");
+
+               if(Form==null)
+                       throw new InvalidOperationException ("A form tag with runat=server must exist on the Page to use SetFocus() or the Focus property.");
+
+               _focusedControlID = clientID;
+       }
+
+       public void SetFocus (Control control)
+       {
+               if (control == null)
+                       throw new ArgumentNullException ("control");
+
+               SetFocus (control.ClientID);
+       }
+       
        [EditorBrowsable (EditorBrowsableState.Advanced)]
        public void RegisterRequiresControlState (Control control)
        {
-               if (requireStateControls == null) requireStateControls = new ArrayList ();
-               requireStateControls.Add (control);
+               if (control == null)
+                       throw new ArgumentNullException ("control");
+
+               if (RequiresControlState (control))
+                       return;
+
+               if (requireStateControls == null)
+                       requireStateControls = new ArrayList ();
+               int n = requireStateControls.Add (control);
+
+               if (_savedControlState == null || n >= _savedControlState.Length) 
+                       return;
+
+               for (Control parent = control.Parent; parent != null; parent = parent.Parent)
+                       if (parent.IsChildControlStateCleared)
+                               return;
+
+               object state = _savedControlState [n];
+               if (state != null)
+                       control.LoadControlState (state);
        }
        
        public bool RequiresControlState (Control control)
@@ -1787,13 +2479,14 @@ public class Page : TemplateControl, IHttpHandler
        
        void LoadPageControlState (object data)
        {
+               _savedControlState = (object []) data;
+               
                if (requireStateControls == null) return;
 
-               object[] state = (object[]) data;
-               int max = Math.Min (requireStateControls.Count, state != null ? state.Length : requireStateControls.Count);
+               int max = Math.Min (requireStateControls.Count, _savedControlState != null ? _savedControlState.Length : requireStateControls.Count);
                for (int n=0; n < max; n++) {
                        Control ctl = (Control) requireStateControls [n];
-                       ctl.LoadControlState (state != null ? state [n] : null);
+                       ctl.LoadControlState (_savedControlState != null ? _savedControlState [n] : null);
                }
        }
 
@@ -1804,11 +2497,8 @@ public class Page : TemplateControl, IHttpHandler
                        if (prevPage != null) {
                                previousPage = (Page) PageParser.GetCompiledPageInstance (prevPage, Server.MapPath (prevPage), Context);
                                previousPage.ProcessCrossPagePostBack (_context);
-                       } else {
-                               previousPage = _context.LastPage;
-                       }
+                       } 
                }
-               _context.LastPage = this;
        }
 
 
@@ -1857,8 +2547,6 @@ public class Page : TemplateControl, IHttpHandler
        protected internal override void OnInit (EventArgs e)
        {
                base.OnInit (e);
-               if (Header == null)
-                       return;
 
                ArrayList themes = new ArrayList();
 
@@ -1867,6 +2555,9 @@ public class Page : TemplateControl, IHttpHandler
                if (PageTheme != null && PageTheme.GetStyleSheets () != null)
                        themes.AddRange (PageTheme.GetStyleSheets ());
 
+               if (themes.Count > 0 && Header == null)
+                       throw new InvalidOperationException ("Using themed css files requires a header control on the page.");
+
                foreach (string lss in themes) {
                        HtmlLink hl = new HtmlLink ();
                        hl.Href = ResolveUrl (lss);
@@ -1879,18 +2570,18 @@ public class Page : TemplateControl, IHttpHandler
        #endif
 
 #if NET_2_0
-       [MonoTODO ("Used by .net aspx parser")]
+       [MonoTODO ("Not implemented.  Only used by .net aspx parser")]
        protected object GetWrappedFileDependencies (string [] list)
        {
-               return null;
+               return list;
        }
 
-       [MonoTODO ("Used by .net aspx parser")]
+       [MonoTODO ("Does nothing.  Used by .net aspx parser")]
        protected virtual void InitializeCulture ()
        {
        }
 
-       [MonoTODO ("Used by .net aspx parser")]
+       [MonoTODO ("Does nothing. Used by .net aspx parser")]
        protected internal void AddWrappedFileDependencies (object virtualFileDependencies)
        {
        }