2014-08-13 10:39:27 +01:00
//
// System.Web.HttpApplication.cs
//
// Author:
// Miguel de Icaza (miguel@novell.com)
// Gonzalo Paniagua (gonzalo@ximian.com)
2015-08-26 07:17:56 -04:00
// Matthias Bogad (bogad@cs.tum.edu)
//
2014-08-13 10:39:27 +01:00
//
// Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// The Application Processing Pipeline.
//
// The Http application pipeline implemented in this file is a
// beautiful thing. The application pipeline invokes a number of
// hooks at various stages of the processing of a request. These
// hooks can be either synchronous or can be asynchronous.
//
// The pipeline must ensure that every step is completed before
// moving to the next step. A trivial thing for synchronous
// hooks, but asynchronous hooks introduce an extra layer of
// complexity: when the hook is invoked, the thread must
// relinquish its control so that the thread can be reused in
// another operation while waiting.
//
// To implement this functionality we used C# iterators manually;
// we drive the pipeline by executing the various hooks from the
// `RunHooks' routine which is an enumerator that will yield the
// value `false' if execution must proceed or `true' if execution
// must be stopped.
//
// By yielding values we can suspend execution of RunHooks.
//
// Special attention must be given to `in_begin' and `must_yield'
// variables. These are used in the case that an async hook
// completes synchronously as its important to not yield in that
// case or we would hang.
//
// Many of Mono modules used to be declared async, but they would
// actually be completely synchronous, this might resurface in the
// future with other modules.
//
// TODO:
// Events Disposed
//
2015-08-26 07:17:56 -04:00
using System ;
2014-08-13 10:39:27 +01:00
using System.IO ;
using System.Collections ;
2015-08-26 07:17:56 -04:00
using System.Collections.Generic ;
2014-08-13 10:39:27 +01:00
using System.ComponentModel ;
using System.Configuration ;
using System.Diagnostics ;
using System.Globalization ;
using System.Reflection ;
using System.Security.Permissions ;
using System.Security.Principal ;
using System.Threading ;
using System.Web.Caching ;
using System.Web.Compilation ;
using System.Web.Configuration ;
using System.Web.Management ;
using System.Web.SessionState ;
using System.Web.UI ;
using System.Web.Util ;
namespace System.Web
{
// CAS
[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
[AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
// attributes
[ToolboxItem(false)]
public class HttpApplication : IHttpAsyncHandler , IHttpHandler , IComponent , IDisposable
{
static readonly object disposedEvent = new object ( ) ;
static readonly object errorEvent = new object ( ) ;
// we do this static rather than per HttpApplication because
// mono's perfcounters use the counter instance parameter for
// the process to access shared memory.
internal static PerformanceCounter requests_total_counter = new PerformanceCounter ( "ASP.NET" , "Requests Total" ) ;
internal static readonly string [ ] BinDirs = { "Bin" , "bin" } ;
object this_lock = new object ( ) ;
HttpContext context ;
HttpSessionState session ;
ISite isite ;
// The source, and the exposed API (cache).
volatile HttpModuleCollection modcoll ;
string assemblyLocation ;
//
// The factory for the handler currently running.
//
IHttpHandlerFactory factory ;
//
// Whether the thread culture is to be auto-set.
// Used only in the 2.0 profile, always false for 1.x
//
bool autoCulture ;
bool autoUICulture ;
//
// Whether the pipeline should be stopped
//
bool stop_processing ;
//
// See https://bugzilla.novell.com/show_bug.cgi?id=381971
//
bool in_application_start ;
//
// The Pipeline
//
IEnumerator pipeline ;
// To flag when we are done processing a request from BeginProcessRequest.
ManualResetEvent done ;
// The current IAsyncResult for the running async request handler in the pipeline
AsyncRequestState begin_iar ;
// Tracks the current AsyncInvocation being dispatched
AsyncInvoker current_ai ;
EventHandlerList events ;
EventHandlerList nonApplicationEvents = new EventHandlerList ( ) ;
// Culture and IPrincipal
CultureInfo app_culture ;
CultureInfo appui_culture ;
CultureInfo prev_app_culture ;
CultureInfo prev_appui_culture ;
IPrincipal prev_user ;
static string binDirectory ;
static volatile Exception initialization_exception ;
bool removeConfigurationFromCache ;
bool fullInitComplete = false ;
2015-08-26 07:17:56 -04:00
static DynamicModuleManager dynamicModuleManeger = new DynamicModuleManager ( ) ;
2014-08-13 10:39:27 +01:00
//
// These are used to detect the case where the EndXXX method is invoked
// from within the BeginXXXX delegate, so we detect whether we kick the
// pipeline from here, or from the the RunHook routine
//
bool must_yield ;
bool in_begin ;
public virtual event EventHandler Disposed {
add { nonApplicationEvents . AddHandler ( disposedEvent , value ) ; }
remove { nonApplicationEvents . RemoveHandler ( disposedEvent , value ) ; }
}
public virtual event EventHandler Error {
add { nonApplicationEvents . AddHandler ( errorEvent , value ) ; }
remove { nonApplicationEvents . RemoveHandler ( errorEvent , value ) ; }
}
public HttpApplication ( )
{
done = new ManualResetEvent ( false ) ;
}
internal void InitOnce ( bool full_init )
{
if ( initialization_exception ! = null )
return ;
if ( modcoll ! = null )
return ;
lock ( this_lock ) {
if ( initialization_exception ! = null )
return ;
if ( modcoll ! = null )
return ;
bool mustNullContext = context = = null ;
try {
HttpModulesSection modules ;
modules = ( HttpModulesSection ) WebConfigurationManager . GetWebApplicationSection ( "system.web/httpModules" ) ;
HttpContext saved = HttpContext . Current ;
HttpContext . Current = new HttpContext ( new System . Web . Hosting . SimpleWorkerRequest ( String . Empty , String . Empty , new StringWriter ( ) ) ) ;
if ( context = = null )
context = HttpContext . Current ;
HttpModuleCollection coll = modules . LoadModules ( this ) ;
2015-08-26 07:17:56 -04:00
HttpModuleCollection dynMods = CreateDynamicModules ( ) ;
for ( int i = 0 ; i < dynMods . Count ; i + + ) {
coll . AddModule ( dynMods . GetKey ( i ) , dynMods . Get ( i ) ) ;
}
2014-08-13 10:39:27 +01:00
Interlocked . CompareExchange ( ref modcoll , coll , null ) ;
HttpContext . Current = saved ;
if ( full_init ) {
HttpApplicationFactory . AttachEvents ( this ) ;
Init ( ) ;
fullInitComplete = true ;
}
} catch ( Exception e ) {
initialization_exception = e ;
2015-01-13 10:44:36 +00:00
Console . Error . WriteLine ( "Exception while initOnce: " + e . ToString ( ) ) ;
// Once initialization_exception != null, we always respond with this exception
// You have to restart the HttpApplication to "unlock" it
Console . Error . WriteLine ( "Please restart your app to unlock it" ) ;
2014-08-13 10:39:27 +01:00
} finally {
if ( mustNullContext )
context = null ;
}
}
}
internal bool InApplicationStart {
get { return in_application_start ; }
set { in_application_start = value ; }
}
internal string AssemblyLocation {
get {
if ( assemblyLocation = = null )
assemblyLocation = GetType ( ) . Assembly . Location ;
return assemblyLocation ;
}
}
internal static Exception InitializationException {
get { return initialization_exception ; }
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public HttpApplicationState Application {
get {
return HttpApplicationFactory . ApplicationState ;
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public HttpContext Context {
get {
return context ;
}
}
protected EventHandlerList Events {
get {
if ( events = = null )
events = new EventHandlerList ( ) ;
return events ;
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public HttpModuleCollection Modules {
[AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
get {
if ( modcoll = = null )
modcoll = new HttpModuleCollection ( ) ;
return modcoll ;
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public HttpRequest Request {
get {
if ( context = = null )
throw HttpException . NewWithCode ( Locale . GetText ( "No context is available." ) , WebEventCodes . RuntimeErrorRequestAbort ) ;
if ( false = = HttpApplicationFactory . ContextAvailable )
throw HttpException . NewWithCode ( Locale . GetText ( "Request is not available in this context." ) , WebEventCodes . RuntimeErrorRequestAbort ) ;
return context . Request ;
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public HttpResponse Response {
get {
if ( context = = null )
throw HttpException . NewWithCode ( Locale . GetText ( "No context is available." ) , WebEventCodes . RuntimeErrorRequestAbort ) ;
if ( false = = HttpApplicationFactory . ContextAvailable )
throw HttpException . NewWithCode ( Locale . GetText ( "Response is not available in this context." ) , WebEventCodes . RuntimeErrorRequestAbort ) ;
return context . Response ;
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public HttpServerUtility Server {
get {
if ( context ! = null )
return context . Server ;
//
// This is so we can get the Server and call a few methods
// which are not context sensitive, see HttpServerUtilityTest
//
return new HttpServerUtility ( ( HttpContext ) null ) ;
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public HttpSessionState Session {
get {
// Only used for Session_End
if ( session ! = null )
return session ;
if ( context = = null )
throw HttpException . NewWithCode ( Locale . GetText ( "No context is available." ) , WebEventCodes . RuntimeErrorRequestAbort ) ;
HttpSessionState ret = context . Session ;
if ( ret = = null )
throw HttpException . NewWithCode ( Locale . GetText ( "Session state is not available in the context." ) , WebEventCodes . RuntimeErrorRequestAbort ) ;
return ret ;
}
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public ISite Site {
get { return isite ; }
set { isite = value ; }
}
[Browsable (false)]
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
public IPrincipal User {
get {
if ( context = = null )
throw new HttpException ( Locale . GetText ( "No context is available." ) ) ;
if ( context . User = = null )
throw new HttpException ( Locale . GetText ( "No currently authenticated user." ) ) ;
return context . User ;
}
}
static object PreSendRequestHeadersEvent = new object ( ) ;
public event EventHandler PreSendRequestHeaders
{
add { AddEventHandler ( PreSendRequestHeadersEvent , value ) ; }
remove { RemoveEventHandler ( PreSendRequestHeadersEvent , value ) ; }
}
internal void TriggerPreSendRequestHeaders ( )
{
EventHandler handler = Events [ PreSendRequestHeadersEvent ] as EventHandler ;
if ( handler ! = null )
handler ( this , EventArgs . Empty ) ;
}
static object PreSendRequestContentEvent = new object ( ) ;
public event EventHandler PreSendRequestContent
{
add { AddEventHandler ( PreSendRequestContentEvent , value ) ; }
remove { RemoveEventHandler ( PreSendRequestContentEvent , value ) ; }
}
internal void TriggerPreSendRequestContent ( )
{
EventHandler handler = Events [ PreSendRequestContentEvent ] as EventHandler ;
if ( handler ! = null )
handler ( this , EventArgs . Empty ) ;
}
static object AcquireRequestStateEvent = new object ( ) ;
public event EventHandler AcquireRequestState
{
add { AddEventHandler ( AcquireRequestStateEvent , value ) ; }
remove { RemoveEventHandler ( AcquireRequestStateEvent , value ) ; }
}
public void AddOnAcquireRequestStateAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
AcquireRequestState + = new EventHandler ( invoker . Invoke ) ;
}
static object AuthenticateRequestEvent = new object ( ) ;
public event EventHandler AuthenticateRequest
{
add { AddEventHandler ( AuthenticateRequestEvent , value ) ; }
remove { RemoveEventHandler ( AuthenticateRequestEvent , value ) ; }
}
public void AddOnAuthenticateRequestAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
AuthenticateRequest + = new EventHandler ( invoker . Invoke ) ;
}
static object AuthorizeRequestEvent = new object ( ) ;
public event EventHandler AuthorizeRequest
{
add { AddEventHandler ( AuthorizeRequestEvent , value ) ; }
remove { RemoveEventHandler ( AuthorizeRequestEvent , value ) ; }
}
public void AddOnAuthorizeRequestAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
AuthorizeRequest + = new EventHandler ( invoker . Invoke ) ;
}
static object BeginRequestEvent = new object ( ) ;
public event EventHandler BeginRequest
{
add {
// See https://bugzilla.novell.com/show_bug.cgi?id=381971
if ( InApplicationStart )
return ;
AddEventHandler ( BeginRequestEvent , value ) ;
}
remove {
if ( InApplicationStart )
return ;
RemoveEventHandler ( BeginRequestEvent , value ) ;
}
}
public void AddOnBeginRequestAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
BeginRequest + = new EventHandler ( invoker . Invoke ) ;
}
static object EndRequestEvent = new object ( ) ;
public event EventHandler EndRequest
{
add {
// See https://bugzilla.novell.com/show_bug.cgi?id=381971
if ( InApplicationStart )
return ;
AddEventHandler ( EndRequestEvent , value ) ;
}
remove {
if ( InApplicationStart )
return ;
RemoveEventHandler ( EndRequestEvent , value ) ;
}
}
public void AddOnEndRequestAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
EndRequest + = new EventHandler ( invoker . Invoke ) ;
}
static object PostRequestHandlerExecuteEvent = new object ( ) ;
public event EventHandler PostRequestHandlerExecute
{
add { AddEventHandler ( PostRequestHandlerExecuteEvent , value ) ; }
remove { RemoveEventHandler ( PostRequestHandlerExecuteEvent , value ) ; }
}
public void AddOnPostRequestHandlerExecuteAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
PostRequestHandlerExecute + = new EventHandler ( invoker . Invoke ) ;
}
static object PreRequestHandlerExecuteEvent = new object ( ) ;
public event EventHandler PreRequestHandlerExecute
{
add { AddEventHandler ( PreRequestHandlerExecuteEvent , value ) ; }
remove { RemoveEventHandler ( PreRequestHandlerExecuteEvent , value ) ; }
}
public void AddOnPreRequestHandlerExecuteAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
PreRequestHandlerExecute + = new EventHandler ( invoker . Invoke ) ;
}
static object ReleaseRequestStateEvent = new object ( ) ;
public event EventHandler ReleaseRequestState
{
add { AddEventHandler ( ReleaseRequestStateEvent , value ) ; }
remove { RemoveEventHandler ( ReleaseRequestStateEvent , value ) ; }
}
public void AddOnReleaseRequestStateAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
ReleaseRequestState + = new EventHandler ( invoker . Invoke ) ;
}
static object ResolveRequestCacheEvent = new object ( ) ;
public event EventHandler ResolveRequestCache
{
add { AddEventHandler ( ResolveRequestCacheEvent , value ) ; }
remove { RemoveEventHandler ( ResolveRequestCacheEvent , value ) ; }
}
public void AddOnResolveRequestCacheAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
ResolveRequestCache + = new EventHandler ( invoker . Invoke ) ;
}
static object UpdateRequestCacheEvent = new object ( ) ;
public event EventHandler UpdateRequestCache
{
add { AddEventHandler ( UpdateRequestCacheEvent , value ) ; }
remove { RemoveEventHandler ( UpdateRequestCacheEvent , value ) ; }
}
public void AddOnUpdateRequestCacheAsync ( BeginEventHandler bh , EndEventHandler eh )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( bh , eh , this ) ;
2014-08-13 10:39:27 +01:00
UpdateRequestCache + = new EventHandler ( invoker . Invoke ) ;
}
static object PostAuthenticateRequestEvent = new object ( ) ;
public event EventHandler PostAuthenticateRequest
{
add { AddEventHandler ( PostAuthenticateRequestEvent , value ) ; }
remove { RemoveEventHandler ( PostAuthenticateRequestEvent , value ) ; }
}
public void AddOnPostAuthenticateRequestAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnPostAuthenticateRequestAsync ( bh , eh , null ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnPostAuthenticateRequestAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PostAuthenticateRequest + = new EventHandler ( invoker . Invoke ) ;
}
static object PostAuthorizeRequestEvent = new object ( ) ;
public event EventHandler PostAuthorizeRequest
{
add { AddEventHandler ( PostAuthorizeRequestEvent , value ) ; }
remove { RemoveEventHandler ( PostAuthorizeRequestEvent , value ) ; }
}
public void AddOnPostAuthorizeRequestAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnPostAuthorizeRequestAsync ( bh , eh , null ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnPostAuthorizeRequestAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PostAuthorizeRequest + = new EventHandler ( invoker . Invoke ) ;
}
static object PostResolveRequestCacheEvent = new object ( ) ;
public event EventHandler PostResolveRequestCache
{
add { AddEventHandler ( PostResolveRequestCacheEvent , value ) ; }
remove { RemoveEventHandler ( PostResolveRequestCacheEvent , value ) ; }
}
public void AddOnPostResolveRequestCacheAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnPostResolveRequestCacheAsync ( bh , eh , null ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnPostResolveRequestCacheAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PostResolveRequestCache + = new EventHandler ( invoker . Invoke ) ;
}
static object PostMapRequestHandlerEvent = new object ( ) ;
public event EventHandler PostMapRequestHandler
{
add { AddEventHandler ( PostMapRequestHandlerEvent , value ) ; }
remove { RemoveEventHandler ( PostMapRequestHandlerEvent , value ) ; }
}
public void AddOnPostMapRequestHandlerAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnPostMapRequestHandlerAsync ( bh , eh , null ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnPostMapRequestHandlerAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PostMapRequestHandler + = new EventHandler ( invoker . Invoke ) ;
}
static object PostAcquireRequestStateEvent = new object ( ) ;
public event EventHandler PostAcquireRequestState
{
add { AddEventHandler ( PostAcquireRequestStateEvent , value ) ; }
remove { RemoveEventHandler ( PostAcquireRequestStateEvent , value ) ; }
}
public void AddOnPostAcquireRequestStateAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnPostAcquireRequestStateAsync ( bh , eh , null ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnPostAcquireRequestStateAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PostAcquireRequestState + = new EventHandler ( invoker . Invoke ) ;
}
static object PostReleaseRequestStateEvent = new object ( ) ;
public event EventHandler PostReleaseRequestState
{
add { AddEventHandler ( PostReleaseRequestStateEvent , value ) ; }
remove { RemoveEventHandler ( PostReleaseRequestStateEvent , value ) ; }
}
public void AddOnPostReleaseRequestStateAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnPostReleaseRequestStateAsync ( bh , eh , null ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnPostReleaseRequestStateAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PostReleaseRequestState + = new EventHandler ( invoker . Invoke ) ;
}
static object PostUpdateRequestCacheEvent = new object ( ) ;
public event EventHandler PostUpdateRequestCache
{
add { AddEventHandler ( PostUpdateRequestCacheEvent , value ) ; }
remove { RemoveEventHandler ( PostUpdateRequestCacheEvent , value ) ; }
}
public void AddOnPostUpdateRequestCacheAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnPostUpdateRequestCacheAsync ( bh , eh , null ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnPostUpdateRequestCacheAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PostUpdateRequestCache + = new EventHandler ( invoker . Invoke ) ;
}
//
// The new overloads that take a data parameter
//
2016-02-22 11:00:01 -05:00
public void AddOnAcquireRequestStateAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
AcquireRequestState + = new EventHandler ( invoker . Invoke ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnAuthenticateRequestAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
AuthenticateRequest + = new EventHandler ( invoker . Invoke ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnAuthorizeRequestAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
AuthorizeRequest + = new EventHandler ( invoker . Invoke ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnBeginRequestAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
BeginRequest + = new EventHandler ( invoker . Invoke ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnEndRequestAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
EndRequest + = new EventHandler ( invoker . Invoke ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnPostRequestHandlerExecuteAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PostRequestHandlerExecute + = new EventHandler ( invoker . Invoke ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnPreRequestHandlerExecuteAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PreRequestHandlerExecute + = new EventHandler ( invoker . Invoke ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnReleaseRequestStateAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
ReleaseRequestState + = new EventHandler ( invoker . Invoke ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnResolveRequestCacheAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
ResolveRequestCache + = new EventHandler ( invoker . Invoke ) ;
}
2016-02-22 11:00:01 -05:00
public void AddOnUpdateRequestCacheAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
2014-08-13 10:39:27 +01:00
{
2016-02-22 11:00:01 -05:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
UpdateRequestCache + = new EventHandler ( invoker . Invoke ) ;
}
// Added in 2.0 SP1
// They are for use with the IIS7 integrated mode, but have been added for
// compatibility
static object LogRequestEvent = new object ( ) ;
public event EventHandler LogRequest
{
add { AddEventHandler ( LogRequestEvent , value ) ; }
remove { RemoveEventHandler ( LogRequestEvent , value ) ; }
}
public void AddOnLogRequestAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnLogRequestAsync ( bh , eh , null ) ;
}
public void AddOnLogRequestAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
LogRequest + = new EventHandler ( invoker . Invoke ) ;
}
static object MapRequestHandlerEvent = new object ( ) ;
public event EventHandler MapRequestHandler
{
add { AddEventHandler ( MapRequestHandlerEvent , value ) ; }
remove { RemoveEventHandler ( MapRequestHandlerEvent , value ) ; }
}
public void AddOnMapRequestHandlerAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnMapRequestHandlerAsync ( bh , eh , null ) ;
}
public void AddOnMapRequestHandlerAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
MapRequestHandler + = new EventHandler ( invoker . Invoke ) ;
}
static object PostLogRequestEvent = new object ( ) ;
public event EventHandler PostLogRequest
{
add { AddEventHandler ( PostLogRequestEvent , value ) ; }
remove { RemoveEventHandler ( PostLogRequestEvent , value ) ; }
}
public void AddOnPostLogRequestAsync ( BeginEventHandler bh , EndEventHandler eh )
{
AddOnPostLogRequestAsync ( bh , eh , null ) ;
}
public void AddOnPostLogRequestAsync ( BeginEventHandler beginHandler , EndEventHandler endHandler , object state )
{
2015-08-26 07:17:56 -04:00
AsyncInvoker invoker = new AsyncInvoker ( beginHandler , endHandler , this , state ) ;
2014-08-13 10:39:27 +01:00
PostLogRequest + = new EventHandler ( invoker . Invoke ) ;
}
internal event EventHandler DefaultAuthentication ;
void AddEventHandler ( object key , EventHandler handler )
{
if ( fullInitComplete )
return ;
Events . AddHandler ( key , handler ) ;
}
void RemoveEventHandler ( object key , EventHandler handler )
{
if ( fullInitComplete )
return ;
Events . RemoveHandler ( key , handler ) ;
}
//
// Bypass all the event on the Http pipeline and go directly to EndRequest
//
public void CompleteRequest ( )
{
stop_processing = true ;
}
internal bool RequestCompleted {
set { stop_processing = value ; }
}
internal void DisposeInternal ( )
{
Dispose ( ) ;
HttpModuleCollection coll = new HttpModuleCollection ( ) ;
Interlocked . Exchange ( ref modcoll , coll ) ;
if ( coll ! = null ) {
for ( int i = coll . Count - 1 ; i > = 0 ; i - - ) {
coll . Get ( i ) . Dispose ( ) ;
}
coll = null ;
}
EventHandler eh = nonApplicationEvents [ disposedEvent ] as EventHandler ;
if ( eh ! = null )
eh ( this , EventArgs . Empty ) ;
done . Close ( ) ;
done = null ;
}
public virtual void Dispose ( )
{
}
public virtual string GetOutputCacheProviderName ( HttpContext context )
{
// LAMESPEC: doesn't throw ProviderException if context is null
return OutputCache . DefaultProviderName ;
}
public virtual string GetVaryByCustomString ( HttpContext context , string custom )
{
if ( custom = = null ) // Sigh
throw new NullReferenceException ( ) ;
if ( 0 = = String . Compare ( custom , "browser" , true , Helpers . InvariantCulture ) )
return context . Request . Browser . Type ;
return null ;
}
bool ShouldHandleException ( Exception e )
{
if ( e is ParseException )
return false ;
return true ;
}
//
// If we catch an error, queue this error
//
2015-08-26 07:17:56 -04:00
internal void ProcessError ( Exception e )
2014-08-13 10:39:27 +01:00
{
bool first = context . Error = = null ;
context . AddError ( e ) ;
if ( first & & ShouldHandleException ( e ) ) {
EventHandler eh = nonApplicationEvents [ errorEvent ] as EventHandler ;
if ( eh ! = null ) {
try {
eh ( this , EventArgs . Empty ) ;
if ( stop_processing )
context . ClearError ( ) ;
} catch ( ThreadAbortException taex ) {
context . ClearError ( ) ;
if ( FlagEnd . Value = = taex . ExceptionState | | HttpRuntime . DomainUnloading )
// This happens on Redirect(), End() and
// when unloading the AppDomain
Thread . ResetAbort ( ) ;
else
// This happens on Thread.Abort()
context . AddError ( taex ) ;
} catch ( Exception ee ) {
context . AddError ( ee ) ;
}
}
}
stop_processing = true ;
// we want to remove configuration from the cache in case of
// invalid resource not exists to prevent DOS attack.
HttpException httpEx = e as HttpException ;
if ( httpEx ! = null & & httpEx . GetHttpCode ( ) = = 404 ) {
removeConfigurationFromCache = true ;
}
}
//
// Ticks the clock: next step on the pipeline.
//
internal void Tick ( )
{
try {
if ( pipeline . MoveNext ( ) ) {
if ( ( bool ) pipeline . Current )
PipelineDone ( ) ;
}
} catch ( ThreadAbortException taex ) {
object obj = taex . ExceptionState ;
Thread . ResetAbort ( ) ;
if ( obj is StepTimeout )
ProcessError ( HttpException . NewWithCode ( "The request timed out." , WebEventCodes . RequestTransactionAbort ) ) ;
else {
context . ClearError ( ) ;
if ( FlagEnd . Value ! = obj & & ! HttpRuntime . DomainUnloading )
context . AddError ( taex ) ;
}
stop_processing = true ;
PipelineDone ( ) ;
} catch ( Exception e ) {
ThreadAbortException inner = e . InnerException as ThreadAbortException ;
if ( inner ! = null & & FlagEnd . Value = = inner . ExceptionState & & ! HttpRuntime . DomainUnloading ) {
context . ClearError ( ) ;
Thread . ResetAbort ( ) ;
} else {
ProcessError ( e ) ;
}
stop_processing = true ;
PipelineDone ( ) ;
}
}
void Resume ( )
{
if ( in_begin )
must_yield = false ;
else
Tick ( ) ;
}
//
// Invoked when our async callback called from RunHooks completes,
// we restart the pipeline here.
//
void async_callback_completed_cb ( IAsyncResult ar )
{
if ( current_ai . end ! = null ) {
try {
current_ai . end ( ar ) ;
} catch ( Exception e ) {
ProcessError ( e ) ;
}
}
Resume ( ) ;
}
void async_handler_complete_cb ( IAsyncResult ar )
{
IHttpAsyncHandler async_handler = ar ! = null ? ar . AsyncState as IHttpAsyncHandler : null ;
try {
if ( async_handler ! = null )
async_handler . EndProcessRequest ( ar ) ;
} catch ( Exception e ) {
ProcessError ( e ) ;
}
Resume ( ) ;
}
//
// This enumerator yields whether processing must be stopped:
// true: processing of the pipeline must be stopped
// false: processing of the pipeline must not be stopped
//
IEnumerable RunHooks ( Delegate list )
{
Delegate [ ] delegates = list . GetInvocationList ( ) ;
foreach ( EventHandler d in delegates ) {
if ( d . Target ! = null & & ( d . Target is AsyncInvoker ) ) {
current_ai = ( AsyncInvoker ) d . Target ;
try {
must_yield = true ;
in_begin = true ;
context . BeginTimeoutPossible ( ) ;
current_ai . begin ( this , EventArgs . Empty , async_callback_completed_cb , current_ai . data ) ;
} finally {
in_begin = false ;
context . EndTimeoutPossible ( ) ;
}
//
// If things are still moving forward, yield this
// thread now
//
if ( must_yield )
yield return stop_processing ;
else if ( stop_processing )
yield return true ;
} else {
try {
context . BeginTimeoutPossible ( ) ;
d ( this , EventArgs . Empty ) ;
} finally {
context . EndTimeoutPossible ( ) ;
}
if ( stop_processing )
yield return true ;
}
}
}
static void FinalErrorWrite ( HttpResponse response , string error )
{
try {
response . Write ( error ) ;
response . Flush ( true ) ;
} catch {
response . Close ( ) ;
}
}
void OutputPage ( )
{
if ( context . Error = = null ) {
try {
context . Response . Flush ( true ) ;
} catch ( Exception e ) {
context . AddError ( e ) ;
}
}
Exception error = context . Error ;
if ( error ! = null ) {
HttpResponse response = context . Response ;
if ( ! response . HeadersSent ) {
response . ClearHeaders ( ) ;
response . ClearContent ( ) ;
if ( error is HttpException ) {
response . StatusCode = ( ( HttpException ) error ) . GetHttpCode ( ) ;
} else {
error = HttpException . NewWithCode ( String . Empty , error , WebEventCodes . WebErrorOtherError ) ;
response . StatusCode = 500 ;
}
HttpException httpEx = ( HttpException ) error ;
if ( ! RedirectCustomError ( ref httpEx ) )
FinalErrorWrite ( response , httpEx . GetHtmlErrorMessage ( ) ) ;
else
response . Flush ( true ) ;
} else {
if ( ! ( error is HttpException ) )
error = HttpException . NewWithCode ( String . Empty , error , WebEventCodes . WebErrorOtherError ) ;
FinalErrorWrite ( response , ( ( HttpException ) error ) . GetHtmlErrorMessage ( ) ) ;
}
}
}
//
// Invoked at the end of the pipeline execution
//
void PipelineDone ( )
{
try {
EventHandler handler = Events [ EndRequestEvent ] as EventHandler ;
if ( handler ! = null )
handler ( this , EventArgs . Empty ) ;
} catch ( Exception e ) {
ProcessError ( e ) ;
}
try {
OutputPage ( ) ;
} catch ( ThreadAbortException taex ) {
ProcessError ( taex ) ;
Thread . ResetAbort ( ) ;
} catch ( Exception e ) {
Console . WriteLine ( "Internal error: OutputPage threw an exception " + e ) ;
} finally {
context . WorkerRequest . EndOfRequest ( ) ;
if ( factory ! = null & & context . Handler ! = null ) {
factory . ReleaseHandler ( context . Handler ) ;
context . Handler = null ;
factory = null ;
}
context . PopHandler ( ) ;
// context = null; -> moved to PostDone
pipeline = null ;
current_ai = null ;
}
PostDone ( ) ;
if ( begin_iar ! = null )
begin_iar . Complete ( ) ;
else
done . Set ( ) ;
requests_total_counter . Increment ( ) ;
}
class Tim {
string name ;
DateTime start ;
public Tim ( ) {
}
public Tim ( string name ) {
this . name = name ;
}
public string Name {
get { return name ; }
set { name = value ; }
}
public void Start ( ) {
start = DateTime . UtcNow ;
}
public void Stop ( ) {
Console . WriteLine ( "{0}: {1}ms" , name , ( DateTime . UtcNow - start ) . TotalMilliseconds ) ;
}
}
Tim tim ;
[Conditional ("PIPELINE_TIMER")]
void StartTimer ( string name )
{
if ( tim = = null )
tim = new Tim ( ) ;
tim . Name = name ;
tim . Start ( ) ;
}
[Conditional ("PIPELINE_TIMER")]
void StopTimer ( )
{
tim . Stop ( ) ;
}
//
// Events fired as described in `Http Runtime Support, HttpModules,
// Handling Public Events'
//
IEnumerator Pipeline ( )
{
Delegate eventHandler ;
if ( stop_processing )
yield return true ;
HttpRequest req = context . Request ;
if ( req ! = null )
req . Validate ( ) ;
context . MapRequestHandlerDone = false ;
StartTimer ( "BeginRequest" ) ;
eventHandler = Events [ BeginRequestEvent ] ;
if ( eventHandler ! = null ) {
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
}
StopTimer ( ) ;
StartTimer ( "AuthenticateRequest" ) ;
eventHandler = Events [ AuthenticateRequestEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "DefaultAuthentication" ) ;
if ( DefaultAuthentication ! = null )
foreach ( bool stop in RunHooks ( DefaultAuthentication ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "PostAuthenticateRequest" ) ;
eventHandler = Events [ PostAuthenticateRequestEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "AuthorizeRequest" ) ;
eventHandler = Events [ AuthorizeRequestEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "PostAuthorizeRequest" ) ;
eventHandler = Events [ PostAuthorizeRequestEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "ResolveRequestCache" ) ;
eventHandler = Events [ ResolveRequestCacheEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "PostResolveRequestCache" ) ;
eventHandler = Events [ PostResolveRequestCacheEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "MapRequestHandler" ) ;
// As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
eventHandler = Events [ MapRequestHandlerEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
context . MapRequestHandlerDone = true ;
StartTimer ( "GetHandler" ) ;
// Obtain the handler for the request.
IHttpHandler handler = null ;
try {
handler = GetHandler ( context , context . Request . CurrentExecutionFilePath ) ;
context . Handler = handler ;
context . PushHandler ( handler ) ;
} catch ( FileNotFoundException fnf ) {
if ( context . Request . IsLocal )
ProcessError ( HttpException . NewWithCode ( 404 ,
String . Format ( "File not found {0}" , fnf . FileName ) ,
fnf ,
context . Request . FilePath ,
WebEventCodes . RuntimeErrorRequestAbort ) ) ;
else
ProcessError ( HttpException . NewWithCode ( 404 ,
"File not found: " + Path . GetFileName ( fnf . FileName ) ,
context . Request . FilePath ,
WebEventCodes . RuntimeErrorRequestAbort ) ) ;
} catch ( DirectoryNotFoundException dnf ) {
if ( ! context . Request . IsLocal )
dnf = null ; // Do not "leak" real path information
ProcessError ( HttpException . NewWithCode ( 404 , "Directory not found" , dnf , WebEventCodes . RuntimeErrorRequestAbort ) ) ;
} catch ( Exception e ) {
ProcessError ( e ) ;
}
StopTimer ( ) ;
if ( stop_processing )
yield return true ;
StartTimer ( "PostMapRequestHandler" ) ;
eventHandler = Events [ PostMapRequestHandlerEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "AcquireRequestState" ) ;
eventHandler = Events [ AcquireRequestStateEvent ] ;
if ( eventHandler ! = null ) {
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
}
StopTimer ( ) ;
StartTimer ( "PostAcquireRequestState" ) ;
eventHandler = Events [ PostAcquireRequestStateEvent ] ;
if ( eventHandler ! = null ) {
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
}
StopTimer ( ) ;
//
// From this point on, we need to ensure that we call
// ReleaseRequestState, so the code below jumps to
// `release:' to guarantee it rather than yielding.
//
StartTimer ( "PreRequestHandlerExecute" ) ;
eventHandler = Events [ PreRequestHandlerExecuteEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
if ( stop )
goto release ;
StopTimer ( ) ;
IHttpHandler ctxHandler = context . Handler ;
if ( ctxHandler ! = null & & handler ! = ctxHandler ) {
context . PopHandler ( ) ;
handler = ctxHandler ;
context . PushHandler ( handler ) ;
}
StartTimer ( "ProcessRequest" ) ;
try {
context . BeginTimeoutPossible ( ) ;
if ( handler ! = null ) {
IHttpAsyncHandler async_handler = handler as IHttpAsyncHandler ;
if ( async_handler ! = null ) {
must_yield = true ;
in_begin = true ;
async_handler . BeginProcessRequest ( context , async_handler_complete_cb , handler ) ;
} else {
must_yield = false ;
handler . ProcessRequest ( context ) ;
}
} else
throw new InvalidOperationException ( "No handler for the current request." ) ;
if ( context . Error ! = null )
throw new TargetInvocationException ( context . Error ) ;
} finally {
in_begin = false ;
context . EndTimeoutPossible ( ) ;
}
StopTimer ( ) ;
if ( must_yield )
yield return stop_processing ;
else if ( stop_processing )
goto release ;
// These are executed after the application has returned
StartTimer ( "PostRequestHandlerExecute" ) ;
eventHandler = Events [ PostRequestHandlerExecuteEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
if ( stop )
goto release ;
StopTimer ( ) ;
release :
StartTimer ( "ReleaseRequestState" ) ;
eventHandler = Events [ ReleaseRequestStateEvent ] ;
if ( eventHandler ! = null ) {
#pragma warning disable 219
foreach ( bool stop in RunHooks ( eventHandler ) ) {
//
// Ignore the stop signal while release the state
//
}
#pragma warning restore 219
}
StopTimer ( ) ;
if ( stop_processing )
yield return true ;
StartTimer ( "PostReleaseRequestState" ) ;
eventHandler = Events [ PostReleaseRequestStateEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "Filter" ) ;
if ( context . Error = = null )
context . Response . DoFilter ( true ) ;
StopTimer ( ) ;
StartTimer ( "UpdateRequestCache" ) ;
eventHandler = Events [ UpdateRequestCacheEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "PostUpdateRequestCache" ) ;
eventHandler = Events [ PostUpdateRequestCacheEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "LogRequest" ) ;
eventHandler = Events [ LogRequestEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "PostLogRequest" ) ;
eventHandler = Events [ PostLogRequestEvent ] ;
if ( eventHandler ! = null )
foreach ( bool stop in RunHooks ( eventHandler ) )
yield return stop ;
StopTimer ( ) ;
StartTimer ( "PipelineDone" ) ;
PipelineDone ( ) ;
StopTimer ( ) ;
}
internal CultureInfo GetThreadCulture ( HttpRequest request , CultureInfo culture , bool isAuto )
{
if ( ! isAuto )
return culture ;
CultureInfo ret = null ;
string [ ] languages = request . UserLanguages ;
try {
if ( languages ! = null & & languages . Length > 0 )
ret = CultureInfo . CreateSpecificCulture ( languages [ 0 ] ) ;
} catch {
}
if ( ret = = null )
ret = culture ;
return ret ;
}
void PreStart ( )
{
GlobalizationSection cfg ;
cfg = ( GlobalizationSection ) WebConfigurationManager . GetSection ( "system.web/globalization" ) ;
app_culture = cfg . GetCulture ( ) ;
autoCulture = cfg . IsAutoCulture ;
appui_culture = cfg . GetUICulture ( ) ;
autoUICulture = cfg . IsAutoUICulture ;
context . StartTimeoutTimer ( ) ;
Thread th = Thread . CurrentThread ;
if ( app_culture ! = null ) {
prev_app_culture = th . CurrentCulture ;
CultureInfo new_app_culture = GetThreadCulture ( Request , app_culture , autoCulture ) ;
if ( ! new_app_culture . Equals ( Helpers . InvariantCulture ) )
th . CurrentCulture = new_app_culture ;
}
if ( appui_culture ! = null ) {
prev_appui_culture = th . CurrentUICulture ;
CultureInfo new_app_culture = GetThreadCulture ( Request , appui_culture , autoUICulture ) ;
if ( ! new_app_culture . Equals ( Helpers . InvariantCulture ) )
th . CurrentUICulture = new_app_culture ;
}
prev_user = Thread . CurrentPrincipal ;
}
void PostDone ( )
{
if ( removeConfigurationFromCache ) {
WebConfigurationManager . RemoveConfigurationFromCache ( context ) ;
removeConfigurationFromCache = false ;
}
Thread th = Thread . CurrentThread ;
if ( Thread . CurrentPrincipal ! = prev_user )
Thread . CurrentPrincipal = prev_user ;
if ( prev_appui_culture ! = null & & prev_appui_culture ! = th . CurrentUICulture )
th . CurrentUICulture = prev_appui_culture ;
if ( prev_app_culture ! = null & & prev_app_culture ! = th . CurrentCulture )
th . CurrentCulture = prev_app_culture ;
if ( context = = null )
context = HttpContext . Current ;
context . StopTimeoutTimer ( ) ;
context . Request . ReleaseResources ( ) ;
context . Response . ReleaseResources ( ) ;
context = null ;
session = null ;
HttpContext . Current = null ;
}
void Start ( object x )
{
var cultures = x as CultureInfo [ ] ;
if ( cultures ! = null & & cultures . Length = = 2 ) {
Thread ct = Thread . CurrentThread ;
ct . CurrentCulture = cultures [ 0 ] ;
ct . CurrentUICulture = cultures [ 1 ] ;
}
InitOnce ( true ) ;
if ( initialization_exception ! = null ) {
Exception e = initialization_exception ;
HttpException exc = HttpException . NewWithCode ( String . Empty , e , WebEventCodes . RuntimeErrorRequestAbort ) ;
2015-01-13 10:44:36 +00:00
context . Response . StatusCode = 500 ;
2014-08-13 10:39:27 +01:00
FinalErrorWrite ( context . Response , exc . GetHtmlErrorMessage ( ) ) ;
PipelineDone ( ) ;
return ;
}
HttpContext . Current = Context ;
PreStart ( ) ;
pipeline = Pipeline ( ) ;
Tick ( ) ;
}
const string HANDLER_CACHE = "@@HttpHandlerCache@@" ;
internal static Hashtable GetHandlerCache ( )
{
Cache cache = HttpRuntime . InternalCache ;
Hashtable ret = cache [ HANDLER_CACHE ] as Hashtable ;
if ( ret = = null ) {
ret = new Hashtable ( ) ;
cache . Insert ( HANDLER_CACHE , ret ) ;
}
return ret ;
}
internal static void ClearHandlerCache ( )
{
Hashtable cache = GetHandlerCache ( ) ;
cache . Clear ( ) ;
}
object LocateHandler ( HttpRequest req , string verb , string url )
{
Hashtable cache = GetHandlerCache ( ) ;
string id = String . Concat ( verb , url ) ;
object ret = cache [ id ] ;
if ( ret ! = null )
return ret ;
bool allowCache ;
HttpHandlersSection httpHandlersSection = WebConfigurationManager . GetSection ( "system.web/httpHandlers" , req . Path , req . Context ) as HttpHandlersSection ;
ret = httpHandlersSection . LocateHandler ( verb , url , out allowCache ) ;
IHttpHandler handler = ret as IHttpHandler ;
if ( allowCache & & handler ! = null & & handler . IsReusable )
cache [ id ] = ret ;
return ret ;
}
internal IHttpHandler GetHandler ( HttpContext context , string url )
{
return GetHandler ( context , url , false ) ;
}
// Used by HttpServerUtility.Execute
internal IHttpHandler GetHandler ( HttpContext context , string url , bool ignoreContextHandler )
{
if ( ! ignoreContextHandler & & context . Handler ! = null )
return context . Handler ;
HttpRequest request = context . Request ;
string verb = request . RequestType ;
IHttpHandler handler = null ;
object o = LocateHandler ( request , verb , url ) ;
factory = o as IHttpHandlerFactory ;
if ( factory = = null ) {
handler = ( IHttpHandler ) o ;
} else {
handler = factory . GetHandler ( context , verb , url , request . MapPath ( url ) ) ;
}
return handler ;
}
void IHttpHandler . ProcessRequest ( HttpContext context )
{
begin_iar = null ;
this . context = context ;
done . Reset ( ) ;
Start ( null ) ;
done . WaitOne ( ) ;
}
//
// This is used by FireOnAppStart, when we init the application
// as the context is required to be set at that point (the user
// might call methods that require it on that hook).
//
internal void SetContext ( HttpContext context )
{
this . context = context ;
}
internal void SetSession ( HttpSessionState session )
{
this . session = session ;
}
IAsyncResult IHttpAsyncHandler . BeginProcessRequest ( HttpContext context , AsyncCallback cb , object extraData )
{
this . context = context ;
done . Reset ( ) ;
begin_iar = new AsyncRequestState ( done , cb , extraData ) ;
CultureInfo [ ] cultures = new CultureInfo [ 2 ] ;
cultures [ 0 ] = Thread . CurrentThread . CurrentCulture ;
cultures [ 1 ] = Thread . CurrentThread . CurrentUICulture ;
if ( Thread . CurrentThread . IsThreadPoolThread )
Start ( null ) ;
else
ThreadPool . QueueUserWorkItem ( x = > {
try {
Start ( x ) ;
} catch ( Exception e ) {
Console . Error . WriteLine ( e ) ;
}
} ) ;
return begin_iar ;
}
void IHttpAsyncHandler . EndProcessRequest ( IAsyncResult result )
{
if ( ! result . IsCompleted )
result . AsyncWaitHandle . WaitOne ( ) ;
begin_iar = null ;
}
public virtual void Init ( )
{
}
bool IHttpHandler . IsReusable {
get {
return true ;
}
}
2015-08-26 07:17:56 -04:00
public static void RegisterModule ( Type moduleType )
{
HttpRuntimeSection config = ( HttpRuntimeSection ) WebConfigurationManager . GetSection ( "system.web/httpRuntime" ) ;
if ( ! config . AllowDynamicModuleRegistration )
throw new InvalidOperationException ( "The Application has requested to register a dynamic Module, but dynamic module registration is disabled in web.config." ) ;
dynamicModuleManeger . Add ( moduleType ) ;
}
HttpModuleCollection CreateDynamicModules ( )
{
HttpModuleCollection modules = new HttpModuleCollection ( ) ;
foreach ( var module in dynamicModuleManeger . LockAndGetModules ( ) ) {
IHttpModule httpModule = CreateModuleInstance ( module . Type ) ;
httpModule . Init ( this ) ;
modules . AddModule ( module . Name , httpModule ) ;
}
return modules ;
}
IHttpModule CreateModuleInstance ( Type type )
{
return ( IHttpModule ) Activator . CreateInstance ( type ,
BindingFlags . Instance | BindingFlags . NonPublic | BindingFlags . Public | BindingFlags . CreateInstance ,
null ,
null ,
null ) ;
}
2014-08-13 10:39:27 +01:00
#region internals
internal void ClearError ( )
{
context . ClearError ( ) ;
}
bool RedirectErrorPage ( string error_page )
{
if ( context . Request . QueryString [ "aspxerrorpath" ] ! = null )
return false ;
Response . Redirect ( error_page + "?aspxerrorpath=" + Request . Path , false ) ;
return true ;
}
bool RedirectCustomError ( ref HttpException httpEx )
{
try {
if ( ! context . IsCustomErrorEnabledUnsafe )
return false ;
CustomErrorsSection config = ( CustomErrorsSection ) WebConfigurationManager . GetSection ( "system.web/customErrors" ) ;
if ( config = = null ) {
if ( context . ErrorPage ! = null )
return RedirectErrorPage ( context . ErrorPage ) ;
return false ;
}
CustomError err = config . Errors [ context . Response . StatusCode . ToString ( ) ] ;
string redirect = err = = null ? null : err . Redirect ;
if ( redirect = = null ) {
redirect = context . ErrorPage ;
if ( redirect = = null )
redirect = config . DefaultRedirect ;
}
if ( redirect = = null )
return false ;
if ( config . RedirectMode = = CustomErrorsRedirectMode . ResponseRewrite ) {
context . Server . Execute ( redirect ) ;
return true ;
}
return RedirectErrorPage ( redirect ) ;
}
catch ( Exception ex ) {
httpEx = HttpException . NewWithCode ( 500 , String . Empty , ex , WebEventCodes . WebErrorOtherError ) ;
return false ;
}
}
#endregion
internal static string BinDirectory
{
get {
if ( binDirectory = = null ) {
AppDomainSetup setup = AppDomain . CurrentDomain . SetupInformation ;
string baseDir = setup . ApplicationBase ;
string bindir ;
foreach ( string dir in BinDirs ) {
bindir = Path . Combine ( baseDir , dir ) ;
if ( ! Directory . Exists ( bindir ) )
continue ;
binDirectory = bindir ;
break ;
}
}
return binDirectory ;
}
}
internal static string [ ] BinDirectoryAssemblies
{
get {
ArrayList binDlls = null ;
string [ ] dlls ;
string bindir = BinDirectory ;
if ( bindir ! = null ) {
binDlls = new ArrayList ( ) ;
dlls = Directory . GetFiles ( bindir , "*.dll" ) ;
binDlls . AddRange ( dlls ) ;
}
if ( binDlls = = null )
return new string [ ] { } ;
return ( string [ ] ) binDlls . ToArray ( typeof ( string ) ) ;
}
}
internal static Type LoadType ( string typeName )
{
return LoadType ( typeName , false ) ;
}
internal static Type LoadType ( string typeName , bool throwOnMissing )
{
Type type = Type . GetType ( typeName ) ;
if ( type ! = null )
return type ;
Assembly [ ] assemblies = AppDomain . CurrentDomain . GetAssemblies ( ) ;
foreach ( Assembly ass in assemblies ) {
type = ass . GetType ( typeName , false ) ;
if ( type ! = null )
return type ;
}
IList tla = System . Web . Compilation . BuildManager . TopLevelAssemblies ;
if ( tla ! = null & & tla . Count > 0 ) {
foreach ( Assembly asm in tla ) {
if ( asm = = null )
continue ;
type = asm . GetType ( typeName , false ) ;
if ( type ! = null )
return type ;
}
}
Exception loadException = null ;
try {
type = null ;
type = LoadTypeFromBin ( typeName ) ;
} catch ( Exception ex ) {
loadException = ex ;
}
if ( type ! = null )
return type ;
if ( throwOnMissing )
throw new TypeLoadException ( String . Format ( "Type '{0}' cannot be found" , typeName ) , loadException ) ;
return null ;
}
internal static Type LoadType < TBaseType > ( string typeName , bool throwOnMissing )
{
Type ret = LoadType ( typeName , throwOnMissing ) ;
if ( typeof ( TBaseType ) . IsAssignableFrom ( ret ) )
return ret ;
if ( throwOnMissing )
throw new TypeLoadException ( String . Format ( "Type '{0}' found but it doesn't derive from base type '{1}'." , typeName , typeof ( TBaseType ) ) ) ;
return null ;
}
internal static Type LoadTypeFromBin ( string typeName )
{
Type type = null ;
foreach ( string s in BinDirectoryAssemblies ) {
Assembly binA = null ;
try {
binA = Assembly . LoadFrom ( s ) ;
} catch ( FileLoadException ) {
// ignore
continue ;
} catch ( BadImageFormatException ) {
// ignore
continue ;
}
type = binA . GetType ( typeName , false ) ;
if ( type = = null )
continue ;
return type ;
}
return null ;
}
}
//
// Based on Fritz' Onion's AsyncRequestState class for asynchronous IHttpAsyncHandlers
//
class AsyncRequestState : IAsyncResult {
AsyncCallback cb ;
object cb_data ;
bool completed ;
ManualResetEvent complete_event = null ;
internal AsyncRequestState ( ManualResetEvent complete_event , AsyncCallback cb , object cb_data )
{
this . cb = cb ;
this . cb_data = cb_data ;
this . complete_event = complete_event ;
}
internal void Complete ( )
{
completed = true ;
try {
//
// TODO: if this throws an error, we have no way of reporting it
// Not really too bad, since the only failure might be
// `HttpRuntime.request_processed'.
//
if ( cb ! = null )
cb ( this ) ;
} catch {
}
complete_event . Set ( ) ;
}
public object AsyncState {
get {
return cb_data ;
}
}
public bool CompletedSynchronously {
get {
return false ;
}
}
public bool IsCompleted {
get {
return completed ;
}
}
public WaitHandle AsyncWaitHandle {
get {
return complete_event ;
}
}
}
#region Helper classes
//
// A wrapper to keep track of begin/end pairs
//
class AsyncInvoker {
public BeginEventHandler begin ;
public EndEventHandler end ;
public object data ;
2015-08-26 07:17:56 -04:00
HttpApplication app ;
AsyncCallback callback ;
2014-08-13 10:39:27 +01:00
2015-08-26 07:17:56 -04:00
public AsyncInvoker ( BeginEventHandler bh , EndEventHandler eh , HttpApplication a , object d )
2014-08-13 10:39:27 +01:00
{
begin = bh ;
end = eh ;
data = d ;
2015-08-26 07:17:56 -04:00
app = a ;
callback = new AsyncCallback ( doAsyncCallback ) ;
2014-08-13 10:39:27 +01:00
}
2015-08-26 07:17:56 -04:00
public AsyncInvoker ( BeginEventHandler bh , EndEventHandler eh , HttpApplication app ) : this ( bh , eh , app , null ) { }
2014-08-13 10:39:27 +01:00
public void Invoke ( object sender , EventArgs e )
{
2015-08-26 07:17:56 -04:00
IAsyncResult res ;
res = begin ( app , e , callback , data ) ;
}
void doAsyncCallback ( IAsyncResult res )
{
ThreadPool . QueueUserWorkItem ( ( object ores ) = > {
IAsyncResult tres = ( IAsyncResult ) ores ;
try {
end ( tres ) ;
} catch ( Exception ee ) {
// I tried using ProcessError(), but we only come here frome an Invokation in PipelineDone().
// Using ProcessError, I still get a blank screen, this way, we at least log the error to console...
Console . Error . WriteLine ( ee . ToString ( ) ) ;
}
} , res ) ;
2014-08-13 10:39:27 +01:00
}
}
#endregion
}
2015-08-26 07:17:56 -04:00