|
//------------------------------------------------------------------------------
// <copyright file="Page.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
// Uncomment out this line to display rare field statistics at the end of the page
//#define DISPLAYRAREFIELDSTATISTICS
/*
* Page class definition
*
* Copyright (c) 1998 Microsoft Corporation
*/
namespace System.Web.UI {
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;
using System.Configuration;
using System.EnterpriseServices;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Web.Caching;
using System.Web.Compilation;
using System.Web.Configuration;
using System.Web.Handlers;
using System.Web.Hosting;
using System.Web.Management;
using System.Web.RegularExpressions;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.UI.Adapters;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.Util;
using System.Xml;
using System.Web.Routing;
using System.Web.ModelBinding;
using System.Web.Security.Cryptography;
using System.Diagnostics.CodeAnalysis;
/// <devdoc>
/// Default ControlBuilder used to parse page files.
/// </devdoc>
public class FileLevelPageControlBuilder: RootBuilder {
private ArrayList _contentBuilderEntries;
private ControlBuilder _firstControlBuilder;
private int _firstLiteralLineNumber;
private bool _containsContentPage;
private string _firstLiteralText;
internal ICollection ContentBuilderEntries {
get {
return _contentBuilderEntries;
}
}
public override void AppendLiteralString(string text) {
if (_firstLiteralText == null) {
if (!Util.IsWhiteSpaceString(text)) {
int iFirstNonWhiteSpace = Util.FirstNonWhiteSpaceIndex(text);
if (iFirstNonWhiteSpace < 0) iFirstNonWhiteSpace = 0;
_firstLiteralLineNumber = Parser._lineNumber - Util.LineCount(text, iFirstNonWhiteSpace, text.Length);
_firstLiteralText = text;
if (_containsContentPage) {
throw new HttpException(SR.GetString(SR.Only_Content_supported_on_content_page));
}
}
}
base.AppendLiteralString(text);
}
public override void AppendSubBuilder(ControlBuilder subBuilder) {
// Tell the sub builder that it's about to be appended to its parent
if (subBuilder is ContentBuilderInternal) {
ContentBuilderInternal contentBuilder = (ContentBuilderInternal)subBuilder;
_containsContentPage = true;
if (_contentBuilderEntries == null) {
_contentBuilderEntries = new ArrayList();
}
if (_firstLiteralText != null) {
throw new HttpParseException(SR.GetString(SR.Only_Content_supported_on_content_page),
null, Parser.CurrentVirtualPath, _firstLiteralText, _firstLiteralLineNumber);
}
if (_firstControlBuilder != null) {
Parser._lineNumber = _firstControlBuilder.Line;
throw new HttpException(SR.GetString(SR.Only_Content_supported_on_content_page));
}
TemplatePropertyEntry entry = new TemplatePropertyEntry();
entry.Filter = contentBuilder.ContentPlaceHolderFilter;
entry.Name = contentBuilder.ContentPlaceHolder;
entry.Builder = contentBuilder;
_contentBuilderEntries.Add(entry);
}
else {
if (_firstControlBuilder == null) {
if (_containsContentPage) {
throw new HttpException(SR.GetString(SR.Only_Content_supported_on_content_page));
}
_firstControlBuilder = subBuilder;
}
}
base.AppendSubBuilder(subBuilder);
}
internal override void InitObject(object obj) {
base.InitObject(obj);
if (_contentBuilderEntries == null)
return;
ICollection entries = GetFilteredPropertyEntrySet(_contentBuilderEntries);
foreach(TemplatePropertyEntry entry in entries) {
ContentBuilderInternal contentBuilder = (ContentBuilderInternal)entry.Builder;
try {
contentBuilder.SetServiceProvider(ServiceProvider);
// Note that 'obj' can be either a Page or a MasterPage,
// hence the need for this virtual method.
AddContentTemplate(obj, contentBuilder.ContentPlaceHolder, contentBuilder.BuildObject() as ITemplate);
}
finally {
contentBuilder.SetServiceProvider(null);
}
}
}
internal virtual void AddContentTemplate(object obj, string templateName, ITemplate template) {
Page page = (Page)obj;
page.AddContentTemplate(templateName, template);
}
internal override void SortEntries() {
base.SortEntries();
FilteredPropertyEntryComparer comparer = null;
ProcessAndSortPropertyEntries(_contentBuilderEntries, ref comparer);
}
}
/// <devdoc>
/// <para>
/// Defines the properties, methods, and events common to
/// all pages that are processed on the server by the Web Forms page framework.
/// <see langword='Page '/>
/// objects are compiled and cached in
/// memory when any ASP.NET page is
/// requested.</para>
/// <para>This class is not marked as abstract, because the VS designer
/// needs to instantiate it when opening .ascx files</para>
/// </devdoc>
[
DefaultEvent("Load"),
Designer("Microsoft.VisualStudio.Web.WebForms.WebFormDesigner, " + AssemblyRef.MicrosoftVisualStudioWeb, typeof(IRootDesigner)),
DesignerCategory("ASPXCodeBehind"),
DesignerSerializer("Microsoft.VisualStudio.Web.WebForms.WebFormCodeDomSerializer, " + AssemblyRef.MicrosoftVisualStudioWeb, "System.ComponentModel.Design.Serialization.TypeCodeDomSerializer, " + AssemblyRef.SystemDesign),
ToolboxItem(false)
]
public class Page: TemplateControl, IHttpHandler {
private const string HiddenClassName = "aspNetHidden";
private const string PageID = "__Page";
private const string PageScrollPositionScriptKey = "PageScrollPositionScript";
private const string PageSubmitScriptKey = "PageSubmitScript";
private const string PageReEnableControlsScriptKey = "PageReEnableControlsScript";
// NOTE: Make sure this stays in sync with MobilePage.PageRegisteredControlsThatRequirePostBackKey
//
private const string PageRegisteredControlsThatRequirePostBackKey = "__ControlsRequirePostBackKey__";
private const string EnabledControlArray = "__enabledControlArray";
//used by TemplateControl to hookup auto-events
internal static readonly object EventPreRenderComplete = new Object();
internal static readonly object EventPreLoad = new object();
internal static readonly object EventLoadComplete = new object();
internal static readonly object EventPreInit = new object();
internal static readonly object EventInitComplete = new object();
internal static readonly object EventSaveStateComplete = new object();
private static readonly Version FocusMinimumEcmaVersion = new Version("1.4");
private static readonly Version FocusMinimumJScriptVersion = new Version("3.0");
private static readonly Version JavascriptMinimumVersion = new Version("1.0");
private static readonly Version MSDomScrollMinimumVersion = new Version("4.0");
// Review: this is consistent with MMIT legacy -do we prefer two underscores?
private static readonly string UniqueFilePathSuffixID = "__ufps";
private string _uniqueFilePathSuffix;
internal static readonly int DefaultMaxPageStateFieldLength = -1;
internal static readonly int DefaultAsyncTimeoutSeconds = 45;
private int _maxPageStateFieldLength = DefaultMaxPageStateFieldLength;
private string _requestViewState;
private bool _cachedRequestViewState;
private PageAdapter _pageAdapter;
// Has the page layout changed since last request
private bool _fPageLayoutChanged;
private bool _haveIdSeparator;
private char _idSeparator;
// Session state
private bool _sessionRetrieved;
private HttpSessionState _session;
private int _transactionMode; /* 0 = TransactionOption.Disabled*/
private bool _aspCompatMode;
private bool _asyncMode;
// Async related
private static readonly TimeSpan _maxAsyncTimeout = TimeSpan.FromMilliseconds(Int32.MaxValue);
private TimeSpan _asyncTimeout;
private bool _asyncTimeoutSet;
private PageAsyncTaskManager _asyncTaskManager;
private LegacyPageAsyncTaskManager _legacyAsyncTaskManager;
private LegacyPageAsyncInfo _legacyAsyncInfo;
// Page culture and uiculture set dynamically
private CultureInfo _dynamicCulture;
private CultureInfo _dynamicUICulture;
// ViewState
private string _clientState;
private PageStatePersister _persister;
internal ControlSet _registeredControlsRequiringControlState;
private StringSet _controlStateLoadedControlIds;
internal HybridDictionary _registeredControlsRequiringClearChildControlState;
internal const ViewStateEncryptionMode EncryptionModeDefault = ViewStateEncryptionMode.Auto;
private ViewStateEncryptionMode _encryptionMode = EncryptionModeDefault;
private bool _viewStateEncryptionRequested;
private ArrayList _enabledControls;
// Http Intrinsics
internal HttpRequest _request;
internal HttpResponse _response;
internal HttpApplicationState _application;
internal Cache _cache;
internal string _errorPage;
private string _clientTarget;
// Form related fields
private HtmlForm _form;
private bool _inOnFormRender;
private bool _fOnFormRenderCalled;
private bool _fRequireWebFormsScript;
private bool _fWebFormsScriptRendered;
private bool _fRequirePostBackScript;
private bool _fPostBackScriptRendered;
private bool _containsCrossPagePost;
private RenderMethod _postFormRenderDelegate;
internal Dictionary<String, String> _hiddenFieldsToRender;
private bool _requireFocusScript;
private bool _profileTreeBuilt;
internal const bool MaintainScrollPositionOnPostBackDefault = false;
private bool _maintainScrollPosition = MaintainScrollPositionOnPostBackDefault;
private ClientScriptManager _clientScriptManager;
// Needed to support Validators in AJAX 1.0 (Windows OS Bugs 2015831)
private static Type _scriptManagerType;
internal const bool EnableViewStateMacDefault = true;
internal const bool EnableEventValidationDefault = true;
internal const string systemPostFieldPrefix = "__";
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
public const string postEventSourceID = systemPostFieldPrefix + "EVENTTARGET";
private const string lastFocusID = systemPostFieldPrefix + "LASTFOCUS";
private const string _scrollPositionXID = systemPostFieldPrefix + "SCROLLPOSITIONX";
private const string _scrollPositionYID = systemPostFieldPrefix + "SCROLLPOSITIONY";
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
public const string postEventArgumentID = systemPostFieldPrefix + "EVENTARGUMENT";
internal const string ViewStateFieldPrefixID = systemPostFieldPrefix + "VIEWSTATE";
internal const string ViewStateFieldCountID = ViewStateFieldPrefixID + "FIELDCOUNT";
internal const string ViewStateGeneratorFieldID = ViewStateFieldPrefixID + "GENERATOR";
internal const string ViewStateEncryptionID = systemPostFieldPrefix + "VIEWSTATEENCRYPTED";
internal const string EventValidationPrefixID = systemPostFieldPrefix + "EVENTVALIDATION";
// Any change in this constant must be duplicated in DetermineIsExportingWebPart
internal const string WebPartExportID = systemPostFieldPrefix + "WEBPARTEXPORT";
private bool _requireScrollScript;
private bool _isCallback;
private bool _isCrossPagePostBack;
private bool _containsEncryptedViewState;
private bool _enableEventValidation = EnableEventValidationDefault;
internal const string callbackID = systemPostFieldPrefix + "CALLBACKID";
internal const string callbackParameterID = systemPostFieldPrefix + "CALLBACKPARAM";
internal const string callbackLoadScriptID = systemPostFieldPrefix + "CALLBACKLOADSCRIPT";
internal const string callbackIndexID = systemPostFieldPrefix + "CALLBACKINDEX";
internal const string previousPageID = systemPostFieldPrefix + "PREVIOUSPAGE";
// BasePartialCachingControl's currently on the stack
private Stack _partialCachingControlStack;
private ArrayList _controlsRequiringPostBack;
private ArrayList _registeredControlsThatRequirePostBack;
private NameValueCollection _leftoverPostData;
private IPostBackEventHandler _registeredControlThatRequireRaiseEvent;
private ArrayList _changedPostDataConsumers;
private bool _needToPersistViewState;
private bool _enableViewStateMac;
private string _viewStateUserKey;
private string _themeName;
private PageTheme _theme;
private string _styleSheetName;
private PageTheme _styleSheet;
private VirtualPath _masterPageFile;
private MasterPage _master;
private IDictionary _contentTemplateCollection;
private SmartNavigationSupport _smartNavSupport;
internal HttpContext _context;
private ValidatorCollection _validators;
private bool _validated;
private HtmlHead _header;
private int _supportsStyleSheets;
private Control _autoPostBackControl;
private string _focusedControlID;
private Control _focusedControl;
private string _validatorInvalidControl;
private int _scrollPositionX;
private int _scrollPositionY;
private Page _previousPage;
private VirtualPath _previousPagePath;
private bool _preInitWorkComplete;
private bool _clientSupportsJavaScriptChecked;
private bool _clientSupportsJavaScript;
private string _titleToBeSet;
private string _descriptionToBeSet;
private string _keywordsToBeSet;
private ICallbackEventHandler _callbackControl;
// DevDiv 33149, 43258: A backward compat. switch for Everett rendering,
private bool _xhtmlConformanceModeSet;
private XhtmlConformanceMode _xhtmlConformanceMode;
// const masks into the BitVector32
private const int styleSheetInitialized = 0x00000001;
private const int isExportingWebPart = 0x00000002;
private const int isExportingWebPartShared = 0x00000004;
private const int isCrossPagePostRequest = 0x00000008;
// Needed to support Validators in AJAX 1.0 (Windows OS Bugs 2015831)
private const int isPartialRenderingSupported = 0x00000010;
private const int isPartialRenderingSupportedSet = 0x00000020;
private const int skipFormActionValidation = 0x00000040;
private const int wasViewStateMacErrorSuppressed = 0x00000080;
// Todo: Move boolean fields into _pageFlags.
#pragma warning disable 0649
private SimpleBitVector32 _pageFlags;
#pragma warning restore 0649
// Can be either Context.Request.Form or Context.Request.QueryString
// depending on the method used.
private NameValueCollection _requestValueCollection;
// The unvalidated version of _requestValueCollection
private NameValueCollection _unvalidatedRequestValueCollection;
private ModelStateDictionary _modelState;
private ModelBindingExecutionContext _modelBindingExecutionContext;
private UnobtrusiveValidationMode? _unobtrusiveValidationMode;
private bool _executingAsyncTasks = false;
private static StringSet s_systemPostFields;
static Page() {
// Create a static hashtable with all the names that should be
// ignored in ProcessPostData().
s_systemPostFields = new StringSet();
s_systemPostFields.Add(postEventSourceID);
s_systemPostFields.Add(postEventArgumentID);
s_systemPostFields.Add(ViewStateFieldCountID);
s_systemPostFields.Add(ViewStateGeneratorFieldID);
s_systemPostFields.Add(ViewStateFieldPrefixID);
s_systemPostFields.Add(ViewStateEncryptionID);
s_systemPostFields.Add(previousPageID);
s_systemPostFields.Add(callbackID);
s_systemPostFields.Add(callbackParameterID);
s_systemPostFields.Add(lastFocusID);
s_systemPostFields.Add(UniqueFilePathSuffixID);
s_systemPostFields.Add(HttpResponse.RedirectQueryStringVariable);
s_systemPostFields.Add(EventValidationPrefixID);
}
/// <devdoc>
/// <para>Initializes a new instance of the <see cref='System.Web.UI.Page'/> class.</para>
/// </devdoc>
public Page() {
_page = this; // Set the page to ourselves
_enableViewStateMac = EnableViewStateMacDefault;
// Ensure that the page has an ID, for things like trace
ID = PageID;
_supportsStyleSheets = -1;
// Set the default ValidateRequestMode of a page to Enabled since the value Inherit
// does not make sense as the page has nobody to inherit from.
// Also, since this is the default value for Page, we do not want this value to be
// stored in ViewState , so we set the value here but do not set the property changed
// flag so that it's not stored in ViewState by default.
SetValidateRequestModeInternal(ValidateRequestMode.Enabled, setDirty: false);
}
public ModelStateDictionary ModelState {
get {
if (_modelState == null) {
_modelState = new ModelStateDictionary();
}
return _modelState;
}
}
private IValueProvider ActiveValueProvider {
get;
set;
}
internal bool IsExecutingAsyncTasks {
get {
return _executingAsyncTasks;
}
set {
_executingAsyncTasks = value;
}
}
public ModelBindingExecutionContext ModelBindingExecutionContext {
get {
if (_modelBindingExecutionContext == null) {
_modelBindingExecutionContext = new ModelBindingExecutionContext(new HttpContextWrapper(Context), this.ModelState);
//This is used to query the ViewState in ViewStateValueProvider later.
_modelBindingExecutionContext.PublishService<StateBag>(ViewState);
//This is used to query RouteData in RouteDataValueProvider later.
_modelBindingExecutionContext.PublishService<RouteData>(RouteData);
}
return _modelBindingExecutionContext;
}
}
/// <summary>
/// We support calling TryUpdateModel only within a Data Method of DataBoundControl.
/// So this method provides a way to enfore that.
/// This sets the active value provider which is used to provide the values for
/// TryUpdateModel. This method should be called before calling TryUpdateModel otherwise the latter
/// would throw. Also it's callers responsibility to reset the active value Provider by calling this
/// method again with null values. (Currently this is all done by ModelDataSourceView).
/// </summary>
internal void SetActiveValueProvider(IValueProvider valueProvider) {
ActiveValueProvider = valueProvider;
}
/// <summary>
/// Attempts to update the model object from the values within a databound control. This
/// must be invoked within the Select/Update/Delete/InsertMethods used for data binding.
/// </summary>
/// <returns>True if the model object is updated succesfully with valid values. False otherwise.</returns>
public virtual bool TryUpdateModel<TModel>(TModel model) where TModel : class {
if (ActiveValueProvider == null) {
throw new InvalidOperationException(SR.GetString(SR.Page_InvalidUpdateModelAttempt, "TryUpdateModel"));
}
return TryUpdateModel<TModel>(model, ActiveValueProvider);
}
/// <summary>
/// Attempts to update the model object from the values provided by given valueProvider.
/// </summary>
/// <returns>True if the model object is updated succesfully with valid values. False otherwise.</returns>
public virtual bool TryUpdateModel<TModel>(TModel model, IValueProvider valueProvider) where TModel : class {
if (model == null) {
throw new ArgumentNullException("model");
}
if (valueProvider == null) {
throw new ArgumentNullException("valueProvider");
}
IModelBinder binder = ModelBinders.Binders.DefaultBinder;
ModelBindingContext bindingContext = new ModelBindingContext() {
ModelBinderProviders = ModelBinderProviders.Providers,
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(TModel)),
ModelState = ModelState,
ValueProvider = valueProvider
};
if (binder.BindModel(ModelBindingExecutionContext, bindingContext)) {
return ModelState.IsValid;
}
//ModelBinding failed!!!
return false;
}
/// <summary>
/// Updates the model object from the values within a databound control. This must be invoked
/// within the Select/Update/Delete/InsertMethods used for data binding.
/// Throws an exception if the update fails.
/// </summary>
public virtual void UpdateModel<TModel>(TModel model) where TModel : class {
if (ActiveValueProvider == null) {
throw new InvalidOperationException(SR.GetString(SR.Page_InvalidUpdateModelAttempt, "UpdateModel"));
}
UpdateModel<TModel>(model, ActiveValueProvider);
}
/// <summary>
/// Updates the model object from the values provided by given valueProvider.
/// Throws an exception if the update fails.
/// </summary>
public virtual void UpdateModel<TModel>(TModel model, IValueProvider valueProvider) where TModel : class {
if (!TryUpdateModel(model, valueProvider)) {
throw new InvalidOperationException(SR.GetString(SR.Page_UpdateModel_UpdateUnsuccessful, typeof(TModel).FullName));
}
}
[
DefaultValue(UnobtrusiveValidationMode.None),
WebCategory("Behavior"),
WebSysDescription(SR.Page_UnobtrusiveValidationMode)
]
public UnobtrusiveValidationMode UnobtrusiveValidationMode {
get {
return _unobtrusiveValidationMode ?? ValidationSettings.UnobtrusiveValidationMode;
}
set {
if (value < UnobtrusiveValidationMode.None || value > UnobtrusiveValidationMode.WebForms) {
throw new ArgumentOutOfRangeException("value");
}
_unobtrusiveValidationMode = value;
}
}
/// <devdoc>
/// <para>Gets the <see langword='Application'/> object provided by the HTTP Runtime.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public HttpApplicationState Application {
get {
return _application;
}
}
/// <devdoc>
/// <para>Gets the HttpContext for the Page.</para>
/// </devdoc>
protected internal override HttpContext Context {
get {
if (_context == null) {
_context = HttpContext.Current;
}
return _context;
}
}
// Set of unique control ids which have already loaded control state
private StringSet ControlStateLoadedControlIds {
get {
if (_controlStateLoadedControlIds == null) {
_controlStateLoadedControlIds = new StringSet();
}
return _controlStateLoadedControlIds;
}
}
/// <devdoc>
/// The value to be written to the __VIEWSTATE hidden fields. Getter is exposed through a protected property in
/// PageAdapter.
/// </devdoc>
internal string ClientState {
get {
return _clientState;
}
set {
_clientState = value;
}
}
/*
* Any onsubmit statment to hook up by the form. The HtmlForm object calls this
* during RenderAttributes.
*/
internal string ClientOnSubmitEvent {
get {
if (ClientScript.HasSubmitStatements ||
(Form != null && Form.SubmitDisabledControls && (EnabledControls.Count > 0))) {
// to avoid being affected by earlier instructions we must
// write out the language as well
return "javascript:return WebForm_OnSubmit();";
}
return string.Empty;
}
}
public ClientScriptManager ClientScript {
get {
if (_clientScriptManager == null) {
_clientScriptManager = new ClientScriptManager(this);
}
return _clientScriptManager;
}
}
/// <devdoc>
/// <para>Indicates whether the requesting browser is uplevel or downlevel so that the appropriate behavior can be
/// generated for the request.</para>
/// </devdoc>
[
DefaultValue(""),
WebSysDescription(SR.Page_ClientTarget),
Browsable(false),
EditorBrowsable(EditorBrowsableState.Advanced),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string ClientTarget {
get {
return (_clientTarget == null) ? String.Empty : _clientTarget;
}
set {
_clientTarget = value;
if (_request != null) {
_request.ClientTarget = value;
}
}
}
private string _clientQueryString = null;
public String ClientQueryString {
get {
if (_clientQueryString == null) {
if (RequestInternal != null && Request.HasQueryString) {
// Eliminate system post fields (generated by the framework) from the
// querystring used for adaptive rendering.
Hashtable ht = new Hashtable();
foreach (string systemPostField in s_systemPostFields) {
ht.Add(systemPostField, true);
}
//
HttpValueCollection httpValueCollection = (HttpValueCollection)((SkipFormActionValidation) ? Request.Unvalidated.QueryString : Request.QueryString);
_clientQueryString = httpValueCollection.ToString(urlencoded: true, excludeKeys: ht);
}
else {
_clientQueryString = String.Empty;
}
}
return _clientQueryString;
}
}
internal bool ContainsEncryptedViewState {
get {
return _containsEncryptedViewState;
}
set {
_containsEncryptedViewState = value;
}
}
/// <devdoc>
/// <para>
/// Gets or sets the error page to which the requesting browser should be
/// redirected in the event of an unhandled page exception.
/// </para>
/// </devdoc>
[
DefaultValue(""),
WebSysDescription(SR.Page_ErrorPage),
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string ErrorPage {
get {
return _errorPage;
}
set {
_errorPage = value;
}
}
/// <devdoc>
/// Gets a value indicating whether the page is being loaded in response to a client callback.
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public bool IsCallback {
get {
return _isCallback;
}
}
/// <internalonly/>
/// <devdoc>Page class can be cached/reused</devdoc>
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never)
]
public bool IsReusable {
get { return false; }
}
/// <devdoc>
/// Required for small browsers that cache too aggressively.
/// </devdoc>
protected internal virtual String UniqueFilePathSuffix {
get {
if (_uniqueFilePathSuffix != null) {
return _uniqueFilePathSuffix;
}
// Only need a few digits, so save space by modulo'ing by a prime.
// The chosen prime is the highest of six digits.
long ticks = DateTime.Now.Ticks % 999983;
_uniqueFilePathSuffix = String.Concat(UniqueFilePathSuffixID + "=", ticks.ToString("D6", CultureInfo.InvariantCulture));
_uniqueFilePathSuffix = _uniqueFilePathSuffix.PadLeft(6, '0');
return _uniqueFilePathSuffix;
}
}
// This property should be public. (DevDiv Bugs 161340)
public Control AutoPostBackControl {
get {
return _autoPostBackControl;
}
set {
_autoPostBackControl = value;
}
}
internal bool ClientSupportsFocus {
get {
return (_request != null) &&
((_request.Browser.EcmaScriptVersion >= FocusMinimumEcmaVersion) || (_request.Browser.JScriptVersion >= FocusMinimumJScriptVersion));
}
}
internal bool ClientSupportsJavaScript {
get {
if (!_clientSupportsJavaScriptChecked) {
_clientSupportsJavaScript = (_request != null) &&
(_request.Browser.EcmaScriptVersion >= JavascriptMinimumVersion);
_clientSupportsJavaScriptChecked = true;
}
return _clientSupportsJavaScript;
}
}
private ArrayList EnabledControls {
get {
if (_enabledControls == null) {
_enabledControls = new ArrayList();
}
return _enabledControls;
}
}
internal string FocusedControlID {
get {
if (_focusedControlID == null) {
return String.Empty;
}
return _focusedControlID;
}
}
/// <devdoc>
/// The control that has been set to be focused (empty if there was no such control)
/// </devdoc>
internal Control FocusedControl {
get {
return _focusedControl;
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public HtmlHead Header {
get {
return _header;
}
}
/// <internalonly/>
/// <devdoc>
/// VSWhidbey 80467: Need to adapt Id separator.
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Never)
]
public new virtual char IdSeparator {
get {
if (!_haveIdSeparator) {
if (AdapterInternal != null) {
_idSeparator = PageAdapter.IdSeparator;
}
else {
_idSeparator = IdSeparatorFromConfig;
}
_haveIdSeparator = true;
}
return _idSeparator;
}
}
/// <devdoc>
/// The control that has was last focused (empty if there was no such control)
/// </devdoc>
// We
internal string LastFocusedControl {
[AspNetHostingPermission(SecurityAction.Assert, Level = AspNetHostingPermissionLevel.Low)]
get {
if (RequestInternal != null) {
// SECURITY: Change this to just check form + query string
string lastFocus = Request[lastFocusID];
if (lastFocus != null) {
return lastFocus;
}
}
return String.Empty;
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public bool MaintainScrollPositionOnPostBack {
get {
if (RequestInternal != null && RequestInternal.Browser != null && !RequestInternal.Browser.SupportsMaintainScrollPositionOnPostback)
return false;
return _maintainScrollPosition;
}
set {
if (_maintainScrollPosition != value) {
_maintainScrollPosition = value;
if (_maintainScrollPosition) LoadScrollPosition();
}
}
}
/// <devdoc>
/// <para>The MasterPage used by the Page.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
WebSysDescription(SR.MasterPage_MasterPage)
]
public MasterPage Master {
get {
if (_master == null && !_preInitWorkComplete) {
_master = MasterPage.CreateMaster(this, Context, _masterPageFile, _contentTemplateCollection);
}
return _master;
}
}
/// <devdoc>
/// <para>Gets and sets the masterPageFile of this Page.</para>
/// </devdoc>
[
DefaultValue(""),
WebCategory("Behavior"),
WebSysDescription(SR.MasterPage_MasterPageFile)
]
public virtual string MasterPageFile {
get {
return VirtualPath.GetVirtualPathString(_masterPageFile);
}
set {
if (_preInitWorkComplete) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforePageEvent, "MasterPageFile", "Page_PreInit"));
}
if (value != VirtualPath.GetVirtualPathString(_masterPageFile)) {
_masterPageFile = VirtualPath.CreateAllowNull(value);
if (_master != null && Controls.Contains(_master)) {
Controls.Remove(_master);
}
_master = null;
}
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Never)
]
public int MaxPageStateFieldLength {
get {
return _maxPageStateFieldLength;
}
set {
if (this.ControlState > ControlState.FrameworkInitialized) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetAfterFrameworkInitialize, "MaxPageStateFieldLength"));
}
if (value == 0 || value < -1) {
throw new ArgumentException(SR.GetString(SR.Page_Illegal_MaxPageStateFieldLength), "MaxPageStateFieldLength");
}
_maxPageStateFieldLength = value;
}
}
/// <devdoc>
/// Indicates whether page requires cross post script
/// </devdoc>
internal bool ContainsCrossPagePost {
get {
return _containsCrossPagePost;
}
set {
_containsCrossPagePost = value;
}
}
/// <devdoc>
/// True if the form should render a reference to the focus script.
/// </devdoc>
internal bool RenderFocusScript {
get {
return _requireFocusScript;
}
}
internal Stack PartialCachingControlStack {
get {
return _partialCachingControlStack;
}
}
/// <devdoc>
/// Returns the page state persister associated with the page.
/// </devdoc>
protected virtual PageStatePersister PageStatePersister {
get {
if (_persister == null) {
PageAdapter adapter = PageAdapter;
if (adapter != null) {
_persister = adapter.GetStatePersister();
}
if (_persister == null) {
_persister = new HiddenFieldPageStatePersister(this);
}
}
return _persister;
}
}
// Reconstructs the view state string from the view state fields in the request
internal string RequestViewStateString {
get {
if (!_cachedRequestViewState) {
StringBuilder state = new StringBuilder();
try {
NameValueCollection requestValueCollection = RequestValueCollection;
if (requestValueCollection != null) {
// If ViewStateChunking is disabled(-1) or there is no ViewStateFieldCount, return the __VIEWSTATE field
string fieldCountStr = RequestValueCollection[ViewStateFieldCountID];
if (MaxPageStateFieldLength == -1 || fieldCountStr == null) {
_cachedRequestViewState = true;
_requestViewState = RequestValueCollection[ViewStateFieldPrefixID];
return _requestViewState;
}
// Build up the entire persisted state from all the viewstate fields
int numViewStateFields = Convert.ToInt32(fieldCountStr, CultureInfo.InvariantCulture);
if (numViewStateFields < 0) {
throw new HttpException(SR.GetString(SR.ViewState_InvalidViewState));
}
// The view state is split into __VIEWSTATE, __VIEWSTATE1, __VIEWSTATE2, ... fields
for (int i=0; i<numViewStateFields; ++i) {
string key = ViewStateFieldPrefixID;
// For backwards compat we always need the first chunk to be __VIEWSTATE
if (i > 0) key += i.ToString(CultureInfo.InvariantCulture);
string viewStateChunk = RequestValueCollection[key];
if (viewStateChunk == null) {
throw new HttpException(SR.GetString(SR.ViewState_MissingViewStateField, key));
}
state.Append(viewStateChunk);
}
}
_cachedRequestViewState = true;
_requestViewState = state.ToString();
} catch (Exception e) {
ViewStateException.ThrowViewStateError(e, state.ToString());
}
}
return _requestViewState;
}
}
internal string ValidatorInvalidControl {
get {
if (_validatorInvalidControl == null) {
return String.Empty;
}
return _validatorInvalidControl;
}
}
/// <devdoc>
/// <para>Gets the <see cref='System.Web.TraceContext'/> object for the current Web
/// request. Tracing tracks and presents the execution details about a Web request. </para>
/// For trace data to be visible in a rendered page, you must
/// turn tracing on for that page.
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public TraceContext Trace {
get {
return Context.Trace;
}
}
/// <devdoc>
/// <para>Gets the <see langword='Request'/> object provided by the HTTP Runtime, which
/// allows you to access data from incoming HTTP requests.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public HttpRequest Request {
get {
if (_request == null)
throw new HttpException(SR.GetString(SR.Request_not_available));
return _request;
}
}
internal HttpRequest RequestInternal {
get {
return _request;
}
}
/// <devdoc>
/// <para>Gets the <see langword='Response '/>object provided by the HTTP Runtime, which
/// allows you to send HTTP response data to a client browser.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public HttpResponse Response {
get {
if (_response == null)
throw new HttpException(SR.GetString(SR.Response_not_available));
return _response;
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public RouteData RouteData {
get {
if (Context != null && Context.Request != null) {
// RequestContext is created on demand if not set so it should never be null
return Context.Request.RequestContext.RouteData;
}
return null;
}
}
/// <devdoc>
/// <para>Gets the <see langword='Server'/> object supplied by the HTTP runtime.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public HttpServerUtility Server {
get { return Context.Server;}
}
/// <devdoc>
/// <para>Retrieves a <see langword='Cache'/> object in which to store the page for
/// subsequent requests. This property is read-only.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public Cache Cache {
get {
if (_cache == null)
throw new HttpException(SR.GetString(SR.Cache_not_available));
return _cache;
}
}
/// <devdoc>
/// <para>Gets the <see langword='Session'/>
/// object provided by the HTTP Runtime. This object provides information about the current request's session.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public virtual HttpSessionState Session {
get {
if (!_sessionRetrieved) {
/* try just once to retrieve it */
_sessionRetrieved = true;
try {
_session = Context.Session;
}
catch {
// Just ignore exceptions, return null.
}
}
if (_session == null) {
throw new HttpException(SR.GetString(SR.Session_not_enabled));
}
return _session;
}
}
[
Bindable(true),
Localizable(true),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string Title {
get {
if ((Page.Header == null) && (this.ControlState >= ControlState.ChildrenInitialized)) {
throw new InvalidOperationException(SR.GetString(SR.Page_Title_Requires_Head));
}
if (_titleToBeSet != null) {
return _titleToBeSet;
}
return Page.Header.Title;
}
set {
if (Page.Header == null) {
if (this.ControlState >= ControlState.ChildrenInitialized) {
throw new InvalidOperationException(SR.GetString(SR.Page_Title_Requires_Head));
}
else {
_titleToBeSet = value;
}
}
else {
Page.Header.Title = value;
}
}
}
[
Bindable(true),
Localizable(true),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string MetaDescription {
get {
if ((Page.Header == null) && (this.ControlState >= ControlState.ChildrenInitialized)) {
throw new InvalidOperationException(SR.GetString(SR.Page_Description_Requires_Head));
}
if (_descriptionToBeSet != null) {
return _descriptionToBeSet;
}
return Page.Header.Description;
}
set {
if (Page.Header == null) {
if (this.ControlState >= ControlState.ChildrenInitialized) {
throw new InvalidOperationException(SR.GetString(SR.Page_Description_Requires_Head));
}
else {
_descriptionToBeSet = value;
}
}
else {
Page.Header.Description = value;
}
}
}
[
Bindable(true),
Localizable(true),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public string MetaKeywords {
get {
if ((Page.Header == null) && (this.ControlState >= ControlState.ChildrenInitialized)) {
throw new InvalidOperationException(SR.GetString(SR.Page_Keywords_Requires_Head));
}
if (_keywordsToBeSet != null) {
return _keywordsToBeSet;
}
return Page.Header.Keywords;
}
set {
if (Page.Header == null) {
if (this.ControlState >= ControlState.ChildrenInitialized) {
throw new InvalidOperationException(SR.GetString(SR.Page_Keywords_Requires_Head));
}
else {
_keywordsToBeSet = value;
}
}
else {
Page.Header.Keywords = value;
}
}
}
/// <devdoc>
/// indicates whether the Page has PageTheme defined.
/// </devdoc>
internal bool ContainsTheme {
get {
Debug.Assert(_preInitWorkComplete || DesignMode, "ContainsTheme should not be accessed before Page's PreInit.");
return _theme != null;
}
}
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public virtual String Theme {
get {
return _themeName;
}
set {
if (_preInitWorkComplete) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetBeforePageEvent, "Theme", "Page_PreInit"));
}
if (!String.IsNullOrEmpty(value) && !FileUtil.IsValidDirectoryName(value)) {
throw new ArgumentException(SR.GetString(SR.Page_theme_invalid_name, value), "Theme");
}
_themeName = value;
}
}
internal bool SupportsStyleSheets {
get {
if (_supportsStyleSheets == -1) {
if (Header != null &&
Header.StyleSheet != null &&
RequestInternal != null &&
Request.Browser != null &&
(string)Request.Browser["preferredRenderingType"] != "xhtml-mp" &&
Request.Browser.SupportsCss &&
!Page.IsCallback &&
(ScriptManager == null || !ScriptManager.IsInAsyncPostBack)) {
// We don't want to render the style sheet for XHTML mobile profile devices even though
// SupportsCss may be true because they need the CSS to be in a separate file.
// We don't want embedded styles sheet to render during a callback (VSWhidbey 420743)
_supportsStyleSheets = 1;
return true;
}
_supportsStyleSheets = 0;
return false;
}
return (_supportsStyleSheets == 1);
}
}
[
Browsable(false),
Filterable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public virtual String StyleSheetTheme {
get {
return _styleSheetName;
}
set {
if (_pageFlags[styleSheetInitialized]) {
throw new InvalidOperationException(SR.GetString(SR.SetStyleSheetThemeCannotBeSet));
}
_styleSheetName = value;
}
}
/// <devdoc>
/// <para>Indicates the user making the page request. This property uses the
/// Context.User property to determine where the request originates. This property
/// is read-only.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public IPrincipal User {
get { return Context.User;}
}
internal XhtmlConformanceMode XhtmlConformanceMode {
get {
// We only want the evaluation of conformance mode to be done at most once per page request.
if (!_xhtmlConformanceModeSet) {
// The conformance mode is used to determine if backward compatible markup should
// be generated as in pre-Whidbey versions. So if an adapter is assigned, we can
// assume this is Whidbey rendering and we return the default mode that doesn't do
// backward compatible rendering.
if (DesignMode) {
_xhtmlConformanceMode = XhtmlConformanceSection.DefaultMode;
}
else {
_xhtmlConformanceMode = GetXhtmlConformanceSection().Mode;
}
_xhtmlConformanceModeSet = true;
}
return _xhtmlConformanceMode;
}
}
/*
* This protected virtual method is called by the Page to create the HtmlTextWriter
* to use for rendering. The class created is based on the TagWriter property on
* the browser capabilities.
*/
/// <devdoc>
/// <para>Creates an <see cref='System.Web.UI.HtmlTextWriter'/> object to render the page's
/// content. If the <see langword='IsUplevel'/> property is set to
/// <see langword='false'/>, an <see langword='Html32TextWriter'/> object is created
/// to render requests originating from downlevel browsers. For derived pages, you
/// can override this method to create a custom text writer.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected internal virtual HtmlTextWriter CreateHtmlTextWriter(TextWriter tw) {
// Use Context.Request (rather than Request) to avoid exception in get_Request when
// Request is not available.
if (Context != null && Context.Request != null && Context.Request.Browser != null) {
return Context.Request.Browser.CreateHtmlTextWriter(tw);
}
HtmlTextWriter writer = CreateHtmlTextWriterInternal(tw, _request );
if (writer == null) {
writer = new HtmlTextWriter(tw);
}
return writer;
}
internal static HtmlTextWriter CreateHtmlTextWriterInternal(TextWriter tw, HttpRequest request) {
if (request != null && request.Browser != null) {
return request.Browser.CreateHtmlTextWriterInternal(tw);
}
// Fall back to Html 3.2
return new Html32TextWriter(tw);
}
public static HtmlTextWriter CreateHtmlTextWriterFromType(TextWriter tw, Type writerType) {
if (writerType == typeof(HtmlTextWriter)) {
return new HtmlTextWriter(tw);
}
else if (writerType == typeof(Html32TextWriter)) {
return new Html32TextWriter(tw);
}
else {
try {
// Make sure the type has the correct base class (ASURT 123677)
Util.CheckAssignableType(typeof(HtmlTextWriter), writerType);
return (HtmlTextWriter)HttpRuntime.CreateNonPublicInstance(writerType, new object[] { tw });
}
catch {
throw new HttpException(SR.GetString(SR.Invalid_HtmlTextWriter, writerType.FullName));
}
}
}
/// <devdoc>
/// Overridden to check the Page's own ID against the one being searched.
/// </devdoc>
public override Control FindControl(String id) {
if (StringUtil.EqualsIgnoreCase(id, PageID)) {
return this;
}
return base.FindControl(id, 0);
}
/*
* This method is implemented by the Page classes that we generate on
* the fly. It returns a has code unique to the control layout.
*/
/// <devdoc>
/// <para>Retrieves a hash code that is generated by <see langword='Page'/> objects that
/// are generated at runtime. This hash code is unique to the page's control
/// layout.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual int GetTypeHashCode() {
return 0;
}
/*
* Override for small efficiency win: page doesn't prepend its name
*/
internal override string GetUniqueIDPrefix() {
// Only overridde if we're at the top level
if (Parent == null)
return String.Empty;
// Use base implementation for interior nodes
return base.GetUniqueIDPrefix();
}
// This is a non-cryptographic hash code that can be used to identify which Page generated
// a __VIEWSTATE field. It shouldn't be considered sensitive information since its inputs
// are assumed to be known by all parties.
internal uint GetClientStateIdentifier() {
// Use non-randomized hash code algorithms instead of String.GetHashCode.
// Use the page's directory and class name as part of the key (ASURT 64044)
// We need to make sure that the hash is case insensitive, since the file system
// is, and strange view state errors could otherwise happen (ASURT 128657)
int pageHashCode = StringUtil.GetNonRandomizedHashCode(TemplateSourceDirectory, ignoreCase:true);
pageHashCode += StringUtil.GetNonRandomizedHashCode(GetType().Name, ignoreCase:true);
return (uint)pageHashCode;
}
/*
* Called when an exception occurs in ProcessRequest
*/
/// <devdoc>
/// <para>Throws an <see cref='System.Web.HttpException'/> object when an error occurs during a call to the
/// <see cref='System.Web.UI.Page.ProcessRequest'/> method. If there is a custom error page, and
/// custom error page handling is enabled, the method redirects to the specified
/// custom error page.</para>
/// </devdoc>
private bool HandleError(Exception e) {
try {
// Remember the exception to be accessed via Server.GetLastError/ClearError
Context.TempError = e;
// Raise the error event
OnError(EventArgs.Empty);
// If the error has been cleared by the event handler, nothing else to do
if (Context.TempError == null)
return true;
} finally {
Context.TempError = null;
}
// If an error page was specified, redirect to it
if (!String.IsNullOrEmpty(_errorPage)) {
// only redirect if custom errors are enabled:
if (Context.IsCustomErrorEnabled) {
_response.RedirectToErrorPage(_errorPage, CustomErrorsSection.GetSettings(Context).RedirectMode);
return true;
}
}
// Increment all of the appropriate error counters
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_UNHANDLED);
string traceString = null;
if (Context.TraceIsEnabled) {
Trace.Warn(SR.GetString(SR.Unhandled_Err_Error), null, e);
if (Trace.PageOutput) {
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
// Try to build the profile tree so the control hierarchy will show up
BuildPageProfileTree(false);
// these three calls will happen again at the end of the request, but
// in order to have the full trace log on the rendered page, we need
// to call them now.
Trace.EndRequest();
Trace.StopTracing();
Trace.StatusCode = 500;
Trace.Render(htw);
traceString = sw.ToString();
}
}
// If the exception is an HttpException with a formatter, just
// rethrow it instead of a new one (ASURT 45479)
if (HttpException.GetErrorFormatter(e) != null) {
return false;
}
// Don't touch security exceptions (ASURT 78366)
if (e is System.Security.SecurityException)
return false;
throw new HttpUnhandledException(null, traceString, e);
}
/// <devdoc>
/// <para>Gets a value indicating whether the page is being created in response to a
/// cross page postback.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public bool IsCrossPagePostBack {
get {
return _isCrossPagePostBack;
}
}
internal bool IsExportingWebPart {
get {
return _pageFlags[isExportingWebPart];
}
}
internal bool IsExportingWebPartShared {
get {
return _pageFlags[isExportingWebPartShared];
}
}
/*
* Returns true if this is a postback, which means it has some
* previous viewstate to reload. Use this in the Load method to differentiate
* an initial load from a postback reload.
*/
/// <devdoc>
/// <para>Gets a value indicating whether the page is being loaded in response to a
/// client postback, or if it is being loaded and accessed for the first time.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public bool IsPostBack {
get {
if (_requestValueCollection == null)
return false;
// Treat it as postback if the page is created thru cross page postback.
if (_isCrossPagePostBack)
return true;
// Don't treat it as a postback if the page is posted from cross page
if (_pageFlags[isCrossPagePostRequest])
return false;
// Don't treat it as a postback if a view state MAC check failed and we
// simply ate the exception.
if (ViewStateMacValidationErrorWasSuppressed)
return false;
// If we're in a Transfer/Execute, never treat as postback (ASURT 121000)
// Unless we are being transfered back to the original page, in which case
// it is ok to treat it as a postback (VSWhidbey 117747)
// Note that Context.Handler could be null (VSWhidbey 159775)
if (Context.ServerExecuteDepth > 0 &&
(Context.Handler == null || GetType() != Context.Handler.GetType())) {
return false;
}
// If the page control layout has changed, pretend that we are in
// a non-postback situation.
return !_fPageLayoutChanged;
}
}
internal NameValueCollection RequestValueCollection {
get { return _requestValueCollection; }
}
[
Browsable(false),
DefaultValue(true),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Never),
]
public virtual bool EnableEventValidation {
get {
return _enableEventValidation;
}
set {
if (this.ControlState > ControlState.FrameworkInitialized) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetAfterFrameworkInitialize, "EnableEventValidation"));
}
_enableEventValidation = value;
}
}
[
Browsable(false)
]
public override bool EnableViewState {
get {
return base.EnableViewState;
}
set {
base.EnableViewState = value;
}
}
[
Browsable(false),
DefaultValue(ViewStateEncryptionMode.Auto),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),
EditorBrowsable(EditorBrowsableState.Never),
]
public ViewStateEncryptionMode ViewStateEncryptionMode {
get {
return _encryptionMode;
}
set {
if (this.ControlState > ControlState.FrameworkInitialized) {
throw new InvalidOperationException(SR.GetString(SR.PropertySetAfterFrameworkInitialize, "ViewStateEncryptionMode"));
}
if (value < ViewStateEncryptionMode.Auto || value > ViewStateEncryptionMode.Never) {
throw new ArgumentOutOfRangeException("value");
}
_encryptionMode = value;
}
}
/// <devdoc>
/// <para>Setting this property helps prevent one-click attacks (ASURT 126375)</para>
/// </devdoc>
[
Browsable(false)
]
public string ViewStateUserKey {
get {
return _viewStateUserKey;
}
set {
// Make sure it's not called too late
if (ControlState >= ControlState.Initialized) {
throw new HttpException(SR.GetString(SR.Too_late_for_ViewStateUserKey));
}
_viewStateUserKey = value;
}
}
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never)
]
public override string ID {
get {
return base.ID;
}
set {
base.ID = value;
}
}
[
Browsable(false),
EditorBrowsable(EditorBrowsableState.Never),
DefaultValue(ValidateRequestMode.Enabled)
]
public override ValidateRequestMode ValidateRequestMode {
get {
return base.ValidateRequestMode;
}
set {
base.ValidateRequestMode = value;
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[DefaultValue(false)]
// If this property is false, then
// - we eagerly validate RawUrl at the appropriate point in ProcessRequestMain / ProcessRequestTransacted, and
// - the ClientQueryString property is populated from Request.QueryString (and might be validated) instead of Request.Unvalidated.QueryString.
public bool SkipFormActionValidation {
get {
return _pageFlags[skipFormActionValidation];
}
set {
// Clear the cached ClientQueryString value if the value of this property changes
if (value != SkipFormActionValidation) {
_clientQueryString = null;
}
_pageFlags[skipFormActionValidation] = value;
}
}
[
Browsable(false)
]
public override bool Visible {
get {
return base.Visible;
}
set {
base.Visible = value;
}
}
/// <devdoc>
/// <para>Decrypt the string using symmetric algorithm defined in config.</para>
/// </devdoc>
internal static string DecryptString(string s, Purpose purpose) {
if (s == null)
return null;
byte[] protectedData = HttpServerUtility.UrlTokenDecode(s);
// DevDiv Bugs 137864: IVType.Hash is necessary for WebResource / ScriptResource URLs
// so that client and server caching will continue to work. MS AJAX also caches these
// client-side, and switching to a different IV type could potentially break MS AJAX
// due to loading the same Javascript resource multiple times.
// MSRC 10405: Crypto board approves of this usage of IVType.Hash.
byte[] clearData = null;
if (protectedData != null) {
if (AspNetCryptoServiceProvider.Instance.IsDefaultProvider) {
// ASP.NET 4.5 Crypto DCR: Go through the new AspNetCryptoServiceProvider
// if we're configured to do so.
ICryptoService cryptoService = AspNetCryptoServiceProvider.Instance.GetCryptoService(purpose, CryptoServiceOptions.CacheableOutput);
clearData = cryptoService.Unprotect(protectedData);
}
else {
// If we're not configured to go through the new crypto routines,
// fall back to the standard MachineKey crypto routines.
#pragma warning disable 618 // calling obsolete methods
clearData = MachineKeySection.EncryptOrDecryptData(fEncrypt: false, buf: protectedData, modifier: null, start: 0, length: protectedData.Length, useValidationSymAlgo: false, useLegacyMode: false, ivType: IVType.Hash);
#pragma warning restore 618 // calling obsolete methods
}
}
if (clearData == null)
throw new HttpException(SR.GetString(SR.ViewState_InvalidViewState));
return Encoding.UTF8.GetString(clearData);
}
/*
* Performs intialization of the page required by the designer.
*/
/// <devdoc>
/// <para>Performs any initialization of the page that is required by RAD designers.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Never)]
public void DesignerInitialize() {
InitRecursive(null);
}
internal NameValueCollection GetCollectionBasedOnMethod(bool dontReturnNull) {
// Get the right NameValueCollection base on the method
if (_request.HttpVerb == HttpVerb.POST) {
return (dontReturnNull || _request.HasForm) ? _request.Form : null;
}
else {
return (dontReturnNull || _request.HasQueryString) ? _request.QueryString : null;
}
}
private bool DetermineIsExportingWebPart() {
byte[] queryString = Request.QueryStringBytes;
if ((queryString == null) || (queryString.Length < 28)) {
return false;
}
// query string is never unicode - it can be UTF-8, in which case it's fine to compare character by character
// because what we're looking for is only in the low-ASCII range.
if ((queryString[0] != '_') ||
(queryString[1] != '_') ||
(queryString[2] != 'W') ||
(queryString[3] != 'E') ||
(queryString[4] != 'B') ||
(queryString[5] != 'P') ||
(queryString[6] != 'A') ||
(queryString[7] != 'R') ||
(queryString[8] != 'T') ||
(queryString[9] != 'E') ||
(queryString[10] != 'X') ||
(queryString[11] != 'P') ||
(queryString[12] != 'O') ||
(queryString[13] != 'R') ||
(queryString[14] != 'T') ||
(queryString[15] != '=') ||
(queryString[16] != 't') ||
(queryString[17] != 'r') ||
(queryString[18] != 'u') ||
(queryString[19] != 'e') ||
(queryString[20] != '&')) {
return false;
}
// Setting the export flag so that personalization can know not to toggle modes,
// which would create a new subrequest and kill the export.
_pageFlags.Set(isExportingWebPart);
return true;
}
/*
* Determine which of the following three cases we're in:
* - Initial request. No postback, return null
* - GET postback request. Return Context.Request.QueryString
* - POST postback request. Return Context.Request.Form
*/
/// <devdoc>
/// <para>Determines the type of request made for the page based on if the page was a
/// postback, and whether a GET or POST method was used for the request.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected internal virtual NameValueCollection DeterminePostBackMode() {
if (Context.Request == null)
return null;
// If PreventPostback is set, don't treat as postback (VSWhidbey 181013).
if (Context.PreventPostback)
return null;
NameValueCollection ret = GetCollectionBasedOnMethod(dontReturnNull: false);
if (ret == null)
return null;
// Some devices may send incorrect POST strings without trailing equal signs
// if the last field is empty. Detecting this:
bool isPostback = false;
String [] nullValues = ret.GetValues(null);
if (nullValues != null) {
int numNull = nullValues.Length;
for (int i = 0; i < numNull; i++) {
if (nullValues[i].StartsWith(ViewStateFieldPrefixID, StringComparison.Ordinal) || nullValues[i] == postEventSourceID) {
isPostback = true;
break;
}
}
}
// If there is no state or postEventSourceID in the request,
// it's an initial request
//
if (ret[ViewStateFieldPrefixID] == null &&
ret[ViewStateFieldCountID] == null &&
ret[postEventSourceID] == null &&
!isPostback)
ret = null;
// If page was posted due to a HttpResponse.Redirect, ignore the postback.
else if (Request.QueryStringText.IndexOf(HttpResponse.RedirectQueryStringAssignment, StringComparison.Ordinal) != -1)
ret = null;
return ret;
}
/// <summary>
/// Returns an unvalidated name/value collection of the postback variables. This method will
/// only be called if DeterminePostBackMode() returns a non-null value.
/// This method exists to support the granular request validation feature added in .NET 4.5
/// </summary>
/// <returns>An unvalidated name/value collection of the postback variables.</returns>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected internal virtual NameValueCollection DeterminePostBackModeUnvalidated() {
// Get the right NameValueCollection base on the method. This is modeled on GetCollectionBasedOnMethod()
return _request.HttpVerb == HttpVerb.POST ? _request.Unvalidated.Form : _request.Unvalidated.QueryString;
}
/// <devdoc>
/// <para>This method is used to encrypt previous page hidden form variable that is sent to the client
/// during cross page post. This is to prevent spoofed previous pages from being instantiated and executed.</para>
/// This is also used by the AssemblyResourceLoader to prevent tampering of URLs.
/// </devdoc>
internal static string EncryptString(string s, Purpose purpose) {
Debug.Assert(s != null);
// DevDiv Bugs 137864: IVType.Hash is necessary for WebResource / ScriptResource URLs
// so that client and server caching will continue to work. MS AJAX also caches these
// client-side, and switching to a different IV type could potentially break MS AJAX
// due to loading the same Javascript resource multiple times.
// MSRC 10405: Crypto board approves of this usage of IVType.Hash.
byte[] clearData = Encoding.UTF8.GetBytes(s);
byte[] protectedData;
if (AspNetCryptoServiceProvider.Instance.IsDefaultProvider) {
// ASP.NET 4.5 Crypto DCR: Go through the new AspNetCryptoServiceProvider
// if we're configured to do so.
ICryptoService cryptoService = AspNetCryptoServiceProvider.Instance.GetCryptoService(purpose, CryptoServiceOptions.CacheableOutput);
protectedData = cryptoService.Protect(clearData);
}
else {
// If we're not configured to go through the new crypto routines,
// fall back to the standard MachineKey crypto routines.
#pragma warning disable 618 // calling obsolete methods
protectedData = MachineKeySection.EncryptOrDecryptData(fEncrypt: true, buf: clearData, modifier: null, start: 0, length: clearData.Length, useValidationSymAlgo: false, useLegacyMode: false, ivType: IVType.Hash);
#pragma warning restore 618 // calling obsolete methods
}
return HttpServerUtility.UrlTokenEncode(protectedData);
}
private void LoadAllState() {
object state = LoadPageStateFromPersistenceMedium();
IDictionary controlStates = null;
Pair allSavedViewState = null;
Pair statePair = state as Pair;
if (state != null) {
controlStates = statePair.First as IDictionary;
allSavedViewState = statePair.Second as Pair;
}
// The control state (controlStatePair) was saved as an dictionary of objects:
// 1. A list of controls that require postback[under the page id]
// 2. A dictionary of control states
if (controlStates != null) {
_controlsRequiringPostBack = (ArrayList)controlStates[PageRegisteredControlsThatRequirePostBackKey];
if (_registeredControlsRequiringControlState != null) {
foreach (Control ctl in _registeredControlsRequiringControlState) {
ctl.LoadControlStateInternal(controlStates[ctl.UniqueID]);
}
}
}
// The view state (allSavedViewState) was saved as an array of objects:
// 1. The hash code string
// 2. The state of the entire control hierarchy
// Is there any state?
if (allSavedViewState != null) {
// Get the hash code from the state
string hashCode = (string) allSavedViewState.First;
// If it's different from the current one, the layout has changed
int viewhash = Int32.Parse(hashCode, NumberFormatInfo.InvariantInfo);
_fPageLayoutChanged = viewhash != GetTypeHashCode();
// If the page control layout has changed, don't attempt to
// load any more state.
if (!_fPageLayoutChanged) {
// UNCOMMENT FOR DEBUG OUTPUT
// WalkViewState(allSavedViewState.Second, null, 0);
LoadViewStateRecursive(allSavedViewState.Second);
}
}
}
/*
* Override this method to persist view state to something other
* than hidden fields (
*/
/// <devdoc>
/// <para>Loads any saved view state information to the page. Override this method if
/// you want to load the page view state in anything other than a hidden field.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected internal virtual object LoadPageStateFromPersistenceMedium() {
PageStatePersister persister = PageStatePersister;
try {
persister.Load();
}
catch (HttpException e) {
//VSWhidbey 201601. Ignore the exception in cross-page post
//since this might be a cross application postback.
if (_pageFlags[isCrossPagePostRequest]) {
return null;
}
// DevDiv #461378: Ignore validation errors for cross-page postbacks.
if (ShouldSuppressMacValidationException(e)) {
if (Context != null && Context.TraceIsEnabled) {
Trace.Write("aspx.page", "Ignoring page state", e);
}
ViewStateMacValidationErrorWasSuppressed = true;
return null;
}
e.WebEventCode = WebEventCodes.RuntimeErrorViewStateFailure;
throw;
}
return new Pair(persister.ControlState, persister.ViewState);
}
private bool ViewStateMacValidationErrorWasSuppressed {
get { return _pageFlags[wasViewStateMacErrorSuppressed]; }
set { _pageFlags[wasViewStateMacErrorSuppressed] = value; }
}
internal bool ShouldSuppressMacValidationException(Exception e) {
// If the patch isn't active, don't suppress anything, as it would be a change in behavior.
if (!EnableViewStateMacRegistryHelper.SuppressMacValidationErrorsFromCrossPagePostbacks) {
return false;
}
// We check the __VIEWSTATEGENERATOR field for an identifier that matches the current Page.
// If the generator field exists and says that the current Page generated the incoming
// __VIEWSTATE field, then a validation failure represents a real error and we need to
// surface this information to the developer for resolution. Otherwise we assume this
// view state was not meant for us, so if validation fails we'll just ignore __VIEWSTATE.
if (ViewStateException.IsMacValidationException(e)) {
if (EnableViewStateMacRegistryHelper.SuppressMacValidationErrorsAlways) {
return true;
}
// DevDiv #841854: VSUK is often used for CSRF checks, so we can't ---- MAC exceptions by default in this case.
if (!String.IsNullOrEmpty(ViewStateUserKey)) {
return false;
}
if (_requestValueCollection == null) {
return true;
}
if (!VerifyClientStateIdentifier(_requestValueCollection[ViewStateGeneratorFieldID])) {
return true;
}
}
return false;
}
private bool VerifyClientStateIdentifier(string identifier) {
// Returns true iff we can parse the incoming identifier and it matches our own.
// If we can't parse the identifier, then by definition we didn't generate it.
uint parsedIdentifier;
return identifier != null
&& UInt32.TryParse(identifier, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out parsedIdentifier)
&& parsedIdentifier == GetClientStateIdentifier();
}
internal void LoadScrollPosition() {
// Don't load scroll position if the previous page was a crosspage postback
if (_previousPagePath != null) {
return;
}
// Load the scroll positions from the request if they exist
if (_requestValueCollection != null) {
double doubleValue;
string xpos = _requestValueCollection[_scrollPositionXID];
if (xpos != null) {
_scrollPositionX = HttpUtility.TryParseCoordinates(xpos, out doubleValue) ? (int)doubleValue : 0 ;
}
string ypos = _requestValueCollection[_scrollPositionYID];
if (ypos != null) {
_scrollPositionY = HttpUtility.TryParseCoordinates(ypos, out doubleValue) ? (int)doubleValue : 0 ;
}
}
}
internal IStateFormatter2 CreateStateFormatter() {
return new ObjectStateFormatter(this, true);
}
// Decomposes the large view state string into pieces of size <= MaxPageStateFieldLength
internal ICollection DecomposeViewStateIntoChunks() {
string state = ClientState;
if (state == null) return null;
// Any value less than or equal to 0 turns off chunking
if (MaxPageStateFieldLength <= 0) {
ArrayList chunks = new ArrayList(1);
chunks.Add(state);
return chunks;
}
// Break up the view state into the correctly sized chunks
int numFullChunks = ClientState.Length / MaxPageStateFieldLength;
ArrayList viewStateChunks = new ArrayList(numFullChunks+1);
int curPos = 0;
for (int i=0; i<numFullChunks; i++) {
viewStateChunks.Add(state.Substring(curPos, MaxPageStateFieldLength));
curPos += MaxPageStateFieldLength;
}
// Add the leftover characters
if (curPos < state.Length) {
viewStateChunks.Add(state.Substring(curPos));
}
// Always want to return at least one empty chunk
if (viewStateChunks.Count == 0) {
viewStateChunks.Add(String.Empty);
}
return viewStateChunks;
}
internal void RenderViewStateFields(HtmlTextWriter writer) {
if (_hiddenFieldsToRender == null) {
_hiddenFieldsToRender = new Dictionary<string, string>();
}
if (ClientState != null) {
ICollection viewStateChunks = DecomposeViewStateIntoChunks();
writer.WriteLine();
// Don't write out a view state field count if there is only 1 viewstate field
if (viewStateChunks.Count > 1) {
string value = viewStateChunks.Count.ToString(CultureInfo.InvariantCulture);
writer.Write("<input type=\"hidden\" name=\"");
writer.Write(ViewStateFieldCountID);
writer.Write("\" id=\"");
writer.Write(ViewStateFieldCountID);
writer.Write("\" value=\"");
writer.Write(value);
writer.WriteLine("\" />");
_hiddenFieldsToRender[ViewStateFieldCountID] = value;
}
int count = 0;
foreach (string stateChunk in viewStateChunks) {
writer.Write("<input type=\"hidden\" name=\"");
string name = ViewStateFieldPrefixID;
writer.Write(ViewStateFieldPrefixID);
string countString = null;
if (count > 0) {
countString = count.ToString(CultureInfo.InvariantCulture);
name += countString;
writer.Write(countString);
}
writer.Write("\" id=\"");
writer.Write(name);
writer.Write("\" value=\"");
writer.Write(stateChunk);
writer.WriteLine("\" />");
++count;
_hiddenFieldsToRender[name] = stateChunk;
}
// DevDiv #461378: Write out an identifier so we know who generated this __VIEWSTATE field.
// It doesn't need to be MACed since the only thing we use it for is error suppression,
// similar to how __PREVIOUSPAGE works.
if (EnableViewStateMacRegistryHelper.WriteViewStateGeneratorField) {
// hex is easier than base64 to work with and consumes only one extra byte on the wire
ClientScript.RegisterHiddenField(ViewStateGeneratorFieldID, GetClientStateIdentifier().ToString("X8", CultureInfo.InvariantCulture));
}
}
else {
// ASURT 106992
// Need to always render out the viewstate field so alternate viewstate persistence will get called
writer.Write("\r\n<input type=\"hidden\" name=\"");
writer.Write(ViewStateFieldPrefixID);
// Dev10 Bug 486494
// Remove previously rendered NewLine
writer.Write("\" id=\"");
writer.Write(ViewStateFieldPrefixID);
writer.WriteLine("\" value=\"\" />");
_hiddenFieldsToRender[ViewStateFieldPrefixID] = String.Empty;
}
}
/// <devdoc>
/// Default markup for begin form.
/// </devdoc>
internal void BeginFormRender(HtmlTextWriter writer, string formUniqueID) {
// DevDiv 27324: Form should render div tag around hidden inputs
// DevDiv 33149: backward compat. switch for obsolete rendering
// Dev10 705089: in 4.0 mode or later, we render the div block with class="aspNetHidden" for xHTML conformance.
bool renderDivAroundHiddenInputs = RenderDivAroundHiddenInputs(writer);
if (renderDivAroundHiddenInputs) {
writer.WriteLine();
if (RenderingCompatibility >= VersionUtil.Framework40) {
writer.Write("<div class=\"" + HiddenClassName + "\">");
}
else {
writer.Write("<div>");
}
}
ClientScript.RenderHiddenFields(writer);
RenderViewStateFields(writer);
if (renderDivAroundHiddenInputs) {
writer.WriteLine("</div>");
}
if (ClientSupportsJavaScript) {
if (MaintainScrollPositionOnPostBack && _requireScrollScript == false) {
ClientScript.RegisterHiddenField(_scrollPositionXID, _scrollPositionX.ToString(CultureInfo.InvariantCulture));
ClientScript.RegisterHiddenField(_scrollPositionYID, _scrollPositionY.ToString(CultureInfo.InvariantCulture));
ClientScript.RegisterStartupScript(typeof(Page), PageScrollPositionScriptKey, @"
theForm.oldSubmit = theForm.submit;
theForm.submit = WebForm_SaveScrollPositionSubmit;
theForm.oldOnSubmit = theForm.onsubmit;
theForm.onsubmit = WebForm_SaveScrollPositionOnSubmit;
" + (IsPostBack ? @"
theForm.oldOnLoad = window.onload;
window.onload = WebForm_RestoreScrollPosition;
" : String.Empty), true);
RegisterWebFormsScript();
_requireScrollScript = true;
}
// VSWhidbey 375885, Render the focus script later (specifically for interaction with scrollposition)
if (ClientSupportsFocus && Form != null && (RenderFocusScript || (Form.DefaultFocus.Length > 0) || (Form.DefaultButton.Length > 0))) {
string focusedControlId = String.Empty;
// Someone calling SetFocus(controlId) is the most precendent
if (FocusedControlID.Length > 0) {
focusedControlId = FocusedControlID;
}
else if (FocusedControl != null) {
if (FocusedControl.Visible) {
focusedControlId = FocusedControl.ClientID;
}
}
else if (ValidatorInvalidControl.Length > 0) {
focusedControlId = ValidatorInvalidControl;
}
// AutoPostBack focus is the second least precendent
else if (LastFocusedControl.Length > 0) {
// This doesn't have to be an ASP.NET control
focusedControlId = LastFocusedControl;
}
// DefaultFocus is the next
else if (Form.DefaultFocus.Length > 0) {
// VSWhidbey 379627: Always render the default focus, regardless if we can find it, or if its visible
focusedControlId = Form.DefaultFocus;
}
// DefaultButton is the least precendent
else if (Form.DefaultButton.Length > 0) {
focusedControlId = Form.DefaultButton;
}
// If something got focused, render some script to focus it only if its safe
int match;
if (focusedControlId.Length > 0 && !CrossSiteScriptingValidation.IsDangerousString(focusedControlId, out match) &&
CrossSiteScriptingValidation.IsValidJavascriptId(focusedControlId)) {
ClientScript.RegisterClientScriptResource(typeof(HtmlForm), "Focus.js");
if (!ClientScript.IsClientScriptBlockRegistered(typeof(HtmlForm), "Focus")) {
RegisterWebFormsScript();
ClientScript.RegisterStartupScript(
typeof(HtmlForm),
"Focus",
"WebForm_AutoFocus('" + Util.QuoteJScriptString(focusedControlId) + "');",
true);
}
IScriptManager scriptManager = ScriptManager;
if (scriptManager != null) {
scriptManager.SetFocusInternal(focusedControlId);
}
}
}
// Set the necessary stuff to re-enable disabled controls on the client
if (RenderDisabledControlsScript) {
ClientScript.RegisterOnSubmitStatement(typeof(Page), PageReEnableControlsScriptKey, "WebForm_ReEnableControls();");
RegisterWebFormsScript();
}
if (_fRequirePostBackScript) {
RenderPostBackScript(writer, formUniqueID);
}
if (_fRequireWebFormsScript) {
RenderWebFormsScript(writer);
}
}
ClientScript.RenderClientScriptBlocks(writer);
}
internal void EndFormRenderArrayAndExpandoAttribute(HtmlTextWriter writer, string formUniqueID) {
if (ClientSupportsJavaScript) {
// Devdiv 9409 - Register the array for reenabling only after the controls have been processed,
// so that list controls can have their children registered.
if (RenderDisabledControlsScript) {
foreach (Control control in EnabledControls) {
ClientScript.RegisterArrayDeclaration(EnabledControlArray, "'" + control.ClientID + "'");
}
}
ClientScript.RenderArrayDeclares(writer);
ClientScript.RenderExpandoAttribute(writer);
}
}
private bool RenderDisabledControlsScript {
get {
return Form.SubmitDisabledControls && (EnabledControls.Count > 0) &&
(_request.Browser.W3CDomVersion.Major > 0);
}
}
internal void EndFormRenderHiddenFields(HtmlTextWriter writer, string formUniqueID) {
if (RequiresViewStateEncryptionInternal) {
ClientScript.RegisterHiddenField(ViewStateEncryptionID, String.Empty);
}
if (_containsCrossPagePost) {
string path = EncryptString(Request.CurrentExecutionFilePath, Purpose.WebForms_Page_PreviousPageID);
ClientScript.RegisterHiddenField(previousPageID, path);
}
if (EnableEventValidation) {
ClientScript.SaveEventValidationField();
}
if (ClientScript.HasRegisteredHiddenFields) {
bool renderDivAroundHiddenInputs = RenderDivAroundHiddenInputs(writer);
if (renderDivAroundHiddenInputs) {
writer.WriteLine();
if (RenderingCompatibility >= VersionUtil.Framework40) {
writer.AddAttribute(HtmlTextWriterAttribute.Class, HiddenClassName);
}
writer.RenderBeginTag(HtmlTextWriterTag.Div);
}
ClientScript.RenderHiddenFields(writer);
if (renderDivAroundHiddenInputs) {
writer.RenderEndTag(); // DIV
}
}
}
internal void EndFormRenderPostBackAndWebFormsScript(HtmlTextWriter writer, string formUniqueID) {
if (ClientSupportsJavaScript) {
if (_fRequirePostBackScript && !_fPostBackScriptRendered) {
RenderPostBackScript(writer, formUniqueID);
}
if (_fRequireWebFormsScript && !_fWebFormsScriptRendered)
RenderWebFormsScript(writer);
}
ClientScript.RenderClientStartupScripts(writer);
}
/// <devdoc>
/// Default markup for end form.
/// </devdoc>
internal void EndFormRender(HtmlTextWriter writer, string formUniqueID) {
EndFormRenderArrayAndExpandoAttribute(writer, formUniqueID);
EndFormRenderHiddenFields(writer, formUniqueID);
EndFormRenderPostBackAndWebFormsScript(writer, formUniqueID);
}
// VSWhidbey 475945: For ClientScriptManager.GetPostBackEventReference() to check if '$' should be used for id separator
internal bool IsInOnFormRender {
get {
return _inOnFormRender;
}
}
/// <devdoc>
/// Called by both adapters and default rendering prior to form rendering.
/// </devdoc>
internal void OnFormRender() {
// Make sure there is only one form tag (ASURT 18891, 18894)
if (_fOnFormRenderCalled) {
throw new HttpException(SR.GetString(SR.Multiple_forms_not_allowed));
}
_fOnFormRenderCalled = true;
_inOnFormRender = true;
}
/// <devdoc>
/// Called by both adapters and default rendering after form rendering.
/// </devdoc>
internal void OnFormPostRender(HtmlTextWriter writer) {
_inOnFormRender = false;
if (_postFormRenderDelegate != null) {
_postFormRenderDelegate(writer, null);
}
}
/// <devdoc>
/// Needed by adapters which do more than one pass, so that OnFormRender can be called more than once.
/// </devdoc>
//
internal void ResetOnFormRenderCalled() {
_fOnFormRenderCalled = false;
}
/// <devdoc>
/// Sets focus to the specified control
/// </devdoc>
public void SetFocus(Control control) {
if (control == null) {
throw new ArgumentNullException("control");
}
if (Form == null) {
throw new InvalidOperationException(SR.GetString(SR.Form_Required_For_Focus));
}
if (Form.ControlState == ControlState.PreRendered) {
throw new InvalidOperationException(SR.GetString(SR.Page_MustCallBeforeAndDuringPreRender, "SetFocus"));
}
_focusedControl = control;
_focusedControlID = null;
RegisterFocusScript();
}
/// <devdoc>
/// Sets focus to the specified client id
/// </devdoc>
public void SetFocus(string clientID) {
if ((clientID == null) || (clientID.Trim().Length == 0)) {
throw new ArgumentNullException("clientID");
}
if (Form == null) {
throw new InvalidOperationException(SR.GetString(SR.Form_Required_For_Focus));
}
if (Form.ControlState == ControlState.PreRendered) {
throw new InvalidOperationException(SR.GetString(SR.Page_MustCallBeforeAndDuringPreRender, "SetFocus"));
}
_focusedControlID = clientID.Trim();
_focusedControl = null;
RegisterFocusScript();
}
internal void SetValidatorInvalidControlFocus(string clientID) {
if (String.IsNullOrEmpty(_validatorInvalidControl)) {
_validatorInvalidControl = clientID;
RegisterFocusScript();
}
}
//Note: BCL should provide a way to abort threads without asserting ControlThread for platform internal code.
[SecurityPermission(SecurityAction.Assert, ControlThread = true)]
internal static void ThreadResetAbortWithAssert() {
Thread.ResetAbort();
}
/*
* Enables controls to obtain client-side script function that will cause
* (when invoked) a server post-back to the form.
*/
/// <devdoc>
/// <para>
/// Associates the reference to the control that will
/// process the postback on the server.
/// </para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Obsolete("The recommended alternative is ClientScript.GetPostBackEventReference. http://go.microsoft.com/fwlink/?linkid=14202")]
public string GetPostBackEventReference(Control control) {
return ClientScript.GetPostBackEventReference(control, String.Empty);
}
/*
* Enables controls to obtain client-side script function that will cause
* (when invoked) a server post-back to the form.
* argument: Parameter that will be passed to control on server
*/
/// <devdoc>
/// <para>Passes a parameter to the control that will do the postback processing on the
/// server.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Obsolete("The recommended alternative is ClientScript.GetPostBackEventReference. http://go.microsoft.com/fwlink/?linkid=14202")]
public string GetPostBackEventReference(Control control,
string argument) {
return ClientScript.GetPostBackEventReference(control, argument);
}
/// <devdoc>
/// <para>This returs a string that can be put in client event to post back to the named control</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Obsolete("The recommended alternative is ClientScript.GetPostBackEventReference. http://go.microsoft.com/fwlink/?linkid=14202")]
public string GetPostBackClientEvent(Control control, string argument) {
return ClientScript.GetPostBackEventReference(control, argument);
}
/// <devdoc>
/// <para>This returs a string that can be put in client event to post back to the named control</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Obsolete("The recommended alternative is ClientScript.GetPostBackClientHyperlink. http://go.microsoft.com/fwlink/?linkid=14202")]
public string GetPostBackClientHyperlink(Control control, string argument) {
return ClientScript.GetPostBackClientHyperlink(control, argument, false);
}
internal void InitializeStyleSheet() {
if (_pageFlags[styleSheetInitialized]) {
return;
}
String styleSheetName = StyleSheetTheme;
if (!String.IsNullOrEmpty(styleSheetName)) {
BuildResultCompiledType resultType = ThemeDirectoryCompiler.GetThemeBuildResultType(
Context, styleSheetName);
if (resultType != null) {
_styleSheet = (PageTheme)resultType.CreateInstance();
_styleSheet.Initialize(this, true);
}
else {
throw new HttpException(SR.GetString(SR.Page_theme_not_found, styleSheetName));
}
}
_pageFlags.Set(styleSheetInitialized);
}
private void InitializeThemes() {
String themeName = Theme;
if (!String.IsNullOrEmpty(themeName)) {
BuildResultCompiledType resultType = ThemeDirectoryCompiler.GetThemeBuildResultType(
Context, themeName);
if (resultType != null) {
_theme = (PageTheme)resultType.CreateInstance();
_theme.Initialize(this, false);
}
else {
throw new HttpException(SR.GetString(SR.Page_theme_not_found, themeName));
}
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected internal void AddContentTemplate(string templateName, ITemplate template) {
if (_contentTemplateCollection == null) {
_contentTemplateCollection = new Hashtable(11, StringComparer.OrdinalIgnoreCase);
}
try {
_contentTemplateCollection.Add(templateName, template);
}
catch (ArgumentException) {
throw new HttpException(SR.GetString(SR.MasterPage_Multiple_content, templateName));
}
}
private void ApplyMasterPage() {
if (Master != null) {
ArrayList appliedMasterPages = new ArrayList();
appliedMasterPages.Add(_masterPageFile.VirtualPathString.ToLower(CultureInfo.InvariantCulture));
MasterPage.ApplyMasterRecursive(Master, appliedMasterPages);
}
}
internal void ApplyControlSkin(Control ctrl) {
if (_theme != null) {
_theme.ApplyControlSkin(ctrl);
}
}
internal bool ApplyControlStyleSheet(Control ctrl) {
if (_styleSheet != null) {
_styleSheet.ApplyControlSkin(ctrl);
return true;
}
return false;
}
internal void RegisterFocusScript() {
if (ClientSupportsFocus && (_requireFocusScript == false)) {
ClientScript.RegisterHiddenField(lastFocusID, String.Empty);
_requireFocusScript = true;
// If there are any partial caching controls on the stack, forward the call to them
if (_partialCachingControlStack != null) {
foreach(BasePartialCachingControl c in _partialCachingControlStack) {
c.RegisterFocusScript();
}
}
}
}
internal void RegisterPostBackScript() {
if (!ClientSupportsJavaScript) {
return;
}
if (_fPostBackScriptRendered) {
return;
}
if (!_fRequirePostBackScript) {
ClientScript.RegisterHiddenField(postEventSourceID, String.Empty);
ClientScript.RegisterHiddenField(postEventArgumentID, String.Empty);
_fRequirePostBackScript = true;
}
// If there are any partial caching controls on the stack, forward the call to them
if (_partialCachingControlStack != null) {
foreach(BasePartialCachingControl c in _partialCachingControlStack) {
c.RegisterPostBackScript();
}
}
}
private void RenderPostBackScript(HtmlTextWriter writer, string formUniqueID) {
writer.Write(EnableLegacyRendering ?
ClientScriptManager.ClientScriptStartLegacy :
ClientScriptManager.ClientScriptStart);
if (PageAdapter != null) {
writer.Write("var theForm = ");
writer.Write(PageAdapter.GetPostBackFormReference(formUniqueID));
writer.WriteLine(";");
}
else {
writer.Write("var theForm = document.forms['");
writer.Write(formUniqueID);
writer.WriteLine("'];");
// VSWhidbey 392597: Try to use the document._ctl00 syntax since PocketPC doesn't support document.forms[id]
writer.Write("if (!theForm) {\r\n theForm = document.");
writer.Write(formUniqueID);
writer.WriteLine(";\r\n}");
}
writer.WriteLine(@"function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}");
writer.WriteLine(EnableLegacyRendering ?
ClientScriptManager.ClientScriptEndLegacy :
ClientScriptManager.ClientScriptEnd);
_fPostBackScriptRendered = true;
}
/// <devdoc>
/// Allows controls on a page to access to the _doPostBack and _doCallback JavaScript handlers on the
/// client. This method can be called multiple times by multiple controls. It should
/// render only one instance of the WebForms script.
/// </devdoc>
internal void RegisterWebFormsScript() {
if (ClientSupportsJavaScript) {
if (_fWebFormsScriptRendered) {
return;
}
RegisterPostBackScript();
_fRequireWebFormsScript = true;
// If there are any partial caching controls on the stack, forward the call to them
if (_partialCachingControlStack != null) {
foreach(BasePartialCachingControl c in _partialCachingControlStack) {
c.RegisterWebFormsScript();
}
}
}
}
private void RenderWebFormsScript(HtmlTextWriter writer) {
ClientScript.RenderWebFormsScript(writer);
_fWebFormsScriptRendered = true;
}
/// <devdoc>
/// <para>Determines if the client script block is registered with the page.</para>
/// </devdoc>
[Obsolete("The recommended alternative is ClientScript.IsClientScriptBlockRegistered(string key). http://go.microsoft.com/fwlink/?linkid=14202")]
public bool IsClientScriptBlockRegistered(string key) {
return ClientScript.IsClientScriptBlockRegistered(typeof(Page), key);
}
/// <devdoc>
/// <para>Determines if the client startup script is registered with the
/// page.</para>
/// </devdoc>
[Obsolete("The recommended alternative is ClientScript.IsStartupScriptRegistered(string key). http://go.microsoft.com/fwlink/?linkid=14202")]
public bool IsStartupScriptRegistered(string key) {
return ClientScript.IsStartupScriptRegistered(typeof(Page), key);
}
/// <devdoc>
/// <para>Declares a value that will be declared as a JavaScript array declaration
/// when the page renders. This can be used by script-based controls to declare
/// themselves within an array so that a client script library can work with
/// all the controls of the same type.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Obsolete("The recommended alternative is ClientScript.RegisterArrayDeclaration(string arrayName, string arrayValue). http://go.microsoft.com/fwlink/?linkid=14202")]
public void RegisterArrayDeclaration(string arrayName, string arrayValue) {
ClientScript.RegisterArrayDeclaration(arrayName, arrayValue);
}
/// <devdoc>
/// <para>
/// Allows controls to automatically register a hidden field on the form. The
/// field will be emitted when the form control renders itself.
/// </para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Obsolete("The recommended alternative is ClientScript.RegisterHiddenField(string hiddenFieldName, string hiddenFieldInitialValue). http://go.microsoft.com/fwlink/?linkid=14202")]
public virtual void RegisterHiddenField(string hiddenFieldName, string hiddenFieldInitialValue) {
ClientScript.RegisterHiddenField(hiddenFieldName, hiddenFieldInitialValue);
}
/// <devdoc>
/// <para> Prevents controls from sending duplicate blocks of
/// client-side script to the client. Any script blocks with the same <paramref name="key"/> parameter
/// values are considered duplicates.</para>
/// </devdoc>
[Obsolete("The recommended alternative is ClientScript.RegisterClientScriptBlock(Type type, string key, string script). http://go.microsoft.com/fwlink/?linkid=14202")]
[EditorBrowsable(EditorBrowsableState.Advanced)]
public virtual void RegisterClientScriptBlock(string key, string script) {
ClientScript.RegisterClientScriptBlock(typeof(Page), key, script);
}
/// <devdoc>
/// <para>
/// Allows controls to keep duplicate blocks of client-side script code from
/// being sent to the client. Any script blocks with the same <paramref name="key"/> parameter
/// value are considered duplicates.
/// </para>
/// </devdoc>
[Obsolete("The recommended alternative is ClientScript.RegisterStartupScript(Type type, string key, string script). http://go.microsoft.com/fwlink/?linkid=14202")]
[EditorBrowsable(EditorBrowsableState.Advanced)]
public virtual void RegisterStartupScript(string key, string script) {
ClientScript.RegisterStartupScript(typeof(Page), key, script, false);
}
/// <devdoc>
/// <para>Allows a control to access a the client
/// <see langword='onsubmit'/> event.
/// The script should be a function call to client code registered elsewhere.</para>
/// </devdoc>
[Obsolete("The recommended alternative is ClientScript.RegisterOnSubmitStatement(Type type, string key, string script). http://go.microsoft.com/fwlink/?linkid=14202")]
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void RegisterOnSubmitStatement(string key, string script) {
ClientScript.RegisterOnSubmitStatement(typeof(Page), key, script);
}
internal void RegisterEnabledControl(Control control) {
EnabledControls.Add(control);
}
/// <devdoc>
/// <para>If called, Control State for this control will be persisted.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void RegisterRequiresControlState(Control control) {
if (control == null) {
throw new ArgumentException(SR.GetString(SR.Page_ControlState_ControlCannotBeNull));
}
if (control.ControlState == ControlState.PreRendered) {
throw new InvalidOperationException(SR.GetString(SR.Page_MustCallBeforeAndDuringPreRender, "RegisterRequiresControlState"));
}
if (_registeredControlsRequiringControlState == null) {
_registeredControlsRequiringControlState = new ControlSet();
}
// Don't do anything if RegisterRequiresControlState is called multiple times on the same control.
if (!_registeredControlsRequiringControlState.Contains(control)) {
_registeredControlsRequiringControlState.Add(control);
IDictionary controlState = (IDictionary)PageStatePersister.ControlState;
if (controlState != null) {
string uniqueID = control.UniqueID;
// VSWhidbey 422416: We allow control state loaded only once, to
// match the same behavior of ViewState loading in Control.AddedControl
// method which ViewState is removed after applied once. The
// scenario is having a control to be re-parented multiple times.
// Note: We can't call remove here, because we may be in the middle of iterating thru
// the keys of controlState(within in a call to RegisterRequiresClearChildControlState),
// so we just remember that we loaded this control's control state
if (!ControlStateLoadedControlIds.Contains(uniqueID)) {
control.LoadControlStateInternal(controlState[uniqueID]);
ControlStateLoadedControlIds.Add(uniqueID);
}
}
}
}
public bool RequiresControlState(Control control) {
return (_registeredControlsRequiringControlState != null && _registeredControlsRequiringControlState.Contains(control));
}
/// <devdoc>
/// <para>If called, Control State for this control will no longer persisted.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void UnregisterRequiresControlState(Control control) {
if (control == null) {
throw new ArgumentException(SR.GetString(SR.Page_ControlState_ControlCannotBeNull));
}
if (_registeredControlsRequiringControlState == null) {
return;
}
_registeredControlsRequiringControlState.Remove(control);
}
internal bool ShouldLoadControlState(Control control) {
if (_registeredControlsRequiringClearChildControlState == null) return true;
foreach (Control cleared in _registeredControlsRequiringClearChildControlState.Keys) {
if (control != cleared && control.IsDescendentOf(cleared)) return false;
}
return true;
}
internal void RegisterRequiresClearChildControlState(Control control) {
if (_registeredControlsRequiringClearChildControlState == null) {
_registeredControlsRequiringClearChildControlState = new HybridDictionary();
_registeredControlsRequiringClearChildControlState.Add(control, true);
}
else if (_registeredControlsRequiringClearChildControlState[control] == null) {
_registeredControlsRequiringClearChildControlState.Add(control, true);
}
IDictionary controlState = (IDictionary)PageStatePersister.ControlState;
if (controlState != null) {
// Clear out the control state for children of this control
List<string> controlsToClear = new List<string>(controlState.Count);
foreach (string id in controlState.Keys) {
Control controlWithState = FindControl(id);
if (controlWithState != null && controlWithState.IsDescendentOf(control)) {
controlsToClear.Add(id);
}
}
foreach (string id in controlsToClear) {
controlState[id] = null;
}
}
}
/// <devdoc>
/// <para>Registers a control as one that requires postback handling.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void RegisterRequiresPostBack(Control control) {
// Fail if the control is not an IPostBackDataHandler (VSWhidbey 184483)
if (!(control is IPostBackDataHandler)) {
IPostBackDataHandler dataHandler = control.AdapterInternal as IPostBackDataHandler;
if (dataHandler == null)
throw new HttpException(SR.GetString(SR.Ctrl_not_data_handler));
}
if (_registeredControlsThatRequirePostBack == null)
_registeredControlsThatRequirePostBack = new ArrayList();
_registeredControlsThatRequirePostBack.Add(control.UniqueID);
}
// Push a BasePartialCachingControl on the stack of registered caching controls
internal void PushCachingControl(BasePartialCachingControl c) {
// Create the stack on demand
if (_partialCachingControlStack == null) {
_partialCachingControlStack = new Stack();
}
_partialCachingControlStack.Push(c);
}
// Pop a BasePartialCachingControl from the stack of registered caching controls
internal void PopCachingControl() {
Debug.Assert(_partialCachingControlStack != null);
_partialCachingControlStack.Pop();
}
/*
* This method will process the data posted back in the request header.
* The collection of posted data keys consists of three types :
* 1. Fully qualified ids of controls. The associated value is the data
* posted back by the browser for an intrinsic html element.
* 2. Fully qualified ids of controls that have explicitly registered that
* they want to be notified on postback. This is required for intrinsic
* html elements that for some states do not postback data ( e.g. a select
* when there is no selection, a checkbox or radiobutton that is not checked )
* The associated value for these keys is not relevant.
* 3. Framework generated hidden fields for event processing, whose values are
* set by client-side script prior to postback.
*
* This method handles the process of notifying the relevant controls that a postback
* has occurred, via the IPostBackDataHandler interface.
*
* It can potentially be called twice: before and after LoadControl. This is to
* handle the case where users programmatically add controls in Page_Load (ASURT 29045).
*/
private void ProcessPostData(NameValueCollection postData, bool fBeforeLoad) {
if (_changedPostDataConsumers == null)
_changedPostDataConsumers = new ArrayList();
// identify controls that have postback data
if (postData != null) {
foreach (string postKey in postData) {
if (postKey != null) {
// Ignore system post fields
if (IsSystemPostField(postKey))
continue;
Control ctrl = FindControl(postKey);
if (ctrl == null) {
if (fBeforeLoad) {
// It was not found, so keep track of it for the post load attempt
if (_leftoverPostData == null)
_leftoverPostData = new NameValueCollection();
_leftoverPostData.Add(postKey, null);
}
continue;
}
IPostBackDataHandler consumer = ctrl.PostBackDataHandler;
// Ignore controls that are not IPostBackDataHandler (see ASURT 13581)
if (consumer == null) {
// If it's a IPostBackEventHandler (which doesn't implement IPostBackDataHandler),
// register it (ASURT 39040)
if(ctrl.PostBackEventHandler != null)
RegisterRequiresRaiseEvent(ctrl.PostBackEventHandler);
continue;
}
bool changed;
if(consumer != null) {
NameValueCollection postCollection = ctrl.CalculateEffectiveValidateRequest() ? _requestValueCollection : _unvalidatedRequestValueCollection;
changed = consumer.LoadPostData(postKey, postCollection);
if(changed)
_changedPostDataConsumers.Add(ctrl);
}
// ensure controls are only notified of postback once
if (_controlsRequiringPostBack != null)
_controlsRequiringPostBack.Remove(postKey);
}
}
}
// Keep track of the leftover for the post-load attempt
ArrayList leftOverControlsRequiringPostBack = null;
// process controls that explicitly registered to be notified of postback
if (_controlsRequiringPostBack != null) {
foreach (string controlID in _controlsRequiringPostBack) {
Control c = FindControl(controlID);
if (c != null) {
IPostBackDataHandler consumer = c.AdapterInternal as IPostBackDataHandler;
if(consumer == null) {
consumer = c as IPostBackDataHandler;
}
// Give a helpful error if the control is not a IPostBackDataHandler (ASURT 128532)
if (consumer == null) {
throw new HttpException(SR.GetString(SR.Postback_ctrl_not_found, controlID));
}
NameValueCollection postCollection = c.CalculateEffectiveValidateRequest() ? _requestValueCollection : _unvalidatedRequestValueCollection;
bool changed = consumer.LoadPostData(controlID, postCollection);
if (changed)
_changedPostDataConsumers.Add(c);
}
else {
if (fBeforeLoad) {
if (leftOverControlsRequiringPostBack == null)
leftOverControlsRequiringPostBack = new ArrayList();
leftOverControlsRequiringPostBack.Add(controlID);
}
}
}
_controlsRequiringPostBack = leftOverControlsRequiringPostBack;
}
}
// Operations like FindControl and LoadPostData call EnsureDataBound, which may fire up
// async model binding methods. Therefore we make ProcessPostData method to be async so that we can await
// async data bindings.
// The differences between ProcessPostData and ProcessPostDataAsync are:
// 1. ProcessPostDataAsync awaits GetWaitForPreviousStepCompletionAwaitable after FindControl();
// 2. ProcessPostDataAsync calls LoadPostDataAsync() instead of LoadPostData().
private async Task ProcessPostDataAsync(NameValueCollection postData, bool fBeforeLoad) {
if (_changedPostDataConsumers == null)
_changedPostDataConsumers = new ArrayList();
// identify controls that have postback data
if (postData != null) {
foreach (string postKey in postData) {
if (postKey != null) {
// Ignore system post fields
if (IsSystemPostField(postKey))
continue;
Control ctrl = null;
using (Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
ctrl = FindControl(postKey);
await GetWaitForPreviousStepCompletionAwaitable();
}
if (ctrl == null) {
if (fBeforeLoad) {
// It was not found, so keep track of it for the post load attempt
if (_leftoverPostData == null)
_leftoverPostData = new NameValueCollection();
_leftoverPostData.Add(postKey, null);
}
continue;
}
IPostBackDataHandler consumer = ctrl.PostBackDataHandler;
// Ignore controls that are not IPostBackDataHandler (see ASURT 13581)
if (consumer == null) {
// If it's a IPostBackEventHandler (which doesn't implement IPostBackDataHandler),
// register it (ASURT 39040)
if (ctrl.PostBackEventHandler != null)
RegisterRequiresRaiseEvent(ctrl.PostBackEventHandler);
continue;
}
if (consumer != null) {
NameValueCollection postCollection = ctrl.CalculateEffectiveValidateRequest() ? _requestValueCollection : _unvalidatedRequestValueCollection;
bool changed = await LoadPostDataAsync(consumer, postKey, postCollection);
if (changed)
_changedPostDataConsumers.Add(ctrl);
}
// ensure controls are only notified of postback once
if (_controlsRequiringPostBack != null)
_controlsRequiringPostBack.Remove(postKey);
}
}
}
// Keep track of the leftover for the post-load attempt
ArrayList leftOverControlsRequiringPostBack = null;
// process controls that explicitly registered to be notified of postback
if (_controlsRequiringPostBack != null) {
foreach (string controlID in _controlsRequiringPostBack) {
Control c = null;
using (Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
c = FindControl(controlID);
await GetWaitForPreviousStepCompletionAwaitable();
}
if (c != null) {
IPostBackDataHandler consumer = c.AdapterInternal as IPostBackDataHandler;
if (consumer == null) {
consumer = c as IPostBackDataHandler;
}
// Give a helpful error if the control is not a IPostBackDataHandler (ASURT 128532)
if (consumer == null) {
throw new HttpException(SR.GetString(SR.Postback_ctrl_not_found, controlID));
}
NameValueCollection postCollection = c.CalculateEffectiveValidateRequest() ? _requestValueCollection : _unvalidatedRequestValueCollection;
bool changed = await LoadPostDataAsync(consumer, controlID, postCollection);
if (changed)
_changedPostDataConsumers.Add(c);
}
else {
if (fBeforeLoad) {
if (leftOverControlsRequiringPostBack == null)
leftOverControlsRequiringPostBack = new ArrayList();
leftOverControlsRequiringPostBack.Add(controlID);
}
}
}
_controlsRequiringPostBack = leftOverControlsRequiringPostBack;
}
}
private async Task<bool> LoadPostDataAsync(IPostBackDataHandler consumer, string postKey, NameValueCollection postCollection) {
bool changed;
// ListControl family controls call EnsureDataBound in consumer.LoadPostData, which could be an async call in 4.6.
// LoadPostData, however, is a sync method, which means we cannot await EnsureDataBound in the method.
// To workaround this, for ListControl family controls, we call EnsureDataBound before we call into LoadPostData.
if (AppSettings.EnableAsyncModelBinding && consumer is ListControl) {
var listControl = consumer as ListControl;
listControl.SkipEnsureDataBoundInLoadPostData = true;
using (Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
listControl.InternalEnsureDataBound();
await GetWaitForPreviousStepCompletionAwaitable();
}
}
changed = consumer.LoadPostData(postKey, postCollection);
return changed;
}
/*
* This method will raise change events for those controls that indicated
* during PostProcessData that their data has changed.
*/
// !! IMPORTANT !!
// If you change this method, also change RaiseChangedEventsAsync.
internal void RaiseChangedEvents() {
if (_changedPostDataConsumers != null) {
// fire change notifications for those controls that changed as a result of postback
for (int i=0; i < _changedPostDataConsumers.Count; i++) {
Control c = (Control)_changedPostDataConsumers[i];
IPostBackDataHandler changedPostDataConsumer;
if(c != null) {
changedPostDataConsumer = c.PostBackDataHandler;
}
else {
continue;
}
// Make sure the IPostBackDataHandler is still in the tree (ASURT 82495)
if (c != null && !c.IsDescendentOf(this))
continue;
if(c != null && c.PostBackDataHandler != null) {
changedPostDataConsumer.RaisePostDataChangedEvent();
}
}
}
}
// TAP version of RaiseChangedEvents.
// !! IMPORTANT !!
// If you change this method, also change RaiseChangedEvents.
internal async Task RaiseChangedEventsAsync() {
if (_changedPostDataConsumers != null) {
// fire change notifications for those controls that changed as a result of postback
for (int i = 0; i < _changedPostDataConsumers.Count; i++) {
Control c = (Control)_changedPostDataConsumers[i];
IPostBackDataHandler changedPostDataConsumer;
if (c != null) {
changedPostDataConsumer = c.PostBackDataHandler;
}
else {
continue;
}
// Make sure the IPostBackDataHandler is still in the tree (ASURT 82495)
if (c != null && !c.IsDescendentOf(this))
continue;
if (c != null && c.PostBackDataHandler != null) {
using (Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
changedPostDataConsumer.RaisePostDataChangedEvent();
await GetWaitForPreviousStepCompletionAwaitable();
}
}
}
}
}
private void RaisePostBackEvent(NameValueCollection postData) {
// first check if there is a register control needing the postback event
// if we don't have one of those, fall back to the hidden field
// Note: this must happen before we look at postData[postEventArgumentID] (ASURT 50106)
if (_registeredControlThatRequireRaiseEvent != null) {
RaisePostBackEvent(_registeredControlThatRequireRaiseEvent, null);
}
else {
string eventSource = postData[postEventSourceID];
bool hasEventSource = (!String.IsNullOrEmpty(eventSource));
// VSWhidbey 204824: We also need to check if the postback is submitted
// by an autopostback control in mobile browsers which cannot set
// event target in markup
if (hasEventSource || AutoPostBackControl != null) {
Control sourceControl = null;
if (hasEventSource) {
sourceControl = FindControl(eventSource);
}
if (sourceControl != null && sourceControl.PostBackEventHandler != null) {
string eventArgument = postData[postEventArgumentID];
RaisePostBackEvent((sourceControl.PostBackEventHandler), eventArgument);
}
}
else {
Validate();
}
}
}
// Overridable method that just calls RaisePostBackEvent on controls (ASURT 48154)
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected virtual void RaisePostBackEvent(IPostBackEventHandler sourceControl, string eventArgument) {
sourceControl.RaisePostBackEvent(eventArgument);
}
//
/// <devdoc>
/// <para>Registers a control as requiring an event to be raised when it is processed
/// on the page.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public virtual void RegisterRequiresRaiseEvent(IPostBackEventHandler control) {
_registeredControlThatRequireRaiseEvent = control;
}
// VSWhidbey 402530
// This property should be public. (DevDiv Bugs 161340)
public bool IsPostBackEventControlRegistered {
get {
return (_registeredControlThatRequireRaiseEvent != null);
}
}
/// <devdoc>
/// <para> Indicates whether page validation succeeded.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public bool IsValid {
get {
if (!_validated)
throw new HttpException(SR.GetString(SR.IsValid_Cant_Be_Called));
if (_validators != null) {
ValidatorCollection vc = Validators;
int count = vc.Count;
for (int i = 0; i < count; i++) {
if (!vc[i].IsValid) {
return false;
}
}
}
return true;
}
}
/// <devdoc>
/// <para>Gets a collection of all validation controls contained on the requested page.</para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public ValidatorCollection Validators {
get {
if (_validators == null) {
_validators = new ValidatorCollection();
}
return _validators;
}
}
/// <devdoc>
/// <para>Gets the PreviousPage of current Page, it could be either the original Page from
/// Server.Transfer or cross page posting.
/// </para>
/// </devdoc>
[
Browsable(false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)
]
public Page PreviousPage {
get {
// check _previousPage first since _previousPagePath could be null in case of Server.Transfer
if (_previousPage == null) {
if (_previousPagePath != null) {
if (!Util.IsUserAllowedToPath(Context, _previousPagePath)) {
throw new InvalidOperationException(SR.GetString(SR.Previous_Page_Not_Authorized));
}
ITypedWebObjectFactory result =
(ITypedWebObjectFactory)BuildManager.GetVPathBuildResult(Context, _previousPagePath);
// Make sure it has the correct base type
if (typeof(Page).IsAssignableFrom(result.InstantiatedType)) {
_previousPage = (Page)result.CreateInstance();
_previousPage._isCrossPagePostBack = true;
Server.Execute(_previousPage, TextWriter.Null,
true /*preserveForm*/, false /*setPreviousPage*/);
}
}
}
return _previousPage;
}
}
/*
* Map virtual path (absolute or relative) to physical path
*/
/// <devdoc>
/// <para>Assigns a virtual path, either absolute or relative, to a physical path.</para>
/// </devdoc>
public string MapPath(string virtualPath) {
return _request.MapPath(VirtualPath.CreateAllowNull(virtualPath), TemplateControlVirtualDirectory,
true/*allowCrossAppMapping*/);
}
/*
* The following members should only be set by derived class through codegen.
*
*/
static char[] s_varySeparator = new char[] {';'};
/// <devdoc>
/// <para>[To be supplied.]</para>
/// Note: this methods needs to be virtual because the Mobile control team
/// overrides it (ASURT 66157)
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual void InitOutputCache(int duration, string varyByHeader,
string varyByCustom, OutputCacheLocation location, string varyByParam) {
InitOutputCache(duration, null, varyByHeader, varyByCustom, location, varyByParam);
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// Note: this methods needs to be virtual because the Mobile control team
/// overrides it (ASURT 66157)
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Never)]
protected virtual void InitOutputCache(int duration, string varyByContentEncoding, string varyByHeader,
string varyByCustom, OutputCacheLocation location, string varyByParam) {
// DevDivBugs 18348: for a cross-page postback, use cache policy for
// original page and ignore cache policy for this page.
if (_isCrossPagePostBack) {
return;
}
OutputCacheParameters cacheSettings = new OutputCacheParameters();
cacheSettings.Duration = duration;
cacheSettings.VaryByContentEncoding = varyByContentEncoding;
cacheSettings.VaryByHeader = varyByHeader;
cacheSettings.VaryByCustom = varyByCustom;
cacheSettings.Location = location;
cacheSettings.VaryByParam = varyByParam;
InitOutputCache(cacheSettings);
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// Note: this methods needs to be virtual because the Mobile control team
/// overrides it (ASURT 66157)
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Never)]
protected internal virtual void InitOutputCache(OutputCacheParameters cacheSettings)
{
// DevDivBugs 18348: for a cross-page postback, use cache policy for
// original page and ignore cache policy for this page.
if (_isCrossPagePostBack) {
return;
}
OutputCacheSettingsSection outputCacheSettings;
OutputCacheProfile profile = null;
HttpCachePolicy cache = Response.Cache;
HttpCacheability cacheability;
OutputCacheLocation location = (OutputCacheLocation) (-1);
int duration = 0;
string varyByContentEncoding = null;
string varyByHeader = null;
string varyByCustom = null;
string varyByParam = null;
string sqlDependency = null;
string varyByControl = null;
bool noStore = false;
RuntimeConfig config;
config = RuntimeConfig.GetAppConfig();
OutputCacheSection outputCacheConfig = config.OutputCache;
// If output cache is not enabled, then don't do anything and return.
if (! outputCacheConfig.EnableOutputCache)
{
return;
}
if (cacheSettings.CacheProfile != null && cacheSettings.CacheProfile.Length != 0)
{
outputCacheSettings = config.OutputCacheSettings;
profile = (OutputCacheProfile) outputCacheSettings.OutputCacheProfiles[cacheSettings.CacheProfile];
if (profile == null) {
throw new HttpException(SR.GetString(SR.CacheProfile_Not_Found, cacheSettings.CacheProfile));
}
// If the profile disables it, then bail out
if (!profile.Enabled) {
return;
}
}
// If a cache profile was set above, the settings below will override the set defaults from config
// Pick up the settings from the configuration settings profile first
if (profile != null) {
duration = profile.Duration;
varyByContentEncoding = profile.VaryByContentEncoding;
varyByHeader = profile.VaryByHeader;
varyByCustom = profile.VaryByCustom;
varyByParam = profile.VaryByParam;
sqlDependency = profile.SqlDependency;
noStore = profile.NoStore;
varyByControl = profile.VaryByControl;
location = profile.Location;
if (String.IsNullOrEmpty(varyByContentEncoding)) {
varyByContentEncoding = null;
}
if (String.IsNullOrEmpty(varyByHeader)) {
varyByHeader = null;
}
if (String.IsNullOrEmpty(varyByCustom)) {
varyByCustom = null;
}
if (String.IsNullOrEmpty(varyByParam)) {
varyByParam = null;
}
if (String.IsNullOrEmpty(varyByControl)) {
varyByControl = null;
}
if (StringUtil.EqualsIgnoreCase(varyByParam, "none")) {
varyByParam = null;
}
if (StringUtil.EqualsIgnoreCase(varyByControl, "none")) {
varyByControl = null;
}
}
// Start overriding options from the directive
if (cacheSettings.IsParameterSet(OutputCacheParameter.Duration)) {
duration = cacheSettings.Duration;
}
if (cacheSettings.IsParameterSet(OutputCacheParameter.VaryByContentEncoding)) {
varyByContentEncoding = cacheSettings.VaryByContentEncoding;
}
if (cacheSettings.IsParameterSet(OutputCacheParameter.VaryByHeader)) {
varyByHeader = cacheSettings.VaryByHeader;
}
if (cacheSettings.IsParameterSet(OutputCacheParameter.VaryByCustom)) {
varyByCustom = cacheSettings.VaryByCustom;
}
if (cacheSettings.IsParameterSet(OutputCacheParameter.VaryByControl)) {
varyByControl = cacheSettings.VaryByControl;
}
if (cacheSettings.IsParameterSet(OutputCacheParameter.VaryByParam)) {
varyByParam = cacheSettings.VaryByParam;
}
if (cacheSettings.IsParameterSet(OutputCacheParameter.SqlDependency)) {
sqlDependency = cacheSettings.SqlDependency;
}
if (cacheSettings.IsParameterSet(OutputCacheParameter.NoStore)) {
noStore = cacheSettings.NoStore;
}
if (cacheSettings.IsParameterSet(OutputCacheParameter.Location)) {
location = cacheSettings.Location;
}
//
// Make some checks here and see if a configuration exception needs to be thrown:
// If location wasn't specified in the profile or in the directive, set a default one
if (location == (OutputCacheLocation) (-1)) {
location = OutputCacheLocation.Any;
}
// Skip all checks if Location is "None" or we are disabled
if ((location != OutputCacheLocation.None) &&
(profile == null || profile.Enabled)) {
// Check and see if duration is specified in the profile or in the directives
if ((profile == null || profile.Duration == -1) &&
(cacheSettings.IsParameterSet(OutputCacheParameter.Duration) == false)) {
throw new HttpException(SR.GetString(SR.Missing_output_cache_attr, "duration"));
}
// Check and see if varyByParam is specified in the profile or in the directives
if ((profile == null || ((profile.VaryByParam == null) && (profile.VaryByControl == null))) &&
(cacheSettings.IsParameterSet(OutputCacheParameter.VaryByParam) == false &&
cacheSettings.IsParameterSet(OutputCacheParameter.VaryByControl) == false)) {
throw new HttpException(SR.GetString(SR.Missing_output_cache_attr, "varyByParam"));
}
}
// Set the cache policy based upon these settings
if (noStore) {
Response.Cache.SetNoStore();
}
switch (location) {
case OutputCacheLocation.Any:
cacheability = HttpCacheability.Public;
break;
case OutputCacheLocation.Server:
cacheability = HttpCacheability.ServerAndNoCache;
break;
case OutputCacheLocation.ServerAndClient:
cacheability = HttpCacheability.ServerAndPrivate;
break;
case OutputCacheLocation.Client:
cacheability = HttpCacheability.Private;
break;
case OutputCacheLocation.Downstream:
cacheability = HttpCacheability.Public;
cache.SetNoServerCaching();
break;
case OutputCacheLocation.None:
cacheability = HttpCacheability.NoCache;
break;
default:
throw new ArgumentOutOfRangeException("cacheSettings", SR.GetString(SR.Invalid_cache_settings_location));
}
cache.SetCacheability(cacheability);
if (location != OutputCacheLocation.None) {
cache.SetExpires(Context.Timestamp.AddSeconds(duration));
cache.SetMaxAge(new TimeSpan(0, 0, duration));
cache.SetValidUntilExpires(true);
cache.SetLastModified(Context.Timestamp);
//
// A client cache'd item won't be cached on
// the server or a proxy, so it doesn't need
// a Varies header.
//
if (location != OutputCacheLocation.Client) {
if (varyByContentEncoding != null) {
string[] a = varyByContentEncoding.Split(s_varySeparator);
foreach (string s in a) {
cache.VaryByContentEncodings[s.Trim()] = true;
}
}
if (varyByHeader != null) {
string[] a = varyByHeader.Split(s_varySeparator);
foreach (string s in a) {
cache.VaryByHeaders[s.Trim()] = true;
}
}
if(PageAdapter != null) {
StringCollection adapterVaryByHeaders = PageAdapter.CacheVaryByHeaders;
if(adapterVaryByHeaders != null) {
foreach(string header in adapterVaryByHeaders) {
cache.VaryByHeaders[header] = true;
}
}
}
//
// Only items cached on the server need VaryByCustom and
// VaryByParam
//
if (location != OutputCacheLocation.Downstream) {
if (varyByCustom != null) {
cache.SetVaryByCustom(varyByCustom);
}
if (String.IsNullOrEmpty(varyByParam) &&
String.IsNullOrEmpty(varyByControl) &&
(PageAdapter == null || PageAdapter.CacheVaryByParams == null)) {
cache.VaryByParams.IgnoreParams = true;
}
else {
if (!String.IsNullOrEmpty(varyByParam)) {
string[] a = varyByParam.Split(s_varySeparator);
foreach (string s in a) {
cache.VaryByParams[s.Trim()] = true;
}
}
if (!String.IsNullOrEmpty(varyByControl)) {
string[] a = varyByControl.Split(s_varySeparator);
foreach (string s in a) {
cache.VaryByParams[s.Trim()] = true;
}
}
if(PageAdapter != null) {
IList adapterVaryByParams = PageAdapter.CacheVaryByParams;
if(adapterVaryByParams != null) {
foreach(string p in adapterVaryByParams) {
cache.VaryByParams[p] = true;
}
}
}
}
#if !FEATURE_PAL // FEATURE_PAL does not fully SQL dependencies
if (!String.IsNullOrEmpty(sqlDependency)) {
Response.AddCacheDependency(SqlCacheDependency.CreateOutputCacheDependency(sqlDependency));
}
#endif // !FEATURE_PAL
}
}
}
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("The recommended alternative is HttpResponse.AddFileDependencies. http://go.microsoft.com/fwlink/?linkid=14202")]
protected ArrayList FileDependencies {
set { Response.AddFileDependencies(value); }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected object GetWrappedFileDependencies(string[] virtualFileDependencies) {
Debug.Assert(virtualFileDependencies != null);
return virtualFileDependencies;
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected internal void AddWrappedFileDependencies(object virtualFileDependencies) {
Response.AddVirtualPathDependencies((string[])virtualFileDependencies);
}
internal const bool BufferDefault = true;
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool Buffer {
set { Response.BufferOutput = value; }
get { return Response.BufferOutput; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string ContentType {
set { Response.ContentType = value; }
get { return Response.ContentType; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int CodePage {
set { Response.ContentEncoding = Encoding.GetEncoding(value); }
get { return Response.ContentEncoding.CodePage; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string ResponseEncoding {
set { Response.ContentEncoding = Encoding.GetEncoding(value); }
get { return Response.ContentEncoding.EncodingName; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string Culture {
set {
CultureInfo newCulture = null;
if(StringUtil.EqualsIgnoreCase(value, HttpApplication.AutoCulture)) {
CultureInfo browserCulture = CultureFromUserLanguages(true);
if(browserCulture != null) {
newCulture = browserCulture;
}
}
else if(StringUtil.StringStartsWithIgnoreCase(value, HttpApplication.AutoCulture)) {
CultureInfo browserCulture = CultureFromUserLanguages(true);
if(browserCulture != null) {
newCulture = browserCulture;
}
else {
try {
newCulture = HttpServerUtility.CreateReadOnlyCultureInfo(value.Substring(5));
}
catch {}
}
}
else {
newCulture = HttpServerUtility.CreateReadOnlyCultureInfo(value);
}
if (newCulture != null) {
Thread.CurrentThread.CurrentCulture = newCulture;
_dynamicCulture = newCulture;
}
}
get { return Thread.CurrentThread.CurrentCulture.DisplayName; }
}
internal CultureInfo DynamicCulture {
get { return _dynamicCulture; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int LCID {
set {
CultureInfo newCulture = HttpServerUtility.CreateReadOnlyCultureInfo(value);
Thread.CurrentThread.CurrentCulture = newCulture;
_dynamicCulture = newCulture;
}
get { return Thread.CurrentThread.CurrentCulture.LCID; }
}
private CultureInfo CultureFromUserLanguages(bool specific) {
if(_context != null &&
_context.Request != null &&
_context.Request.UserLanguages != null) {
try {
return CultureUtil.CreateReadOnlyCulture(_context.Request.UserLanguages, specific);
}
catch {
}
}
return null;
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public string UICulture {
set {
CultureInfo newUICulture = null;
if(StringUtil.EqualsIgnoreCase(value, HttpApplication.AutoCulture)) {
CultureInfo browserCulture = CultureFromUserLanguages(false);
if(browserCulture != null) {
newUICulture = browserCulture;
}
}
else if(StringUtil.StringStartsWithIgnoreCase(value, HttpApplication.AutoCulture)) {
CultureInfo browserCulture = CultureFromUserLanguages(false);
if(browserCulture != null) {
newUICulture = browserCulture;
}
else {
try {
newUICulture = HttpServerUtility.CreateReadOnlyCultureInfo(value.Substring(5));
}
catch {}
}
}
else {
newUICulture = HttpServerUtility.CreateReadOnlyCultureInfo(value);
}
if (newUICulture != null) {
Thread.CurrentThread.CurrentUICulture = newUICulture;
_dynamicUICulture = newUICulture;
}
}
get { return Thread.CurrentThread.CurrentUICulture.DisplayName; }
}
internal CultureInfo DynamicUICulture {
get { return _dynamicUICulture; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Advanced)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public TimeSpan AsyncTimeout {
set {
if (value < TimeSpan.Zero) {
throw new ArgumentException(SR.GetString(SR.Page_Illegal_AsyncTimeout), "AsyncTimeout");
}
_asyncTimeout = value;
_asyncTimeoutSet = true;
}
get {
if (!_asyncTimeoutSet) {
if (Context != null) {
PagesSection pagesSection = RuntimeConfig.GetConfig(Context).Pages;
if (pagesSection != null) {
AsyncTimeout = pagesSection.AsyncTimeout;
}
}
if (!_asyncTimeoutSet) {
AsyncTimeout = TimeSpan.FromSeconds((double)Page.DefaultAsyncTimeoutSeconds);
}
}
return _asyncTimeout;
}
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected int TransactionMode {
set { _transactionMode = value; }
get { return _transactionMode; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected bool AspCompatMode {
set { _aspCompatMode = value; }
get { return _aspCompatMode; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected bool AsyncMode {
set { _asyncMode = value; }
get { return _asyncMode; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool TraceEnabled {
set { Trace.IsEnabled = value; }
get { return Trace.IsEnabled; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public System.Web.TraceMode TraceModeValue {
set { Trace.TraceMode = value; }
get { return Trace.TraceMode; }
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool EnableViewStateMac {
get { return _enableViewStateMac; }
set {
// DevDiv #461378: EnableViewStateMac=false can lead to remote code execution, so we
// have an mechanism that forces this to keep its default value of 'true'. We only
// allow actually setting the value if this enforcement mechanism is inactive.
if (!EnableViewStateMacRegistryHelper.EnforceViewStateMac) {
_enableViewStateMac = value;
}
}
}
internal const bool SmartNavigationDefault = false;
/// <devdoc>
/// <para>Is the SmartNavigation feature in use</para>
/// </devdoc>
[
Browsable(false),
Filterable(false)
]
[Obsolete("The recommended alternative is Page.SetFocus and Page.MaintainScrollPositionOnPostBack. http://go.microsoft.com/fwlink/?linkid=14202")]
public bool SmartNavigation {
get {
// If it's not supported or asked for, return false
if (_smartNavSupport == SmartNavigationSupport.NotDesiredOrSupported)
return false;
// Otherwise, determine what the browser supports
if (_smartNavSupport == SmartNavigationSupport.Desired) {
// *** We need to check the current context here since
// we check SmartNavigation when the context == null.
HttpContext currentContext = HttpContext.Current;
// Make sure that there is a current context
if (currentContext == null) {
// If there isn't one, assume SmartNavigation is off
return false;
}
// *** We CANNOT just check Request.Browser since Request will be null and throw an exception
HttpBrowserCapabilities browser = currentContext.Request.Browser;
// If it's not IE6+ on Windows, we don't support Smart Navigation
if (!String.Equals(browser.Browser, "ie", StringComparison.OrdinalIgnoreCase) || browser.MajorVersion < 6 ||
!browser.Win32) {
_smartNavSupport = SmartNavigationSupport.NotDesiredOrSupported;
}
else
_smartNavSupport = SmartNavigationSupport.IE6OrNewer;
}
return (_smartNavSupport != SmartNavigationSupport.NotDesiredOrSupported);
}
set {
if (value)
_smartNavSupport = SmartNavigationSupport.Desired;
else
_smartNavSupport = SmartNavigationSupport.NotDesiredOrSupported;
}
}
internal bool IsTransacted { get { return (_transactionMode != 0 /*TransactionOption.Disabled*/); } }
internal bool IsInAspCompatMode { get { return _aspCompatMode; } }
public bool IsAsync {
get { return _asyncMode; }
}
/// <devdoc>
/// Occurs when the control is done handling postback data, and before PreRender.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public event EventHandler LoadComplete {
add {
Events.AddHandler(EventLoadComplete, value);
}
remove {
Events.RemoveHandler(EventLoadComplete, value);
}
}
/// <devdoc>
/// Raised after postback data is handled, and before PreRender.
/// </devdoc>
protected virtual void OnLoadComplete(EventArgs e) {
EventHandler handler = (EventHandler)Events[EventLoadComplete];
if (handler != null) {
handler(this, e);
}
}
/// <devdoc>
/// Raised after PreRender is complete
/// </devdoc>
protected virtual void OnPreRenderComplete(EventArgs e) {
EventHandler handler = (EventHandler)Events[EventPreRenderComplete];
if (handler != null) {
handler(this, e);
}
}
/// <devdoc>
/// Heres where all the 'final' page-level framework stuff happens.
/// Raise the PreRenderComplete event giving the user the first (and last)
/// chance to do certain things that affect page behavior, and
/// then perform the processing steps.
/// </devdoc>
private void PerformPreRenderComplete() {
OnPreRenderComplete(EventArgs.Empty);
}
/// <devdoc>
/// Occurs before controls' OnInit
/// </devdoc>
public event EventHandler PreInit {
add {
Events.AddHandler(EventPreInit, value);
}
remove {
Events.RemoveHandler(EventPreInit, value);
}
}
/// <devdoc>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public event EventHandler PreLoad {
add {
Events.AddHandler(EventPreLoad, value);
}
remove {
Events.RemoveHandler(EventPreLoad, value);
}
}
/// <devdoc>
/// Occurs after all controls have completed PreRender
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public event EventHandler PreRenderComplete {
add {
Events.AddHandler(EventPreRenderComplete, value);
}
remove {
Events.RemoveHandler(EventPreRenderComplete, value);
}
}
/// <devdoc>
/// Override this method to apply stylesheet before building controls
/// </devdoc>
protected override void FrameworkInitialize() {
base.FrameworkInitialize();
InitializeStyleSheet();
}
/// <devdoc>
/// Override this method to initialize culture properties.
/// </devdoc>
protected virtual void InitializeCulture() {
}
/// <devdoc>
/// </devdoc>
protected internal override void OnInit(EventArgs e) {
base.OnInit(e);
if (_theme != null) {
_theme.SetStyleSheet();
}
if (_styleSheet != null) {
_styleSheet.SetStyleSheet();
}
}
/// <devdoc>
/// Raised before OnInit.
/// </devdoc>
protected virtual void OnPreInit(EventArgs e) {
EventHandler handler = (EventHandler)Events[EventPreInit];
if (handler != null) {
handler(this, e);
}
}
/// <devdoc>
/// Heres where all the 'early' page initialization happens.
/// Raise the PreInit event giving the user the first (and last)
/// chance to do certain things that affect page behavior, and
/// then perform the initialization steps.
///
/// For now this early initialization includes
/// theme loading.
///
private void PerformPreInit() {
OnPreInit(EventArgs.Empty);
InitializeThemes();
ApplyMasterPage();
_preInitWorkComplete = true;
}
// TAP version of the PerformPreInit routine.
// !! IMPORTANT !!
// If you change this method, also change PerformPreInit.
private async Task PerformPreInitAsync() {
using (Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
OnPreInit(EventArgs.Empty);
await GetWaitForPreviousStepCompletionAwaitable();
}
InitializeThemes();
ApplyMasterPage();
_preInitWorkComplete = true;
}
/// <devdoc>
/// Occurs when the page is done initializing, and before loading viewstate data.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public event EventHandler InitComplete {
add {
Events.AddHandler(EventInitComplete, value);
}
remove {
Events.RemoveHandler(EventInitComplete, value);
}
}
/// <devdoc>
/// Raised after page is initialized, and before loading viewstate.
/// </devdoc>
protected virtual void OnInitComplete(EventArgs e) {
EventHandler handler = (EventHandler)Events[EventInitComplete];
if (handler != null) {
handler(this, e);
}
}
/// <devdoc>
/// Raises the PreLoad event
/// </devdoc>
protected virtual void OnPreLoad(EventArgs e) {
EventHandler handler = (EventHandler)Events[EventPreLoad];
if (handler != null) {
handler(this, e);
}
}
public void RegisterRequiresViewStateEncryption() {
if (ControlState >= ControlState.PreRendered) {
throw new InvalidOperationException(SR.GetString(SR.Too_late_for_RegisterRequiresViewStateEncryption));
}
_viewStateEncryptionRequested = true;
}
internal bool RequiresViewStateEncryptionInternal {
get {
return ViewStateEncryptionMode == ViewStateEncryptionMode.Always ||
_viewStateEncryptionRequested && ViewStateEncryptionMode == ViewStateEncryptionMode.Auto;
}
}
/// <devdoc>
/// Occurs when the page has completed saving view state and control state.
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public event EventHandler SaveStateComplete {
add {
Events.AddHandler(EventSaveStateComplete, value);
}
remove {
Events.RemoveHandler(EventSaveStateComplete, value);
}
}
/// <devdoc>
/// Raises the SaveStateComplete event
/// </devdoc>
protected virtual void OnSaveStateComplete(EventArgs e) {
EventHandler handler = (EventHandler)Events[EventSaveStateComplete];
if (handler != null) {
handler(this, e);
}
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
public virtual void ProcessRequest(HttpContext context) {
// If running in non-full trust, call PermitOnly to cause the following code
// to run as if there were user code on the stack.
// Check if we're running in non-full trust
if (HttpRuntime.NamedPermissionSet != null && !HttpRuntime.DisableProcessRequestInApplicationTrust) {
// Are we supposed to execute process request without full trust?
if (HttpRuntime.ProcessRequestInApplicationTrust) {
// If so, we don't normally need to do anything, because this ProcessRequest method
// is being called from an override in the generated code (so there is user code
// on the stack).
// However, if the page is no-compile, there won't be any user code on the stack,
// so we need to explicitely call PermitOnly to make it happen
if (NoCompile) {
HttpRuntime.NamedPermissionSet.PermitOnly();
}
}
else {
// Here, we want to run the request in full trust, so the situation is reversed.
// i.e. in the no-compile case, there is no user code on the stack, so we don't need to
// do anything. But in the compiled case, the ProcessRequest override is on the stack,
// so we need to nullify it using an Assert.
ProcessRequestWithAssert(context);
return;
}
}
ProcessRequestWithNoAssert(context);
}
[PermissionSet(SecurityAction.Assert, Unrestricted = true)]
private void ProcessRequestWithAssert(HttpContext context) {
ProcessRequestWithNoAssert(context);
}
private void ProcessRequestWithNoAssert(HttpContext context) {
SetIntrinsics(context);
ProcessRequest();
}
// assert SecurityPermission, for ASURT #112116
[SecurityPermission(SecurityAction.Assert, ControlThread=true)]
void SetCultureWithAssert(Thread currentThread, CultureInfo currentCulture, CultureInfo currentUICulture) {
SetCulture(currentThread, currentCulture, currentUICulture);
}
void SetCulture(Thread currentThread, CultureInfo currentCulture, CultureInfo currentUICulture) {
currentThread.CurrentCulture = currentCulture;
currentThread.CurrentUICulture = currentUICulture;
}
//
// ProcessRequestXXX methods are there because
// transacted pages require some code (ProcessRequestMain)
// to run inside the transaction and some outside
//
// Another reason - support for async pages
//
private void ProcessRequest() {
// culture needs to be saved/restored only on synchronous pages (if at all)
// save culture
Thread currentThread = Thread.CurrentThread;
CultureInfo prevCulture = currentThread.CurrentCulture;
CultureInfo prevUICulture = currentThread.CurrentUICulture;
try {
ProcessRequest(true /*includeStagesBeforeAsyncPoint*/, true /*includeStagesAfterAsyncPoint*/);
}
finally {
// restore culture
RestoreCultures(currentThread, prevCulture, prevUICulture);
}
}
// !! IMPORTANT !!
// If you change this method, also change ProcessRequestAsync(bool, bool).
private void ProcessRequest(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) {
// Initialize the object and build the tree of controls.
// This must happen *after* the intrinsics have been set.
// On async pages only call Initialize once (ProcessRequest is called twice)
if (includeStagesBeforeAsyncPoint) {
FrameworkInitialize();
this.ControlState = ControlState.FrameworkInitialized;
}
bool needToCallEndTrace = Context.WorkerRequest is IIS7WorkerRequest;
try {
try {
if (IsTransacted) {
ProcessRequestTransacted();
}
else {
// No transactions
ProcessRequestMain(includeStagesBeforeAsyncPoint, includeStagesAfterAsyncPoint);
}
if (includeStagesAfterAsyncPoint) {
needToCallEndTrace = false;
ProcessRequestEndTrace();
}
}
catch (ThreadAbortException) {
try {
if (needToCallEndTrace)
ProcessRequestEndTrace();
} catch {}
}
finally {
if (includeStagesAfterAsyncPoint) {
ProcessRequestCleanup();
}
}
}
catch { throw; } // Prevent Exception Filter Security Issue (ASURT 122835)
}
// TAP version of ProcessRequest(bool, bool)
// !! IMPORTANT !!
// If you change this method, also change ProcessRequest(bool, bool).
private async Task ProcessRequestAsync(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) {
// Initialize the object and build the tree of controls.
// This must happen *after* the intrinsics have been set.
// On async pages only call Initialize once (ProcessRequest is called twice)
if (includeStagesBeforeAsyncPoint) {
FrameworkInitialize();
this.ControlState = ControlState.FrameworkInitialized;
}
bool needToCallEndTrace = Context.WorkerRequest is IIS7WorkerRequest;
try {
try {
if (IsTransacted) {
ProcessRequestTransacted();
}
else {
// No transactions
await ProcessRequestMainAsync(includeStagesBeforeAsyncPoint, includeStagesAfterAsyncPoint).WithinCancellableCallback(Context);
}
if (includeStagesAfterAsyncPoint) {
needToCallEndTrace = false;
ProcessRequestEndTrace();
}
}
catch (ThreadAbortException) {
try {
if (needToCallEndTrace)
ProcessRequestEndTrace();
} catch {}
}
finally {
if (includeStagesAfterAsyncPoint) {
ProcessRequestCleanup();
}
}
}
catch { throw; } // Prevent Exception Filter Security Issue (ASURT 122835)
}
private void RestoreCultures(Thread currentThread, CultureInfo prevCulture, CultureInfo prevUICulture) {
if (prevCulture != currentThread.CurrentCulture || prevUICulture != currentThread.CurrentUICulture) {
if (HttpRuntime.IsFullTrust) {
SetCulture(currentThread, prevCulture, prevUICulture);
}
else {
SetCultureWithAssert(currentThread, prevCulture, prevUICulture);
}
}
}
// This must be in its own method to avoid jitting System.EnterpriseServices.dll
// when it is not needed (ASURT 71868)
private void ProcessRequestTransacted() {
bool transactionAborted = false;
TransactedCallback processRequestCallback = new TransactedCallback(ProcessRequestMain);
// Part of the request needs to be done under transacted context
Transactions.InvokeTransacted(processRequestCallback,
(TransactionOption) _transactionMode, ref transactionAborted);
// The remainder has to be done outside
try {
if (transactionAborted) {
OnAbortTransaction(EventArgs.Empty);
WebBaseEvent.RaiseSystemEvent(this, WebEventCodes.RequestTransactionAbort);
}
else {
OnCommitTransaction(EventArgs.Empty);
WebBaseEvent.RaiseSystemEvent(this, WebEventCodes.RequestTransactionComplete);
}
// Make sure Request.RawUrl gets validated.
ValidateRawUrlIfRequired();
}
catch (ThreadAbortException) {
// Don't go into HandleError logic for ThreadAbortException's, since they
// are expected (e.g. when Response.Redirect() is called).
throw;
}
catch (Exception e) {
// Increment all of the appropriate error counters
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_DURING_REQUEST);
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_TOTAL);
// If it hasn't been handled, rethrow it
if (!HandleError(e))
throw;
}
}
private void ProcessRequestCleanup() {
if (_request == null) {
// ProcessRequestCleanup() has already been called
return;
}
#if DISPLAYRAREFIELDSTATISTICS
// Display rare field statistics at the end of the page (for debugging purpose)
DisplayRareFieldStatistics();
#endif
_request = null;
_response = null;
if (!IsCrossPagePostBack) {
UnloadRecursive(true);
}
if (Context.TraceIsEnabled) {
Trace.StopTracing();
}
}
private void ProcessRequestEndTrace() {
if (Context.TraceIsEnabled) {
Trace.EndRequest();
// DevDiv Bugs 154103: Do not write trace output while in an async postback
if (Trace.PageOutput && !IsCallback &&
(ScriptManager == null || !ScriptManager.IsInAsyncPostBack)) {
Trace.Render(CreateHtmlTextWriter(Response.Output));
// responses with trace should not be cached
Response.Cache.SetCacheability(HttpCacheability.NoCache);
}
}
}
#if DEBUG
private void DisplayRareFieldStatistics() {
int totalControls = 0;
int withOccasionalFields = 0;
int withRareFields = 0;
GetRareFieldStatistics(ref totalControls, ref withOccasionalFields, ref withRareFields);
_response.Write("<hr><b><p>Total controls: " + totalControls + "<br>");
_response.Write("With Occasional Fields: " + withOccasionalFields + "<br>");
_response.Write("With Rare Fields: " + withRareFields + "</p></b>");
}
#endif
internal void SetPreviousPage(Page previousPage) {
_previousPage = previousPage;
}
private void ProcessRequestMain() {
ProcessRequestMain(true /*includeStagesBeforeAsyncPoint*/, true /*includeStagesAfterAsyncPoint*/);
}
// !! IMPORTANT !!
// If you make changes to this method, also make changes to ProcessRequestMainAsync.
private void ProcessRequestMain(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) {
try {
HttpContext con = Context;
string exportedWebPartID = null;
if (includeStagesBeforeAsyncPoint) {
// For ASPCOMPAT need to call OnPageStart for each Session object
#if !FEATURE_PAL // FEATURE_PAL does not enable COM
if (IsInAspCompatMode)
AspCompatApplicationStep.OnPageStartSessionObjects();
#else // !FEATURE_PAL
throw new NotImplementedException ("ROTORTODO");
#endif // !FEATURE_PAL
// Is it a GET, POST or initial request?
if(PageAdapter != null) {
_requestValueCollection = PageAdapter.DeterminePostBackMode();
if (_requestValueCollection != null) {
_unvalidatedRequestValueCollection = PageAdapter.DeterminePostBackModeUnvalidated();
}
}
else {
_requestValueCollection = DeterminePostBackMode();
// The contract for DeterminePostBackModeUnvalidated() is that it will only be called when
// DeterminePostBackMode() returns a non-null result. This was done so that the implementation
// of DeterminePostBackModeUnvalidated() can be kep simple, without having to duplicate the
// same logic as DeterminePostBackMode().
if (_requestValueCollection != null) {
_unvalidatedRequestValueCollection = DeterminePostBackModeUnvalidated();
}
}
// It's possible that someone incorrectly implements DeterminePostBackModeUnvalidated() such that it
// returns null when DeterminePostBackMode() a non-null value. This could cause NullRefExceptions later on.
// However since few customers would override these methods we assume that this won't happen very often.
// A customer overriding DeterminePostBackModeUnvalidated() should understand what they are doing.
string callbackControlId = String.Empty;
// Special-case Web Part Export so it executes in the same security context as the page itself (VSWhidbey 426574)
if (DetermineIsExportingWebPart()) {
if (!RuntimeConfig.GetAppConfig().WebParts.EnableExport) {
throw new InvalidOperationException(SR.GetString(SR.WebPartExportHandler_DisabledExportHandler));
}
exportedWebPartID = Request.QueryString["webPart"];
if (String.IsNullOrEmpty(exportedWebPartID)) {
throw new InvalidOperationException(SR.GetString(SR.WebPartExportHandler_InvalidArgument));
}
if (String.Equals(Request.QueryString["scope"], "shared", StringComparison.OrdinalIgnoreCase)) {
_pageFlags.Set(isExportingWebPartShared);
}
string queryString = Request.QueryString["query"];
if (queryString == null) {
queryString = String.Empty;
}
Request.QueryStringText = queryString;
con.Trace.IsEnabled = false;
}
if (_requestValueCollection != null) {
// Determine if viewstate was encrypted.
if (_requestValueCollection[ViewStateEncryptionID] != null) {
ContainsEncryptedViewState = true;
}
// Determine if this is a callback.
callbackControlId = _requestValueCollection[callbackID];
// Only accepting POST callbacks to reduce mail attack possibilities (VSWhidbey 417355)
if ((callbackControlId != null) && (_request.HttpVerb == HttpVerb.POST)) {
_isCallback = true;
}
else { // Otherwise, determine if this is cross-page posting(callsbacks can never be cross page posts)
if (!IsCrossPagePostBack) {
VirtualPath previousPagePath = null;
if (_requestValueCollection[previousPageID] != null) {
try {
previousPagePath = VirtualPath.CreateNonRelativeAllowNull(
DecryptString(_requestValueCollection[previousPageID], Purpose.WebForms_Page_PreviousPageID));
}
catch {
// VSWhidbey 493209 If we fails to decrypt the previouspageid, still
// treat this as a cross page post, not a regular postback. Otherwise
// the viewstate cannot be decrypted properly. This will happen during
// cross page post between different applications.
_pageFlags[isCrossPagePostRequest] = true;
// do nothing, ignore CryptographicException.
}
// Process if the page is posted from cross-page that still exists and the target page is not same as source page.
if (previousPagePath != null &&
previousPagePath != Request.CurrentExecutionFilePathObject) {
_pageFlags[isCrossPagePostRequest] = true;
_previousPagePath = previousPagePath;
Debug.Assert(_previousPagePath != null);
}
}
}
}
}
// Load the scroll position data now that we have the request value collection
if (MaintainScrollPositionOnPostBack) {
LoadScrollPosition();
}
// we can't cache the value of IsEnabled because it could change during any phase.
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin PreInit");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_ENTER, _context.WorkerRequest);
PerformPreInit();
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End PreInit");
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin Init");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_ENTER, _context.WorkerRequest);
InitRecursive(null);
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End Init");
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin InitComplete");
OnInitComplete(EventArgs.Empty);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End InitComplete");
if (IsPostBack) {
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin LoadState");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_ENTER, _context.WorkerRequest);
LoadAllState();
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End LoadState");
Trace.Write("aspx.page", "Begin ProcessPostData");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_ENTER, _context.WorkerRequest);
ProcessPostData(_requestValueCollection, true /* fBeforeLoad */);
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End ProcessPostData");
}
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin PreLoad");
OnPreLoad(EventArgs.Empty);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End PreLoad");
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin Load");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_ENTER, _context.WorkerRequest);
LoadRecursive();
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End Load");
if (IsPostBack) {
// Try process the post data again (ASURT 29045)
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin ProcessPostData Second Try");
ProcessPostData(_leftoverPostData, false /* !fBeforeLoad */);
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End ProcessPostData Second Try");
Trace.Write("aspx.page", "Begin Raise ChangedEvents");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_ENTER, _context.WorkerRequest);
RaiseChangedEvents();
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End Raise ChangedEvents");
Trace.Write("aspx.page", "Begin Raise PostBackEvent");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_ENTER, _context.WorkerRequest);
RaisePostBackEvent(_requestValueCollection);
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End Raise PostBackEvent");
}
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin LoadComplete");
OnLoadComplete(EventArgs.Empty);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End LoadComplete");
if (IsPostBack && IsCallback) {
PrepareCallback(callbackControlId);
}
else if (!IsCrossPagePostBack) {
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin PreRender");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_ENTER, _context.WorkerRequest);
PreRenderRecursiveInternal();
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End PreRender");
}
}
/// Async Point here
if (_legacyAsyncInfo == null || _legacyAsyncInfo.CallerIsBlocking) {
// for non-async pages with registered async tasks - run the tasks here
// also when running async page via server.execute - run the tasks here
ExecuteRegisteredAsyncTasks();
}
// Make sure RawUrl gets validated.
ValidateRawUrlIfRequired();
if (includeStagesAfterAsyncPoint) {
if (IsCallback) {
RenderCallback();
return;
}
if (IsCrossPagePostBack) {
return;
}
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin PreRenderComplete");
PerformPreRenderComplete();
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End PreRenderComplete");
if (con.TraceIsEnabled) {
BuildPageProfileTree(EnableViewState);
Trace.Write("aspx.page", "Begin SaveState");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_ENTER, _context.WorkerRequest);
SaveAllState();
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End SaveState");
Trace.Write("aspx.page", "Begin SaveStateComplete");
}
OnSaveStateComplete(EventArgs.Empty);
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End SaveStateComplete");
Trace.Write("aspx.page", "Begin Render");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_ENTER, _context.WorkerRequest);
// Special-case Web Part Export so it executes in the same security context as the page itself (VSWhidbey 426574)
if (exportedWebPartID != null) {
ExportWebPart(exportedWebPartID);
}
else {
RenderControl(CreateHtmlTextWriter(Response.Output));
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End Render");
CheckRemainingAsyncTasks(false);
}
}
catch (ThreadAbortException e) {
// Don't go into HandleError logic for ThreadAbortExceptions, since they
// are expected (e.g. when Response.Redirect() is called).
// VSWhidbey 500309: perf improvement. We can safely cancel the thread abort here
// to avoid re-throwing the exception if this is a redirect and we're not being executed
// under the context of a Server.Execute call (i.e. _context.Handler == this). Otherwise,
// re-throw so this can be handled lower in the stack (see HttpApplication.ExecuteStep).
// This perf optimization can only be applied if we are executing the entire page
// lifecycle within this method call (otherwise, in async pages) calling ResetAbort
// would only skip part of the lifecycle, not the entire page (as Response.End is supposed to)
HttpApplication.CancelModuleException cancelException = e.ExceptionState as HttpApplication.CancelModuleException;
if (includeStagesBeforeAsyncPoint && includeStagesAfterAsyncPoint && // executing entire page
_context.Handler == this && // not in server execute
_context.ApplicationInstance != null && // application must be non-null so we can complete the request
cancelException != null && !cancelException.Timeout) { // this is Response.End
_context.ApplicationInstance.CompleteRequest();
ThreadResetAbortWithAssert();
}
else {
CheckRemainingAsyncTasks(true);
throw;
}
}
catch (System.Configuration.ConfigurationException) {
throw;
}
catch (Exception e) {
// Increment all of the appropriate error counters
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_DURING_REQUEST);
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_TOTAL);
// If it hasn't been handled, rethrow it
if (!HandleError(e))
throw;
}
}
// TAP version of ProcessRequestMain routine.
// !! IMPORTANT !!
// If you make changes to this method, also make changes to ProcessRequestMain.
private async Task ProcessRequestMainAsync(bool includeStagesBeforeAsyncPoint, bool includeStagesAfterAsyncPoint) {
try {
HttpContext con = Context;
string exportedWebPartID = null;
if (includeStagesBeforeAsyncPoint) {
// For ASPCOMPAT need to call OnPageStart for each Session object
#if !FEATURE_PAL // FEATURE_PAL does not enable COM
if (IsInAspCompatMode)
AspCompatApplicationStep.OnPageStartSessionObjects();
#else // !FEATURE_PAL
throw new NotImplementedException ("ROTORTODO");
#endif // !FEATURE_PAL
// Is it a GET, POST or initial request?
if(PageAdapter != null) {
_requestValueCollection = PageAdapter.DeterminePostBackMode();
if (_requestValueCollection != null) {
_unvalidatedRequestValueCollection = PageAdapter.DeterminePostBackModeUnvalidated();
}
}
else {
_requestValueCollection = DeterminePostBackMode();
// The contract for DeterminePostBackModeUnvalidated() is that it will only be called when
// DeterminePostBackMode() returns a non-null result. This was done so that the implementation
// of DeterminePostBackModeUnvalidated() can be kep simple, without having to duplicate the
// same logic as DeterminePostBackMode().
if (_requestValueCollection != null) {
_unvalidatedRequestValueCollection = DeterminePostBackModeUnvalidated();
}
}
// It's possible that someone incorrectly implements DeterminePostBackModeUnvalidated() such that it
// returns null when DeterminePostBackMode() a non-null value. This could cause NullRefExceptions later on.
// However since few customers would override these methods we assume that this won't happen very often.
// A customer overriding DeterminePostBackModeUnvalidated() should understand what they are doing.
string callbackControlId = String.Empty;
// Special-case Web Part Export so it executes in the same security context as the page itself (VSWhidbey 426574)
if (DetermineIsExportingWebPart()) {
if (!RuntimeConfig.GetAppConfig().WebParts.EnableExport) {
throw new InvalidOperationException(SR.GetString(SR.WebPartExportHandler_DisabledExportHandler));
}
exportedWebPartID = Request.QueryString["webPart"];
if (String.IsNullOrEmpty(exportedWebPartID)) {
throw new InvalidOperationException(SR.GetString(SR.WebPartExportHandler_InvalidArgument));
}
if (String.Equals(Request.QueryString["scope"], "shared", StringComparison.OrdinalIgnoreCase)) {
_pageFlags.Set(isExportingWebPartShared);
}
string queryString = Request.QueryString["query"];
if (queryString == null) {
queryString = String.Empty;
}
Request.QueryStringText = queryString;
con.Trace.IsEnabled = false;
}
if (_requestValueCollection != null) {
// Determine if viewstate was encrypted.
if (_requestValueCollection[ViewStateEncryptionID] != null) {
ContainsEncryptedViewState = true;
}
// Determine if this is a callback.
callbackControlId = _requestValueCollection[callbackID];
// Only accepting POST callbacks to reduce mail attack possibilities (VSWhidbey 417355)
if ((callbackControlId != null) && (_request.HttpVerb == HttpVerb.POST)) {
_isCallback = true;
}
else { // Otherwise, determine if this is cross-page posting(callsbacks can never be cross page posts)
if (!IsCrossPagePostBack) {
VirtualPath previousPagePath = null;
if (_requestValueCollection[previousPageID] != null) {
try {
previousPagePath = VirtualPath.CreateNonRelativeAllowNull(
DecryptString(_requestValueCollection[previousPageID], Purpose.WebForms_Page_PreviousPageID));
}
catch {
// VSWhidbey 493209 If we fails to decrypt the previouspageid, still
// treat this as a cross page post, not a regular postback. Otherwise
// the viewstate cannot be decrypted properly. This will happen during
// cross page post between different applications.
_pageFlags[isCrossPagePostRequest] = true;
// do nothing, ignore CryptographicException.
}
// Process if the page is posted from cross-page that still exists and the target page is not same as source page.
if (previousPagePath != null &&
previousPagePath != Request.CurrentExecutionFilePathObject) {
_pageFlags[isCrossPagePostRequest] = true;
_previousPagePath = previousPagePath;
Debug.Assert(_previousPagePath != null);
}
}
}
}
}
// Load the scroll position data now that we have the request value collection
if (MaintainScrollPositionOnPostBack) {
LoadScrollPosition();
}
// we can't cache the value of IsEnabled because it could change during any phase.
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin PreInit");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_ENTER, _context.WorkerRequest);
await PerformPreInitAsync().WithinCancellableCallback(con);
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_INIT_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End PreInit");
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin Init");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_ENTER, _context.WorkerRequest);
Task initRecursiveTask = InitRecursiveAsync(null, this);
await initRecursiveTask.WithinCancellableCallback(con);
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_INIT_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End Init");
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin InitComplete");
using (con.SyncContext.AllowVoidAsyncOperationsBlock()) {
OnInitComplete(EventArgs.Empty);
await GetWaitForPreviousStepCompletionAwaitable();
}
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End InitComplete");
if (IsPostBack) {
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin LoadState");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_ENTER, _context.WorkerRequest);
LoadAllState();
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_VIEWSTATE_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End LoadState");
Trace.Write("aspx.page", "Begin ProcessPostData");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_ENTER, _context.WorkerRequest);
if (AppSettings.EnableAsyncModelBinding) {
await ProcessPostDataAsync(_requestValueCollection, true /* fBeforeLoad */).WithinCancellableCallback(con);
}
else {
ProcessPostData(_requestValueCollection, true /* fBeforeLoad */);
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_POSTDATA_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End ProcessPostData");
}
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin PreLoad");
using (con.SyncContext.AllowVoidAsyncOperationsBlock()) {
OnPreLoad(EventArgs.Empty);
await GetWaitForPreviousStepCompletionAwaitable();
}
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End PreLoad");
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin Load");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_ENTER, _context.WorkerRequest);
await LoadRecursiveAsync(this).WithinCancellableCallback(con);
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_LOAD_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End Load");
if (IsPostBack) {
// Try process the post data again (ASURT 29045)
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin ProcessPostData Second Try");
if (AppSettings.EnableAsyncModelBinding) {
await ProcessPostDataAsync(_leftoverPostData, false /* !fBeforeLoad */).WithinCancellableCallback(con);
}
else {
ProcessPostData(_leftoverPostData, false /* !fBeforeLoad */);
}
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End ProcessPostData Second Try");
Trace.Write("aspx.page", "Begin Raise ChangedEvents");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_ENTER, _context.WorkerRequest);
await RaiseChangedEventsAsync().WithinCancellableCallback(con);
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_POST_DATA_CHANGED_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End Raise ChangedEvents");
Trace.Write("aspx.page", "Begin Raise PostBackEvent");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_ENTER, _context.WorkerRequest);
using (con.SyncContext.AllowVoidAsyncOperationsBlock()) {
RaisePostBackEvent(_requestValueCollection);
await GetWaitForPreviousStepCompletionAwaitable();
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RAISE_POSTBACK_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End Raise PostBackEvent");
}
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin LoadComplete");
using (con.SyncContext.AllowVoidAsyncOperationsBlock()) {
OnLoadComplete(EventArgs.Empty);
await GetWaitForPreviousStepCompletionAwaitable();
}
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End LoadComplete");
if (IsPostBack && IsCallback) {
await PrepareCallbackAsync(callbackControlId).WithinCancellableCallback(con);
}
else if (!IsCrossPagePostBack) {
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin PreRender");
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_ENTER, _context.WorkerRequest);
await PreRenderRecursiveInternalAsync(this).WithinCancellableCallback(con);
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_PRE_RENDER_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End PreRender");
}
}
/// Async Point here
if (_legacyAsyncInfo == null || _legacyAsyncInfo.CallerIsBlocking) {
// for non-async pages with registered async tasks - run the tasks here
// also when running async page via server.execute - run the tasks here
ExecuteRegisteredAsyncTasks();
}
// Make sure RawUrl gets validated.
ValidateRawUrlIfRequired();
if (includeStagesAfterAsyncPoint) {
if (IsCallback) {
RenderCallback();
return;
}
if (IsCrossPagePostBack) {
return;
}
if (con.TraceIsEnabled) Trace.Write("aspx.page", "Begin PreRenderComplete");
PerformPreRenderComplete();
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End PreRenderComplete");
if (con.TraceIsEnabled) {
BuildPageProfileTree(EnableViewState);
Trace.Write("aspx.page", "Begin SaveState");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_ENTER, _context.WorkerRequest);
SaveAllState();
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_SAVE_VIEWSTATE_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End SaveState");
Trace.Write("aspx.page", "Begin SaveStateComplete");
}
OnSaveStateComplete(EventArgs.Empty);
if (con.TraceIsEnabled) {
Trace.Write("aspx.page", "End SaveStateComplete");
Trace.Write("aspx.page", "Begin Render");
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_ENTER, _context.WorkerRequest);
// Special-case Web Part Export so it executes in the same security context as the page itself (VSWhidbey 426574)
if (exportedWebPartID != null) {
ExportWebPart(exportedWebPartID);
}
else {
RenderControl(CreateHtmlTextWriter(Response.Output));
}
if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Page)) EtwTrace.Trace(EtwTraceType.ETW_TYPE_PAGE_RENDER_LEAVE, _context.WorkerRequest);
if (con.TraceIsEnabled) Trace.Write("aspx.page", "End Render");
CheckRemainingAsyncTasks(false);
}
}
catch (ThreadAbortException e) {
// Don't go into HandleError logic for ThreadAbortExceptions, since they
// are expected (e.g. when Response.Redirect() is called).
// VSWhidbey 500309: perf improvement. We can safely cancel the thread abort here
// to avoid re-throwing the exception if this is a redirect and we're not being executed
// under the context of a Server.Execute call (i.e. _context.Handler == this). Otherwise,
// re-throw so this can be handled lower in the stack (see HttpApplication.ExecuteStep).
// This perf optimization can only be applied if we are executing the entire page
// lifecycle within this method call (otherwise, in async pages) calling ResetAbort
// would only skip part of the lifecycle, not the entire page (as Response.End is supposed to)
HttpApplication.CancelModuleException cancelException = e.ExceptionState as HttpApplication.CancelModuleException;
if (includeStagesBeforeAsyncPoint && includeStagesAfterAsyncPoint && // executing entire page
_context.Handler == this && // not in server execute
_context.ApplicationInstance != null && // application must be non-null so we can complete the request
cancelException != null && !cancelException.Timeout) { // this is Response.End
_context.ApplicationInstance.CompleteRequest();
ThreadResetAbortWithAssert();
}
else {
CheckRemainingAsyncTasks(true);
throw;
}
}
catch (System.Configuration.ConfigurationException) {
throw;
}
catch (Exception e) {
// Increment all of the appropriate error counters
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_DURING_REQUEST);
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_TOTAL);
// If it hasn't been handled, rethrow it
if (!HandleError(e))
throw;
}
}
internal WithinCancellableCallbackTaskAwaitable GetWaitForPreviousStepCompletionAwaitable() {
AspNetSynchronizationContext syncContext = SynchronizationContext.Current as AspNetSynchronizationContext;
if (syncContext != null) {
return syncContext.WaitForPendingOperationsAsync().WithinCancellableCallback(Context);
}
else {
// If the SynchronizationContext has been replaced, we can't query for previous step completion, so just assume it completed.
return WithinCancellableCallbackTaskAwaitable.Completed;
}
}
private void BuildPageProfileTree(bool enableViewState) {
if (!_profileTreeBuilt) {
_profileTreeBuilt = true;
BuildProfileTree("ROOT", enableViewState);
}
}
private void ExportWebPart(string exportedWebPartID) {
WebPart webPartToExport = null;
WebPartManager webPartManager = WebPartManager.GetCurrentWebPartManager(this);
if (webPartManager != null) {
webPartToExport = webPartManager.WebParts[exportedWebPartID];
}
if (webPartToExport == null || webPartToExport.IsClosed || webPartToExport is ProxyWebPart) {
// If there is no WebPartManager, or the web part is not on the page, or has been replaced
// by a ProxyWebPart, we should perform a Response.Redirect() back to the page with the
// Export query string removed. The Export query string has already been removed in
// ProcessRequestMain().
// (VSWhidbey 358464, 496050, 504819, 515472)
Response.Redirect(Request.RawUrl, false);
}
else {
// We'll be writing Xml to the response -> Prepare the response
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Expires = 0;
Response.ContentType = "application/mswebpart";
string title = webPartToExport.DisplayTitle;
if (String.IsNullOrEmpty(title)) {
title = SR.GetString(SR.Part_Untitled);
}
NonWordRegex nonWordRegex = new NonWordRegex();
Response.AddHeader("content-disposition", "attachment; filename=" +
nonWordRegex.Replace(title, "") +
".WebPart");
using (XmlTextWriter writer = new XmlTextWriter(Response.Output)) {
writer.Formatting = Formatting.Indented;
writer.WriteStartDocument();
// Export to the response stream
webPartManager.ExportWebPart(webPartToExport, writer);
writer.WriteEndDocument();
}
}
}
private void InitializeWriter(HtmlTextWriter writer) {
Html32TextWriter h32tw = writer as Html32TextWriter;
if (h32tw != null && Request.Browser != null) {
h32tw.ShouldPerformDivTableSubstitution = Request.Browser.Tables;
}
}
protected internal override void Render(HtmlTextWriter writer) {
InitializeWriter(writer);
base.Render(writer);
}
// !! IMPORTANT !!
// If you change this method, also change PrepareCallbackAsync.
[SuppressMessage("Microsoft.Security.Xml", "CA3004 ReviewCodeForInformationDisclosureVulnerabilities", Justification = "Developer-controlled contents are implicitly trusted.")]
private void PrepareCallback(string callbackControlID) {
Response.Cache.SetNoStore();
try {
string param = _requestValueCollection[callbackParameterID];
_callbackControl = FindControl(callbackControlID) as ICallbackEventHandler;
if (_callbackControl != null) {
_callbackControl.RaiseCallbackEvent(param);
}
else {
throw new InvalidOperationException(SR.GetString(SR.Page_CallBackTargetInvalid, callbackControlID));
}
}
catch (Exception e) {
Response.Clear();
Response.Write('e');
if (Context.IsCustomErrorEnabled) {
Response.Write(SR.GetString(SR.Page_CallBackError));
}
else {
bool needsCallbackLoadScript = !String.IsNullOrEmpty(_requestValueCollection[callbackLoadScriptID]);
Response.Write(needsCallbackLoadScript ?
Util.QuoteJScriptString(HttpUtility.HtmlEncode(e.Message)) :
HttpUtility.HtmlEncode(e.Message));
}
}
return;
}
// TAP version of PrepareCallback.
// !! IMPORTANT !!
// If you change this method, also change PrepareCallback.
[SuppressMessage("Microsoft.Security.Xml", "CA3004 ReviewCodeForInformationDisclosureVulnerabilities", Justification = "Developer-controlled contents are implicitly trusted.")]
private async Task PrepareCallbackAsync(string callbackControlID) {
Response.Cache.SetNoStore();
try {
string param = _requestValueCollection[callbackParameterID];
_callbackControl = FindControl(callbackControlID) as ICallbackEventHandler;
if (_callbackControl != null) {
using (Context.SyncContext.AllowVoidAsyncOperationsBlock()) {
_callbackControl.RaiseCallbackEvent(param);
await GetWaitForPreviousStepCompletionAwaitable();
}
}
else {
throw new InvalidOperationException(SR.GetString(SR.Page_CallBackTargetInvalid, callbackControlID));
}
}
catch (Exception e) {
Response.Clear();
Response.Write('e');
if (Context.IsCustomErrorEnabled) {
Response.Write(SR.GetString(SR.Page_CallBackError));
}
else {
bool needsCallbackLoadScript = !String.IsNullOrEmpty(_requestValueCollection[callbackLoadScriptID]);
Response.Write(needsCallbackLoadScript ?
Util.QuoteJScriptString(HttpUtility.HtmlEncode(e.Message)) :
HttpUtility.HtmlEncode(e.Message));
}
}
return;
}
[SuppressMessage("Microsoft.Security.Xml", "CA3004 ReviewCodeForInformationDisclosureVulnerabilities", Justification = "Developer-controlled contents are implicitly trusted.")]
private void RenderCallback() {
bool needsCallbackLoadScript = !String.IsNullOrEmpty(_requestValueCollection[callbackLoadScriptID]);
try {
string index = null;
if (needsCallbackLoadScript) {
index = _requestValueCollection[callbackIndexID];
if (String.IsNullOrEmpty(index)) {
throw new HttpException(SR.GetString(SR.Page_CallBackInvalid));
}
// We validate the user string because we're injecting it into the response script.
// We don't need the integer, so we don't call Parse, we just need to check only expected
// characters are in the string (0 to 9)
for (int i = 0; i < index.Length; i++) {
char c = index[i];
if (c < '0' || c > '9') {
throw new HttpException(SR.GetString(SR.Page_CallBackInvalid));
}
}
Response.Write("<script>parent.__pendingCallbacks[");
Response.Write(index);
Response.Write("].xmlRequest.responseText=\"");
}
if (_callbackControl != null) {
string result = _callbackControl.GetCallbackResult();
if (EnableEventValidation) {
// Outputting the new value for the validation field under the length|value format.
string validation = ClientScript.GetEventValidationFieldValue();
Response.Write(validation.Length.ToString(CultureInfo.InvariantCulture));
Response.Write('|');
Response.Write(validation);
}
else {
Response.Write('s');
}
Response.Write(needsCallbackLoadScript ? Util.QuoteJScriptString(result) : result);
}
if (needsCallbackLoadScript) {
Response.Write("\";parent.__pendingCallbacks[");
Response.Write(index);
Response.Write("].xmlRequest.readyState=4;parent.WebForm_CallbackComplete();</script>");
}
}
catch (Exception e) {
Response.Clear();
Response.Write('e');
if (Context.IsCustomErrorEnabled) {
Response.Write(SR.GetString(SR.Page_CallBackError));
}
else {
Response.Write(needsCallbackLoadScript ?
Util.QuoteJScriptString(HttpUtility.HtmlEncode(e.Message)) :
HttpUtility.HtmlEncode(e.Message));
}
}
return;
}
private bool RenderDivAroundHiddenInputs(HtmlTextWriter writer) {
return writer.RenderDivAroundHiddenInputs && (!EnableLegacyRendering || (RenderingCompatibility >= VersionUtil.Framework40));
}
internal void SetForm(HtmlForm form) {
_form = form;
}
internal void SetPostFormRenderDelegate(RenderMethod renderMethod) {
_postFormRenderDelegate = renderMethod;
}
public HtmlForm Form { get { return _form; } }
/// <devdoc>
/// <para>If called, ViewState will be persisted (see ASURT 73020).</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public void RegisterViewStateHandler() {
_needToPersistViewState = true;
}
private void SaveAllState() {
// Don't do anything if no one cares about the view state (see ASURT 73020)
// Note: If _needToPersistViewState is false, control state should also be ignored.
if (!_needToPersistViewState)
return;
Pair statePair = new Pair();
// Control state is saved as a dictionary of
// 1. A list of controls that require postback (stored under the page id)
// 2. A dictionary of controls and their control state
IDictionary controlStates = null;
if (_registeredControlsRequiringControlState != null &&
_registeredControlsRequiringControlState.Count > 0) {
#if OBJECTSTATEFORMATTER
controlStates = new HybridDictionary(_registeredControlsRequiringControlState.Count + 1);
#else
controlStates = new Hashtable(_registeredControlsRequiringControlState.Count + 1);
#endif
foreach (Control ctl in _registeredControlsRequiringControlState) {
object controlState = ctl.SaveControlStateInternal();
// Do not allow null control states to be added, and do not allow a control's state to be
// added more than once.
if (controlStates[ctl.UniqueID] == null && controlState != null) {
controlStates.Add(ctl.UniqueID, controlState);
}
}
}
if (_registeredControlsThatRequirePostBack != null && _registeredControlsThatRequirePostBack.Count > 0) {
if (controlStates == null) {
#if OBJECTSTATEFORMATTER
controlStates = new HybridDictionary();
#else
controlStates = new Hashtable();
#endif
}
controlStates.Add(PageRegisteredControlsThatRequirePostBackKey, _registeredControlsThatRequirePostBack);
}
// Only persist control state if it is nonempty.
if (controlStates != null && controlStates.Count > 0) {
statePair.First = controlStates;
}
// The state is saved as an array of objects:
// 1. The hash code string
// 2. The state of the entire control hierarchy
ViewStateMode inheritedMode = ViewStateMode;
if (inheritedMode == ViewStateMode.Inherit) {
inheritedMode = ViewStateMode.Enabled;
}
Pair allSavedViewState = new Pair(GetTypeHashCode().ToString(NumberFormatInfo.InvariantInfo), SaveViewStateRecursive(inheritedMode));
if (Context.TraceIsEnabled) {
int viewStateSize = 0;
if (allSavedViewState.Second is Pair) {
viewStateSize = EstimateStateSize(((Pair)allSavedViewState.Second).First);
} else if (allSavedViewState.Second is Triplet) {
viewStateSize = EstimateStateSize(((Triplet)allSavedViewState.Second).First);
}
Trace.AddControlStateSize(UniqueID, viewStateSize, controlStates == null? 0 : EstimateStateSize(controlStates[UniqueID]));
}
statePair.Second = allSavedViewState;
SavePageStateToPersistenceMedium(statePair);
}
/*
* Override this method to persist view state to something other
* than hidden fields (
*/
/// <devdoc>
/// <para>Saves any view state information for the page. Override
/// this method if you want to save the page view state in anything other than a hidden field.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
protected internal virtual void SavePageStateToPersistenceMedium(object state) {
PageStatePersister persister = PageStatePersister;
if (state is Pair) {
Pair pair = (Pair)state;
persister.ControlState = pair.First;
persister.ViewState = pair.Second;
}
else /* triplet, legacy case, see VSWhidbey 155185 */ {
persister.ViewState = state;
}
persister.Save();
}
/*
* Set the intrinsics in this page object
*/
private void SetIntrinsics(HttpContext context) {
SetIntrinsics(context, false /* allowAsync */);
}
private void SetIntrinsics(HttpContext context, bool allowAsync) {
_context = context;
_request = context.Request;
_response = context.Response;
_application = context.Application;
_cache = context.Cache;
if (!allowAsync && _context != null && _context.ApplicationInstance != null) {
// disable attempts to launch async operations from pages not marked as async=true
// the first non-async page [on the server.execute stack] disables async operations
// it is re-enabled back in HttpApplication after done executing handler
_context.SyncContext.Disable();
}
// Synchronize the ClientTarget
if (!String.IsNullOrEmpty(_clientTarget)) {
_request.ClientTarget = _clientTarget;
}
// DCR 85444: Support per device type encoding
HttpCapabilitiesBase caps = _request.Browser;
if(caps != null) {
// Dev10 440476: Page.SetIntrinsics method has a bug causing throwing NullReferenceException
// in certain circumstances. This edge case was regressed by the VSWhidbey fix below.
// VSWhidbey 109162: Set content type at the very beginning so it can be
// overwritten within the user code of the page if needed.
_response.ContentType = caps.PreferredRenderingMime;
string preferredResponseEncoding = caps.PreferredResponseEncoding;
string preferredRequestEncoding = caps.PreferredRequestEncoding;
if (!String.IsNullOrEmpty(preferredResponseEncoding)) {
_response.ContentEncoding = Encoding.GetEncoding(preferredResponseEncoding);
}
if(!String.IsNullOrEmpty(preferredRequestEncoding)) {
_request.ContentEncoding = Encoding.GetEncoding(preferredRequestEncoding);
}
}
// Hook up any automatic handler we may find (e.g. Page_Load)
HookUpAutomaticHandlers();
}
/// <devdoc>
/// Initializes the page's reference to the header control
/// </devdoc>
internal void SetHeader(HtmlHead header) {
_header = header;
if (!String.IsNullOrEmpty(_titleToBeSet)) {
if (_header == null) {
throw new InvalidOperationException(SR.GetString(SR.Page_Title_Requires_Head));
}
else {
Title = _titleToBeSet;
_titleToBeSet = null;
}
}
if (!String.IsNullOrEmpty(_descriptionToBeSet)) {
if (_header == null) {
throw new InvalidOperationException(SR.GetString(SR.Page_Description_Requires_Head));
}
else {
MetaDescription = _descriptionToBeSet;
_descriptionToBeSet = null;
}
}
if (!String.IsNullOrEmpty(_keywordsToBeSet)) {
if (_header == null) {
throw new InvalidOperationException(SR.GetString(SR.Page_Description_Requires_Head));
}
else {
MetaKeywords = _keywordsToBeSet;
_keywordsToBeSet = null;
}
}
}
/// Override to unload the previousPage. The previousPage is unloaded after
/// the current page since current page could depend on previousPage.
internal override void UnloadRecursive(bool dispose) {
base.UnloadRecursive(dispose);
if (_previousPage != null && _previousPage.IsCrossPagePostBack) {
_previousPage.UnloadRecursive(dispose);
}
}
// ASP Compat helpers
#if !FEATURE_PAL // FEATURE_PAL does not enable COM
private AspCompatApplicationStep _aspCompatStep;
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected IAsyncResult AspCompatBeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) {
SetIntrinsics(context);
_aspCompatStep = new AspCompatApplicationStep(context, new AspCompatCallback(ProcessRequest));
return _aspCompatStep.BeginAspCompatExecution(cb, extraData);
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected void AspCompatEndProcessRequest(IAsyncResult result) {
_aspCompatStep.EndAspCompatExecution(result);
}
#endif // !FEATURE_PAL
// Async page helpers
public void ExecuteRegisteredAsyncTasks() {
if (_legacyAsyncTaskManager == null) {
// no tasks registered
return;
}
if (_legacyAsyncTaskManager.TaskExecutionInProgress) {
// already executing - don't re-enter
return;
}
HttpAsyncResult ar = _legacyAsyncTaskManager.ExecuteTasks(null /*callback*/, null /*extraData*/);
if (ar.Error != null) {
// rethrow any errors running tasks synchronously
throw new HttpException(null, ar.Error);
}
}
private void CheckRemainingAsyncTasks(bool isThreadAbort) {
// this method is called at the end of page execution
// it throws if there are registered async tasks not executed yet
if (_legacyAsyncTaskManager != null) {
_legacyAsyncTaskManager.DisposeTimer();
if (isThreadAbort) {
_legacyAsyncTaskManager.CompleteAllTasksNow(true);
return;
}
if (!_legacyAsyncTaskManager.FailedToStartTasks && _legacyAsyncTaskManager.AnyTasksRemain) {
throw new HttpException(SR.GetString(SR.Registered_async_tasks_remain));
}
}
}
// Registers an asynchronous task with a page. Like other APIs on Page, this method is itself not thread-safe.
public void RegisterAsyncTask(PageAsyncTask task) {
if (task == null) {
throw new ArgumentNullException("task");
}
if (SynchronizationContextUtil.CurrentMode == SynchronizationContextMode.Legacy) {
if (_legacyAsyncTaskManager == null) {
_legacyAsyncTaskManager = new LegacyPageAsyncTaskManager(this);
}
// Need to convert the user-provided PageAsyncTask to a legacy-style task for consumption by the legacy task manager
LegacyPageAsyncTask legacyTask = new LegacyPageAsyncTask(task.BeginHandler, task.EndHandler, task.TimeoutHandler, task.State, task.ExecuteInParallel);
_legacyAsyncTaskManager.AddTask(legacyTask);
}
else {
// synchronous pages don't support async tasks
if (!(this is IHttpAsyncHandler)) {
throw new InvalidOperationException(SR.GetString(SR.Async_required));
}
if (_asyncTaskManager == null) {
_asyncTaskManager = new PageAsyncTaskManager();
}
// We need to detect whether this is TAP or APM and enqueue the appropriate concrete type
IPageAsyncTask asyncTask = (task.TaskHandler != null)
? (IPageAsyncTask)new PageAsyncTaskTap(task.TaskHandler)
: (IPageAsyncTask)new PageAsyncTaskApm(task.BeginHandler, task.EndHandler, task.State);
_asyncTaskManager.EnqueueTask(asyncTask);
}
}
class LegacyPageAsyncInfo {
private Page _page;
private bool _callerIsBlocking; // in case of blocking caller can't lock app instance on another thread (deadlock)
private HttpApplication _app;
private AspNetSynchronizationContextBase _syncContext;
private HttpAsyncResult _asyncResult;
private bool _asyncPointReached;
private int _handlerCount;
private ArrayList _beginHandlers;
private ArrayList _endHandlers;
private ArrayList _stateObjects;
private AsyncCallback _completionCallback;
private WaitCallback _callHandlersThreadpoolCallback;
private int _currentHandler;
private Exception _error;
private bool _completed;
internal LegacyPageAsyncInfo(Page page) {
_page = page;
_app = page.Context.ApplicationInstance;
_syncContext = page.Context.SyncContext;
_completionCallback = new AsyncCallback(this.OnAsyncHandlerCompletion);
_callHandlersThreadpoolCallback = new WaitCallback(this.CallHandlersFromThreadpoolThread);
}
internal HttpAsyncResult AsyncResult {
get { return _asyncResult; }
set { _asyncResult = value; }
}
internal bool AsyncPointReached {
get { return _asyncPointReached; }
set { _asyncPointReached = value; }
}
internal bool CallerIsBlocking {
get { return _callerIsBlocking; }
set { _callerIsBlocking = value; }
}
internal void AddHandler(BeginEventHandler beginHandler, EndEventHandler endHandler, Object state) {
if (_handlerCount == 0) {
_beginHandlers = new ArrayList();
_endHandlers = new ArrayList();
_stateObjects = new ArrayList();
}
_beginHandlers.Add(beginHandler);
_endHandlers.Add(endHandler);
_stateObjects.Add(state);
_handlerCount++;
}
internal void CallHandlers(bool onPageThread) {
try {
if (CallerIsBlocking || onPageThread) {
// locking app on another thread when the caller is blocking will lead to deadlocks, so don't lock here
// VSWhidbey 189344
CallHandlersPossiblyUnderLock(onPageThread);
} else {
lock (_app) {
CallHandlersPossiblyUnderLock(onPageThread);
}
}
}
catch (Exception e) {
_error = e;
_completed = true;
_asyncResult.Complete(onPageThread, null /*result*/, _error);
if (!onPageThread &&
e is ThreadAbortException &&
((ThreadAbortException)e).ExceptionState is HttpApplication.CancelModuleException) {
// don't leave this threadpool thread with CancelModuleException
// as thread state - it might lead to AppDomainUnloadedException
// later, when the current app domain is unloaded and there is
// an attempt to get thread state form another app domain on
// the same thread
ThreadResetAbortWithAssert();
}
}
}
private void CallHandlersPossiblyUnderLock(bool onPageThread) {
ThreadContext threadContext = null;
if (!onPageThread) {
threadContext = _app.OnThreadEnter();
}
try {
while (_currentHandler < _handlerCount && _error == null) {
try {
IAsyncResult ar = ((BeginEventHandler)_beginHandlers[_currentHandler])(_page, EventArgs.Empty, _completionCallback, _stateObjects[_currentHandler]);
if (ar == null) {
throw new InvalidOperationException(SR.GetString(SR.Async_null_asyncresult));
}
if (ar.CompletedSynchronously) {
try {
((EndEventHandler)_endHandlers[_currentHandler])(ar);
}
finally {
_currentHandler++;
}
continue;
}
// async completion
return;
}
catch (Exception e) {
if (onPageThread && _syncContext.PendingOperationsCount == 0) {
throw;
}
// Increment all of the appropriate error counters
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_DURING_REQUEST);
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_TOTAL);
// If it hasn't been handled, rememeber it
try {
if (!_page.HandleError(e))
_error = e;
}
catch (Exception e2) {
_error = e2;
}
}
}
// check if any async operations started
#if DBG
Debug.Trace("Async", "Page has PendingOperationsCount of " + _syncContext.PendingOperationsCount);
#endif
if (_syncContext.PendingCompletion(_callHandlersThreadpoolCallback)) {
return;
}
// get the error that happened in async completion delegates
if (_error == null && _syncContext.Error != null) {
try {
if (!_page.HandleError(_syncContext.Error)) {
_error = _syncContext.Error;
_syncContext.ClearError();
}
}
catch (Exception e) {
_error = e;
}
}
// finish up the page processing
try {
_page.Context.InvokeCancellableCallback(new WaitCallback(o => { _page.ProcessRequest(false /*includeStagesBeforeAsyncPoint*/, true /*includeStagesAfterAsyncPoint*/); }), null);
}
catch (Exception e) {
if (onPageThread)
throw;
_error = e;
}
// complete the async request (notify HttpAppplication)
if (threadContext != null) {
// call DisassociateFromCurrentThread before Complete, because complete
// might resume and finish up the pipeline inside the call
try {
threadContext.DisassociateFromCurrentThread();
}
finally {
threadContext = null;
}
}
_completed = true;
_asyncResult.Complete(onPageThread, null /*result*/, _error);
}
finally {
if (threadContext != null) {
threadContext.DisassociateFromCurrentThread();
}
}
}
private void OnAsyncHandlerCompletion(IAsyncResult ar) {
if (ar.CompletedSynchronously) // handled in CallHandlers()
return;
try {
((EndEventHandler)_endHandlers[_currentHandler])(ar);
}
catch (Exception e) {
_error = e;
}
if (_completed) {
// already completed (possibly due to timeout, don't continue)
return;
}
_currentHandler++;
if (Thread.CurrentThread.IsThreadPoolThread) {
// if on thread pool thread, use the current thread
CallHandlers(false);
}
else {
// if on a non-threadpool thread, requeue
ThreadPool.QueueUserWorkItem(_callHandlersThreadpoolCallback);
}
}
private void CallHandlersFromThreadpoolThread(Object data) {
Debug.Trace("Async", "Page -- CallHandlersFromThreadpoolThread");
CallHandlers(false);
}
internal void SetError(Exception error) {
_error = error;
}
}
private void AsyncPageProcessRequestBeforeAsyncPointCancellableCallback(Object state) {
ProcessRequest(true /*includeStagesBeforeAsyncPoint*/, false /*includeStagesAfterAsyncPoint*/);
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected IAsyncResult AsyncPageBeginProcessRequest(HttpContext context, AsyncCallback callback, Object extraData) {
// This method just dispatches to either the TAP or APM implementation, depending on the synchronization mode
if (SynchronizationContextUtil.CurrentMode == SynchronizationContextMode.Legacy) {
return LegacyAsyncPageBeginProcessRequest(context, callback, extraData);
}
else {
return TaskAsyncHelper.BeginTask(() => ProcessRequestAsync(context), callback, extraData);
}
}
internal CancellationTokenSource CreateCancellationTokenFromAsyncTimeout() {
TimeSpan timeout = AsyncTimeout;
// CancellationTokenSource can only create timers within a specific range (<= _maxAsyncTimeout)
return (timeout <= _maxAsyncTimeout)
? new CancellationTokenSource(timeout)
: new CancellationTokenSource();
}
// TAP
private async Task ProcessRequestAsync(HttpContext context) {
// we disallow async operations except during specific portions of the lifecycle
context.SyncContext.ProhibitVoidAsyncOperations();
SetIntrinsics(context, true /* allowAsync */);
if (_asyncTaskManager == null) {
// could be already created if AddOnPreRenderCompleteAsync called before ProcessRequest
_asyncTaskManager = new PageAsyncTaskManager();
}
try {
// process everything before the async point
// the AsyncPageProcessRequestBeforeAsyncPointCancellableCallback method has its own HandleError semantics and will not throw if the exception is handled
Task preWorkTask = null;
_context.InvokeCancellableCallback(_ => {
preWorkTask = ProcessRequestAsync(includeStagesBeforeAsyncPoint: true, includeStagesAfterAsyncPoint: false);
}, null);
await preWorkTask;
// perform the asynchronous work
try {
using (CancellationTokenSource cancellationTokenSource = CreateCancellationTokenFromAsyncTimeout()) {
CancellationToken cancellationToken = cancellationTokenSource.Token;
try {
await _asyncTaskManager.ExecuteTasksAsync(this, EventArgs.Empty, cancellationToken, _context.SyncContext, _context.ApplicationInstance);
}
finally {
// Homogenize any exceptions due to request timeout into a TimeoutException.
if (cancellationToken.IsCancellationRequested) {
throw new TimeoutException(SR.GetString(SR.Async_task_timed_out));
}
}
}
}
catch (Exception ex) {
// This catch block is copied from ProcessRequestMain
// Increment all of the appropriate error counters
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_DURING_REQUEST);
PerfCounters.IncrementCounter(AppPerfCounter.ERRORS_TOTAL);
// If it hasn't been handled, rethrow it
if (!HandleError(ex))
throw;
}
// process everything after the async point
Task postWorkTask = null;
_context.InvokeCancellableCallback(_ => {
postWorkTask = ProcessRequestAsync(includeStagesBeforeAsyncPoint: false, includeStagesAfterAsyncPoint: true);
}, null);
await postWorkTask;
}
finally {
// call Unload events
ProcessRequestCleanup();
}
}
private IAsyncResult LegacyAsyncPageBeginProcessRequest(HttpContext context, AsyncCallback callback, Object extraData) {
SetIntrinsics(context, true /* allowAsync */);
if (_legacyAsyncInfo == null) {
// could be already created if AddOnPreRenderCompleteAsync called before ProcessRequest
_legacyAsyncInfo = new LegacyPageAsyncInfo(this);
}
_legacyAsyncInfo.AsyncResult = new HttpAsyncResult(callback, extraData);
_legacyAsyncInfo.CallerIsBlocking = (callback == null);
// process request stages before async point
try {
_context.InvokeCancellableCallback(new WaitCallback(this.AsyncPageProcessRequestBeforeAsyncPointCancellableCallback), null);
}
catch (Exception e) {
if (_context.SyncContext.PendingOperationsCount == 0) {
// if there are no pending async operations it is ok to throw
throw;
}
// can't throw yet, have to wait for pending async operations to finish
Debug.Trace("Async", "Exception with async pending - saving the error");
_legacyAsyncInfo.SetError(e);
}
// register handler from async manager to run async tasks (if any tasks are registered)
// for blocking callers async tasks were already run
if (_legacyAsyncTaskManager != null && !_legacyAsyncInfo.CallerIsBlocking) {
_legacyAsyncTaskManager.RegisterHandlersForPagePreRenderCompleteAsync();
}
// mark async point
_legacyAsyncInfo.AsyncPointReached = true;
// disable async operations after this point
_context.SyncContext.Disable();
// call into async subscribers
_legacyAsyncInfo.CallHandlers(true /*onPageThread*/);
return _legacyAsyncInfo.AsyncResult;
}
/// <internalonly/>
[EditorBrowsable(EditorBrowsableState.Never)]
protected void AsyncPageEndProcessRequest(IAsyncResult result) {
// This method just dispatches to either the TAP or APM implementation, depending on the synchronization mode
if (SynchronizationContextUtil.CurrentMode == SynchronizationContextMode.Legacy) {
LegacyAsyncPageEndProcessRequest(result);
}
else {
// EndTask() observes and throws any captured exceptions; also waits for asynchronous completion
TaskAsyncHelper.EndTask(result);
}
}
private void LegacyAsyncPageEndProcessRequest(IAsyncResult result) {
if (_legacyAsyncInfo == null)
return;
Debug.Assert(_legacyAsyncInfo.AsyncResult == result);
// End() observes and throws any captured exceptions
_legacyAsyncInfo.AsyncResult.End();
}
public void AddOnPreRenderCompleteAsync(BeginEventHandler beginHandler, EndEventHandler endHandler) {
AddOnPreRenderCompleteAsync(beginHandler, endHandler, null);
}
public void AddOnPreRenderCompleteAsync(BeginEventHandler beginHandler, EndEventHandler endHandler, Object state) {
if (beginHandler == null) {
throw new ArgumentNullException("beginHandler");
}
if (endHandler == null) {
throw new ArgumentNullException("endHandler");
}
if (SynchronizationContextUtil.CurrentMode == SynchronizationContextMode.Normal) {
// If using the new synchronization patterns, go against the task manager directly
RegisterAsyncTask(new PageAsyncTask(beginHandler, endHandler, null, state));
return;
}
if (_legacyAsyncInfo == null) {
if (this is IHttpAsyncHandler) {
// could be called from ctor before process request
_legacyAsyncInfo = new LegacyPageAsyncInfo(this);
}
else {
// synchronous pages don't support add async handler
throw new InvalidOperationException(SR.GetString(SR.Async_required));
}
}
if (_legacyAsyncInfo.AsyncPointReached) {
throw new InvalidOperationException(SR.GetString(SR.Async_addhandler_too_late));
}
_legacyAsyncInfo.AddHandler(beginHandler, endHandler, state);
}
/// <devdoc>
/// <para>Instructs any validation controls included on the page to validate their
/// assigned information for the incoming page request.</para>
/// </devdoc>
public virtual void Validate() {
_validated = true;
if (_validators != null) {
for (int i = 0; i < Validators.Count; i++) {
Validators[i].Validate();
}
}
}
public virtual void Validate(string validationGroup) {
_validated = true;
if (_validators != null) {
ValidatorCollection validators = GetValidators(validationGroup);
// VSWhidbey 207823: When ValidationGroup is the default empty string,
// we should call the V1 method which could have been overridden so
// the overridden method on user page wouldn't be missed.
if (String.IsNullOrEmpty(validationGroup) &&
_validators.Count == validators.Count) {
Validate();
}
else {
for (int i = 0; i < validators.Count; i++) {
validators[i].Validate();
}
}
}
}
public ValidatorCollection GetValidators(string validationGroup) {
if (validationGroup == null) {
validationGroup = String.Empty;
}
ValidatorCollection validators = new ValidatorCollection();
if (_validators != null) {
for (int i = 0; i < Validators.Count; i++) {
BaseValidator baseValidator = Validators[i] as BaseValidator;
if (baseValidator != null) {
if (0 == String.Compare(baseValidator.ValidationGroup, validationGroup,
StringComparison.Ordinal)) {
validators.Add(baseValidator);
}
}
else if (validationGroup.Length == 0) {
validators.Add(Validators[i]);
}
}
}
return validators;
}
/// <devdoc>
/// <para>Throws an exception if it is runtime and we are not currently rendering the form runat=server tag.
/// Most controls that post back or that use client script require to be in this tag to function, so
/// they can call this during rendering. At design time this will do nothing.</para>
/// <para>Custom Control creators should call this during render if they render any sort of input tag, if they call
/// GetPostBackEventReference, or if they emit client script. A composite control does not need to make this
/// call.</para>
/// <para>This method should not be overridden unless creating an alternative page framework.</para>
/// </devdoc>
[EditorBrowsable(EditorBrowsableState.Advanced)]
public virtual void VerifyRenderingInServerForm(Control control) {
// We only want to make this check if we are definitely at runtime
if (Context == null || DesignMode) {
return;
}
if (control == null) {
throw new ArgumentNullException("control");
}
if (!_inOnFormRender && !IsCallback) {
throw new HttpException(SR.GetString(SR.ControlRenderedOutsideServerForm, control.ClientID, control.GetType().Name));
}
}
public PageAdapter PageAdapter {
get {
if(_pageAdapter == null) {
ResolveAdapter();
_pageAdapter = (PageAdapter)AdapterInternal;
}
return _pageAdapter;
}
}
//
private String _relativeFilePath;
internal String RelativeFilePath {
get {
if (_relativeFilePath == null) {
String s = Context.Request.CurrentExecutionFilePath;
String filePath = Context.Request.FilePath;
if(filePath.Equals(s)) {
int slash = s.LastIndexOf('/');
if (slash >= 0) {
s = s.Substring(slash+1);
}
_relativeFilePath = s;
}
else {
_relativeFilePath = Server.UrlDecode(UrlPath.MakeRelative(filePath, s));
}
}
return _relativeFilePath;
}
}
private bool _designModeChecked = false;
private bool _designMode = false;
internal bool GetDesignModeInternal() {
if(!_designModeChecked) {
_designMode = (Site != null) ? Site.DesignMode : false;
_designModeChecked = true;
}
return _designMode;
}
// For use by controls to store information with same lifetime as the request, for example, all radio buttons can
// use this to store the dictionary of radio button groups. The key should be a type. For the example, the value associated with
// the key System.Web.UI.WebControls.WmlRadioButtonAdapter is a NameValueCollection of RadioButtonGroups.
private IDictionary _items;
[
Browsable(false)
]
public IDictionary Items {
get {
if (_items == null) {
_items = new HybridDictionary();
}
return _items;
}
}
// Simplified data binding context stack
private Stack _dataBindingContext;
/// <devdoc>
/// Creates a new context for databinding by pushing a new data item onto the databinding context stack.
/// </devdoc>
internal void PushDataBindingContext(object dataItem) {
if (_dataBindingContext == null) {
_dataBindingContext = new Stack();
}
_dataBindingContext.Push(dataItem);
}
/// <devdoc>
/// Exits a databinding context by removing the current data item from the databinding context stack.
/// </devdoc>
internal void PopDataBindingContext() {
Debug.Assert(_dataBindingContext != null);
Debug.Assert(_dataBindingContext.Count > 0);
_dataBindingContext.Pop();
}
/// <devdoc>
/// Gets the current data item from the top of the databinding context stack.
/// </devdoc>
public object GetDataItem() {
if ((_dataBindingContext == null) || (_dataBindingContext.Count == 0)) {
throw new InvalidOperationException(SR.GetString(SR.Page_MissingDataBindingContext));
}
return _dataBindingContext.Peek();
}
internal static bool IsSystemPostField(string field) {
return s_systemPostFields.Contains(field);
}
internal IScriptManager ScriptManager {
get {
return (IScriptManager)Items[typeof(IScriptManager)];
}
}
private void ValidateRawUrlIfRequired() {
// Only validate the RawUrl if we weren't asked to skip validation and the current validation mode says we should validate.
bool validationRequired = !SkipFormActionValidation && CalculateEffectiveValidateRequest();
if (validationRequired) {
// Simply touching the RawUrl property getter is sufficient to perform validation.
string unused = _request.RawUrl;
}
}
// Needed to support Validators in AJAX 1.0 (Windows OS Bugs 2015831)
#region Atlas ScriptManager Partial Rendering support
internal bool IsPartialRenderingSupported {
get {
if (!_pageFlags[isPartialRenderingSupportedSet]) {
Type scriptManagerType = ScriptManagerType;
if (scriptManagerType != null) {
object scriptManager = Page.Items[scriptManagerType];
if (scriptManager != null) {
PropertyInfo supportsPartialRenderingProperty = scriptManagerType.GetProperty("SupportsPartialRendering");
if (supportsPartialRenderingProperty != null) {
object supportsPartialRenderingValue = supportsPartialRenderingProperty.GetValue(scriptManager, null);
_pageFlags[isPartialRenderingSupported] = (bool)supportsPartialRenderingValue;
}
}
}
_pageFlags[isPartialRenderingSupportedSet] = true;
}
return _pageFlags[isPartialRenderingSupported];
}
}
internal Type ScriptManagerType {
get {
if (_scriptManagerType == null) {
_scriptManagerType = BuildManager.GetType("System.Web.UI.ScriptManager", false);
}
return _scriptManagerType;
}
set {
// Meant for unit testing
_scriptManagerType = value;
}
}
#endregion
#if DBG
// Temporary debugging method
/// <internalonly/>
/// <devdoc>
/// </devdoc>
public virtual void WalkViewState(object viewState, Control control, int indentLevel) {
if (viewState == null) {
return;
}
object [] viewStateArray = (object [])viewState;
object controlViewState = viewStateArray[0];
IDictionary childViewState = (IDictionary)viewStateArray[1];
string prefix = "";
for (int i=0; i < indentLevel; i++) {
prefix = prefix + " ";
}
if (controlViewState == null) {
System.Web.Util.Debug.Trace("tpeters", prefix + "ObjViewState: null");
}
else {
System.Web.Util.Debug.Trace("tpeters", prefix + "ObjViewState: " + controlViewState.ToString());
}
if (childViewState != null) {
for (IDictionaryEnumerator e = childViewState.GetEnumerator(); e.MoveNext();) {
int index = (int) e.Key;
object value = e.Value;
if (control == null) {
System.Web.Util.Debug.Trace("tpeters", prefix + "Control index: " + index.ToString());
WalkViewState(value, null, indentLevel + 1);
}
else {
string s = "None";
bool recurse = false;
if (control.HasControls()) {
if (index < control.Controls.Count) {
s = control.Controls[index].ToString();
recurse = true;
}
else {
s = "out of range";
}
}
System.Web.Util.Debug.Trace("tpeters", prefix + "Control index: " + index.ToString() + " control: " + s);
if (recurse) {
WalkViewState(value, control.Controls[index], indentLevel + 1);
}
}
}
}
}
#endif // DBG
}
// Used to define the list of valid values of the location attribute of the
// OutputCache directive.
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public enum OutputCacheLocation {
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Any,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Client,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Downstream,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
Server,
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
None,
ServerAndClient
}
internal enum SmartNavigationSupport {
NotDesiredOrSupported=0, // The Page does not ask for SmartNav, or the browser doesn't support it
Desired, // The Page asks for SmartNavigation, but we have not checked browser support
IE6OrNewer // SmartNavigation supported by IE6 or newer browsers
}
}
|