// // System.Web.UI.Page.cs // // Authors: // Duncan Mak (duncan@ximian.com) // Gonzalo Paniagua (gonzalo@ximian.com) // Andreas Nahr (ClassDevelopment@A-SoftTech.com) // // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com) // using System; using System.Collections; using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; using System.IO; using System.Security.Principal; using System.Text; using System.Web; using System.Web.Caching; using System.Web.SessionState; using System.Web.Util; namespace System.Web.UI { // TODO FIXME missing the IRootDesigner Attribute [DefaultEvent ("Load"), DesignerCategory ("ASPXCodeBehind")] [ToolboxItem (false)] [Designer ("System.Web.UI.Design.ControlDesigner, " + Consts.AssemblySystem_Design, typeof (IDesigner))] [RootDesignerSerializer ("Microsoft.VSDesigner.WebForms.RootCodeDomSerializer, " + Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design, true)] public class Page : TemplateControl, IHttpHandler { private string _culture; private bool _viewState = true; private bool _viewStateMac = false; private string _errorPage; private string _ID; private bool _isValid; private bool _smartNavigation = false; private TraceContext _trace; private bool _traceEnabled; private TraceMode _traceModeValue; private int _transactionMode; private string _UICulture; private HttpContext _context; private ValidatorCollection _validators; private bool renderingForm; private object _savedViewState; private ArrayList _requiresPostBack; private ArrayList _requiresPostBackCopy; private ArrayList requiresPostDataChanged; private IPostBackEventHandler requiresRaiseEvent; private NameValueCollection secondPostData; private bool requiresPostBackScript = false; private bool postBackScriptRendered = false; Hashtable clientScriptBlocks; Hashtable startupScriptBlocks; Hashtable hiddenFields; internal Hashtable submitStatements; bool handleViewState; [EditorBrowsable (EditorBrowsableState.Never)] protected const string postEventArgumentID = "__EVENTARGUMENT"; [EditorBrowsable (EditorBrowsableState.Never)] protected const string postEventSourceID = "__EVENTTARGET"; #region Constructor public Page () { Page = this; } #endregion #region Properties [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public HttpApplicationState Application { get { return _context.Application; } } [EditorBrowsable (EditorBrowsableState.Never)] protected bool AspCompatMode { set { throw new NotImplementedException (); } } [EditorBrowsable (EditorBrowsableState.Never)] protected bool Buffer { set { Response.BufferOutput = value; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public Cache Cache { get { return _context.Cache; } } [MonoTODO] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false), DefaultValue ("")] [WebSysDescription ("Value do override the automatic browser detection and force the page to use the specified browser.")] public string ClientTarget { get { throw new NotImplementedException (); } set { throw new NotImplementedException (); } } [EditorBrowsable (EditorBrowsableState.Never)] protected int CodePage { set { Response.ContentEncoding = Encoding.GetEncoding (value); } } [EditorBrowsable (EditorBrowsableState.Never)] protected string ContentType { set { Response.ContentType = value; } } protected override HttpContext Context { get { return _context; } } [EditorBrowsable (EditorBrowsableState.Never)] protected string Culture { set { _culture = value; } } [Browsable (false)] public override bool EnableViewState { get { return _viewState; } set { _viewState = value; } } [EditorBrowsable (EditorBrowsableState.Never)] protected bool EnableViewStateMac { get { return _viewStateMac; } set { _viewStateMac = value; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false), DefaultValue ("")] [WebSysDescription ("The URL of a page used for error redirection.")] public string ErrorPage { get { return _errorPage; } set { _errorPage = value; } } [EditorBrowsable (EditorBrowsableState.Never)] protected ArrayList FileDependencies { set { if (Response != null) Response.AddFileDependencies (value); } } [Browsable (false)] public override string ID { get { return _ID; } set { _ID = value; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public bool IsPostBack { get { return (0 == String.Compare (Request.HttpMethod, "POST", true)); } } [EditorBrowsable (EditorBrowsableState.Never), Browsable (false)] public bool IsReusable { get { return false; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public bool IsValid { get { return _isValid; } } [MonoTODO] [EditorBrowsable (EditorBrowsableState.Never)] protected int LCID { set { throw new NotImplementedException (); } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public HttpRequest Request { get { return _context.Request; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public HttpResponse Response { get { return _context.Response; } } [EditorBrowsable (EditorBrowsableState.Never)] protected string ResponseEncoding { set { Response.ContentEncoding = Encoding.GetEncoding (value); } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public HttpServerUtility Server { get { return Context.Server; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public virtual HttpSessionState Session { get { return _context.Session; } } [Browsable (false)] public bool SmartNavigation { get { return _smartNavigation; } set { _smartNavigation = value; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public TraceContext Trace { get { return _trace; } } [EditorBrowsable (EditorBrowsableState.Never)] protected bool TraceEnabled { set { _traceEnabled = value; } } [EditorBrowsable (EditorBrowsableState.Never)] protected TraceMode TraceModeValue { set { _traceModeValue = value; } } [EditorBrowsable (EditorBrowsableState.Never)] protected int TransactionMode { set { _transactionMode = value; } } [EditorBrowsable (EditorBrowsableState.Never)] protected string UICulture { set { _UICulture = value; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public IPrincipal User { get { return _context.User; } } [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public ValidatorCollection Validators { get { if (_validators == null) _validators = new ValidatorCollection (); return _validators; } } [Browsable (false)] public override bool Visible { get { return base.Visible; } set { base.Visible = value; } } #endregion #region Methods [MonoTODO] [EditorBrowsable (EditorBrowsableState.Never)] protected IAsyncResult AspCompatBeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData) { throw new NotImplementedException (); } [MonoTODO] [EditorBrowsable (EditorBrowsableState.Never)] protected void AspCompatEndProcessRequest (IAsyncResult result) { throw new NotImplementedException (); } [EditorBrowsable (EditorBrowsableState.Advanced)] protected virtual HtmlTextWriter CreateHtmlTextWriter (TextWriter tw) { return new HtmlTextWriter (tw); } [MonoTODO] [EditorBrowsable (EditorBrowsableState.Never)] public void DesignerInitialize () { throw new NotImplementedException (); } [EditorBrowsable (EditorBrowsableState.Advanced)] protected virtual NameValueCollection DeterminePostBackMode () { if (_context == null) return null; HttpRequest req = _context.Request; if (req == null) return null; NameValueCollection coll = null; if (IsPostBack) coll = req.Form; else coll = req.QueryString; if (coll == null || coll ["__VIEWSTATE"] == null) return null; return coll; } [EditorBrowsable (EditorBrowsableState.Advanced)] public string GetPostBackClientEvent (Control control, string argument) { return GetPostBackEventReference (control, argument); } [EditorBrowsable (EditorBrowsableState.Advanced)] public string GetPostBackClientHyperlink (Control control, string argument) { return "javascript:" + GetPostBackEventReference (control, argument); } [EditorBrowsable (EditorBrowsableState.Advanced)] public string GetPostBackEventReference (Control control) { return GetPostBackEventReference (control, ""); } [EditorBrowsable (EditorBrowsableState.Advanced)] public string GetPostBackEventReference (Control control, string argument) { RequiresPostBackScript (); return String.Format ("__doPostBack('{0}','{1}')", control.UniqueID, argument); } internal void RequiresPostBackScript () { requiresPostBackScript = true; } [EditorBrowsable (EditorBrowsableState.Never)] public virtual int GetTypeHashCode () { return 0; } [MonoTODO] [EditorBrowsable (EditorBrowsableState.Never)] protected virtual void InitOutputCache (int duration, string varyByHeader, string varyByCustom, OutputCacheLocation location, string varyByParam) { HttpCachePolicy cache = _context.Response.Cache; switch (location) { case OutputCacheLocation.Any: cache.SetCacheability (HttpCacheability.Public); cache.SetMaxAge (new TimeSpan (0, 0, duration)); cache.SetLastModified (_context.Timestamp); goto case OutputCacheLocation.Server; case OutputCacheLocation.Client: cache.SetCacheability (HttpCacheability.Private); cache.SetMaxAge (new TimeSpan (0, 0, duration)); cache.SetLastModified (_context.Timestamp); break; case OutputCacheLocation.Downstream: cache.SetCacheability (HttpCacheability.Public); cache.SetMaxAge (new TimeSpan (0, 0, duration)); cache.SetLastModified (_context.Timestamp); break; case OutputCacheLocation.Server: if (varyByCustom != null) cache.SetVaryByCustom (varyByCustom); if (varyByParam.Length > 0) { string[] prms = varyByParam.Split (';'); foreach (string p in prms) cache.VaryByParams [p.Trim ()] = true; cache.VaryByParams.IgnoreParams = false; } else { cache.VaryByParams.IgnoreParams = true; } if (varyByHeader != null) { string[] hdrs = varyByHeader.Split (';'); foreach (string h in hdrs) cache.VaryByHeaders [h.Trim ()] = true; } _context.Response.CacheResponse (_context.Request); break; case OutputCacheLocation.None: break; } cache.SetExpires (_context.Timestamp.AddSeconds (duration)); } [EditorBrowsable (EditorBrowsableState.Advanced)] public bool IsClientScriptBlockRegistered (string key) { if (clientScriptBlocks == null) return false; return clientScriptBlocks.ContainsKey (key); } [EditorBrowsable (EditorBrowsableState.Advanced)] public bool IsStartupScriptRegistered (string key) { if (startupScriptBlocks == null) return false; return startupScriptBlocks.ContainsKey (key); } public string MapPath (string virtualPath) { return Request.MapPath (virtualPath); } private void RenderPostBackScript (HtmlTextWriter writer, string formUniqueID) { writer.WriteLine ("", postEventSourceID); writer.WriteLine ("", postEventArgumentID); writer.WriteLine (); writer.WriteLine (""); } static void WriteScripts (HtmlTextWriter writer, Hashtable scripts) { if (scripts == null) return; foreach (string key in scripts.Values) writer.WriteLine (key); } void WriteHiddenFields (HtmlTextWriter writer) { if (hiddenFields == null) return; foreach (string key in hiddenFields.Keys) { string value = hiddenFields [key] as string; writer.WriteLine ("\n", key, value); } hiddenFields = null; } internal void OnFormRender (HtmlTextWriter writer, string formUniqueID) { if (renderingForm) throw new HttpException ("Only 1 HtmlForm is allowed per page."); renderingForm = true; writer.WriteLine (); WriteHiddenFields (writer); if (requiresPostBackScript) { RenderPostBackScript (writer, formUniqueID); postBackScriptRendered = true; } if (handleViewState) { writer.Write ("", GetViewStateString ()); } WriteScripts (writer, clientScriptBlocks); } internal string GetViewStateString () { StringWriter sr = new StringWriter (); LosFormatter fmt = new LosFormatter (); fmt.Serialize (sr, _savedViewState); return sr.GetStringBuilder ().ToString (); } internal void OnFormPostRender (HtmlTextWriter writer, string formUniqueID) { if (!postBackScriptRendered && requiresPostBackScript) RenderPostBackScript (writer, formUniqueID); WriteHiddenFields (writer); WriteScripts (writer, startupScriptBlocks); renderingForm = false; postBackScriptRendered = false; } 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; 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; used.Add (real_id, real_id); 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.LoadPostData (real_id, data) == true) { if (requiresPostDataChanged == null) requiresPostDataChanged = new ArrayList (); requiresPostDataChanged.Add (pbdh); if (_requiresPostBackCopy != null) _requiresPostBackCopy.Remove (ctrl.UniqueID); } } else if (!second) { if (secondPostData == null) secondPostData = new NameValueCollection (); secondPostData.Add (real_id, data [id]); } } if (_requiresPostBackCopy != null && _requiresPostBackCopy.Count > 0) { string [] handlers = (string []) _requiresPostBackCopy.ToArray (typeof (string)); foreach (string id in handlers) { IPostBackDataHandler pbdh = FindControl (id) as IPostBackDataHandler; if (pbdh == null) continue; _requiresPostBackCopy.Remove (id); if (pbdh.LoadPostData (id, data)) { if (requiresPostDataChanged == null) requiresPostDataChanged = new ArrayList (); requiresPostDataChanged.Add (pbdh); } } } } [EditorBrowsable (EditorBrowsableState.Never)] public void ProcessRequest (HttpContext context) { _context = context; WebTrace.PushContext ("Page.ProcessRequest ()"); WebTrace.WriteLine ("Entering"); WireupAutomaticEvents (); WebTrace.WriteLine ("Finished hookup"); //-- Control execution lifecycle in the docs WebTrace.WriteLine ("FrameworkInitialize"); FrameworkInitialize (); WebTrace.WriteLine ("InitRecursive"); InitRecursive (null); renderingForm = false; if (IsPostBack) { LoadPageViewState (); ProcessPostData (DeterminePostBackMode (), false); } WebTrace.WriteLine ("LoadRecursive"); LoadRecursive (); if (IsPostBack) { ProcessPostData (secondPostData, true); RaiseChangedEvents (); RaisePostBackEvents (); } WebTrace.WriteLine ("PreRenderRecursiveInternal"); PreRenderRecursiveInternal (); WebTrace.WriteLine ("SavePageViewState"); SavePageViewState (); //-- HtmlTextWriter output = new HtmlTextWriter (context.Response.Output); WebTrace.WriteLine ("RenderControl"); RenderControl (output); _context = null; WebTrace.WriteLine ("UnloadRecursive"); UnloadRecursive (true); WebTrace.WriteLine ("End"); WebTrace.PopContext (); } internal void RaisePostBackEvents () { if (requiresRaiseEvent != null) { RaisePostBackEvent (requiresRaiseEvent, null); return; } NameValueCollection postdata = DeterminePostBackMode (); if (postdata == null) return; string eventTarget = postdata [postEventSourceID]; if (eventTarget == null || eventTarget.Length == 0) return; IPostBackEventHandler target = FindControl (eventTarget) as IPostBackEventHandler; if (target == null) return; string eventArgument = postdata [postEventArgumentID]; RaisePostBackEvent (target, eventArgument); } internal void RaiseChangedEvents () { if (requiresPostDataChanged == null) return; foreach (IPostBackDataHandler ipdh in requiresPostDataChanged) ipdh.RaisePostDataChangedEvent (); requiresPostDataChanged = null; } [EditorBrowsable (EditorBrowsableState.Advanced)] protected virtual void RaisePostBackEvent (IPostBackEventHandler sourceControl, string eventArgument) { sourceControl.RaisePostBackEvent (eventArgument); } [MonoTODO] [EditorBrowsable (EditorBrowsableState.Advanced)] public void RegisterArrayDeclaration (string arrayName, string arrayValue) { throw new NotImplementedException (); } [EditorBrowsable (EditorBrowsableState.Advanced)] public virtual void RegisterClientScriptBlock (string key, string script) { if (IsClientScriptBlockRegistered (key)) return; if (clientScriptBlocks == null) clientScriptBlocks = new Hashtable (); clientScriptBlocks.Add (key, script); } [EditorBrowsable (EditorBrowsableState.Advanced)] public virtual void RegisterHiddenField (string hiddenFieldName, string hiddenFieldInitialValue) { if (hiddenFields == null) hiddenFields = new Hashtable (); if (!hiddenFields.ContainsKey (hiddenFieldName)) hiddenFields.Add (hiddenFieldName, hiddenFieldInitialValue); } [MonoTODO] public void RegisterClientScriptFile (string a, string b, string c) { throw new NotImplementedException (); } [MonoTODO] [EditorBrowsable (EditorBrowsableState.Advanced)] public void RegisterOnSubmitStatement (string key, string script) { if (submitStatements == null) submitStatements = new Hashtable (); if (submitStatements.ContainsKey (key)) return; submitStatements.Add (key, script); } [EditorBrowsable (EditorBrowsableState.Advanced)] public void RegisterRequiresPostBack (Control control) { if (_requiresPostBack == null) _requiresPostBack = new ArrayList (); _requiresPostBack.Add (control.UniqueID); } [EditorBrowsable (EditorBrowsableState.Advanced)] public virtual void RegisterRequiresRaiseEvent (IPostBackEventHandler control) { requiresRaiseEvent = control; } [EditorBrowsable (EditorBrowsableState.Advanced)] public virtual void RegisterStartupScript (string key, string script) { if (IsStartupScriptRegistered (key)) return; if (startupScriptBlocks == null) startupScriptBlocks = new Hashtable (); startupScriptBlocks.Add (key, script); } [EditorBrowsable (EditorBrowsableState.Advanced)] public void RegisterViewStateHandler () { handleViewState = true; } [EditorBrowsable (EditorBrowsableState.Advanced)] protected virtual void SavePageStateToPersistenceMedium (object viewState) { _savedViewState = viewState; } [EditorBrowsable (EditorBrowsableState.Advanced)] protected virtual object LoadPageStateFromPersistenceMedium () { NameValueCollection postdata = DeterminePostBackMode (); string view_state; if (postdata == null || (view_state = postdata ["__VIEWSTATE"]) == null) return null; _savedViewState = null; LosFormatter fmt = new LosFormatter (); try { _savedViewState = fmt.Deserialize (view_state); } catch (Exception e) { throw new HttpException ("Error restoring page viewstate.\n", e); } return _savedViewState; } internal void LoadPageViewState() { WebTrace.PushContext ("LoadPageViewState"); object sState = LoadPageStateFromPersistenceMedium (); WebTrace.WriteLine ("sState = '{0}'", sState); if (sState != null) { Pair pair = (Pair) sState; LoadViewStateRecursive (pair.First); _requiresPostBack = pair.Second as ArrayList; } WebTrace.PopContext (); } internal void SavePageViewState () { if (!handleViewState) return; Pair pair = new Pair (); pair.First = SaveViewStateRecursive (); if (_requiresPostBack != null && _requiresPostBack.Count > 0) pair.Second = _requiresPostBack; if (pair.First == null && pair.Second == null) pair = null; SavePageStateToPersistenceMedium (pair); } public virtual void Validate () { if (_validators == null || _validators.Count == 0){ _isValid = true; return; } bool all_valid = true; foreach (IValidator v in _validators){ v.Validate (); if (v.IsValid == false) all_valid = false; } if (all_valid) _isValid = true; } [EditorBrowsable (EditorBrowsableState.Advanced)] public virtual void VerifyRenderingInServerForm (Control control) { if (!renderingForm) throw new HttpException ("Control '" + control.ClientID + " " + control.GetType () + "' must be rendered within a HtmlForm"); } #endregion #if NET_1_2 public string GetWebResourceUrl(Type type, string resourceName) { if (type == null) throw new ArgumentNullException ("type"); if (resourceName == null || resourceName.Length == 0) throw new ArgumentNullException ("type"); return System.Web.Handlers.AssemblyResourceLoader.GetResourceUrl (type, resourceName); } #endif } }