2 // System.Web.HttpApplication.cs
5 // Miguel de Icaza (miguel@novell.com)
6 // Gonzalo Paniagua (gonzalo@ximian.com)
9 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 // The Application Processing Pipeline.
32 // The Http application pipeline implemented in this file is a
33 // beautiful thing. The application pipeline invokes a number of
34 // hooks at various stages of the processing of a request. These
35 // hooks can be either synchronous or can be asynchronous.
37 // The pipeline must ensure that every step is completed before
38 // moving to the next step. A trivial thing for synchronous
39 // hooks, but asynchronous hooks introduce an extra layer of
40 // complexity: when the hook is invoked, the thread must
41 // relinquish its control so that the thread can be reused in
42 // another operation while waiting.
44 // To implement this functionality we used C# iterators manually;
45 // we drive the pipeline by executing the various hooks from the
46 // `RunHooks' routine which is an enumerator that will yield the
47 // value `false' if execution must proceed or `true' if execution
50 // By yielding values we can suspend execution of RunHooks.
52 // Special attention must be given to `in_begin' and `must_yield'
53 // variables. These are used in the case that an async hook
54 // completes synchronously as its important to not yield in that
55 // case or we would hang.
57 // Many of Mono modules used to be declared async, but they would
58 // actually be completely synchronous, this might resurface in the
59 // future with other modules.
66 using System.Collections;
67 using System.ComponentModel;
68 using System.Configuration;
69 using System.Diagnostics;
70 using System.Globalization;
71 using System.Reflection;
72 using System.Security.Permissions;
73 using System.Security.Principal;
74 using System.Threading;
75 using System.Web.Caching;
76 using System.Web.Compilation;
77 using System.Web.Configuration;
78 using System.Web.Management;
79 using System.Web.SessionState;
81 using System.Web.Util;
90 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
91 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
94 public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
96 static readonly object disposedEvent = new object ();
97 static readonly object errorEvent = new object ();
99 // we do this static rather than per HttpApplication because
100 // mono's perfcounters use the counter instance parameter for
101 // the process to access shared memory.
102 internal static PerformanceCounter requests_total_counter = new PerformanceCounter ("ASP.NET", "Requests Total");
104 internal static readonly string [] BinDirs = {"Bin", "bin"};
105 object this_lock = new object();
108 HttpSessionState session;
111 // The source, and the exposed API (cache).
112 volatile HttpModuleCollection modcoll;
114 string assemblyLocation;
117 // The factory for the handler currently running.
119 IHttpHandlerFactory factory;
122 // Whether the thread culture is to be auto-set.
123 // Used only in the 2.0 profile, always false for 1.x
129 // Whether the pipeline should be stopped
131 bool stop_processing;
134 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
136 bool in_application_start;
141 IEnumerator pipeline;
143 // To flag when we are done processing a request from BeginProcessRequest.
144 ManualResetEvent done;
146 // The current IAsyncResult for the running async request handler in the pipeline
147 AsyncRequestState begin_iar;
149 // Tracks the current AsyncInvocation being dispatched
150 AsyncInvoker current_ai;
152 EventHandlerList events;
153 EventHandlerList nonApplicationEvents = new EventHandlerList ();
155 // Culture and IPrincipal
156 CultureInfo app_culture;
157 CultureInfo appui_culture;
158 CultureInfo prev_app_culture;
159 CultureInfo prev_appui_culture;
160 IPrincipal prev_user;
162 static string binDirectory;
165 const string initialization_exception_key = "System.Web.HttpApplication.initialization_exception";
166 static Exception initialization_exception {
167 get { return (Exception) AppDomain.CurrentDomain.GetData (initialization_exception_key); }
168 set { AppDomain.CurrentDomain.SetData (initialization_exception_key, value); }
171 static volatile Exception initialization_exception;
173 bool removeConfigurationFromCache;
174 bool fullInitComplete = false;
177 // These are used to detect the case where the EndXXX method is invoked
178 // from within the BeginXXXX delegate, so we detect whether we kick the
179 // pipeline from here, or from the the RunHook routine
184 public virtual event EventHandler Disposed {
185 add { nonApplicationEvents.AddHandler (disposedEvent, value); }
186 remove { nonApplicationEvents.RemoveHandler (disposedEvent, value); }
189 public virtual event EventHandler Error {
190 add { nonApplicationEvents.AddHandler (errorEvent, value); }
191 remove { nonApplicationEvents.RemoveHandler (errorEvent, value); }
194 public HttpApplication ()
196 done = new ManualResetEvent (false);
199 internal void InitOnce (bool full_init)
201 if (initialization_exception != null)
208 if (initialization_exception != null)
214 bool mustNullContext = context == null;
216 HttpModulesSection modules;
217 modules = (HttpModulesSection) WebConfigurationManager.GetWebApplicationSection ("system.web/httpModules");
218 HttpContext saved = HttpContext.Current;
219 HttpContext.Current = new HttpContext (new System.Web.Hosting.SimpleWorkerRequest (String.Empty, String.Empty, new StringWriter()));
221 context = HttpContext.Current;
222 HttpModuleCollection coll = modules.LoadModules (this);
223 Interlocked.CompareExchange (ref modcoll, coll, null);
224 HttpContext.Current = saved;
227 HttpApplicationFactory.AttachEvents (this);
229 fullInitComplete = true;
231 } catch (Exception e) {
232 initialization_exception = e;
233 Console.Error.WriteLine("Exception while initOnce: "+e.ToString());
234 // Once initialization_exception != null, we always respond with this exception
235 // You have to restart the HttpApplication to "unlock" it
236 Console.Error.WriteLine("Please restart your app to unlock it");
244 internal bool InApplicationStart {
245 get { return in_application_start; }
246 set { in_application_start = value; }
249 internal string AssemblyLocation {
251 if (assemblyLocation == null)
252 assemblyLocation = GetType ().Assembly.Location;
253 return assemblyLocation;
257 internal static Exception InitializationException {
258 get { return initialization_exception; }
262 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
263 public HttpApplicationState Application {
265 return HttpApplicationFactory.ApplicationState;
270 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
271 public HttpContext Context {
277 protected EventHandlerList Events {
280 events = new EventHandlerList ();
287 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
288 public HttpModuleCollection Modules {
289 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
292 modcoll = new HttpModuleCollection ();
299 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
300 public HttpRequest Request {
303 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
305 if (false == HttpApplicationFactory.ContextAvailable)
306 throw HttpException.NewWithCode (Locale.GetText ("Request is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
308 return context.Request;
313 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
314 public HttpResponse Response {
317 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
319 if (false == HttpApplicationFactory.ContextAvailable)
320 throw HttpException.NewWithCode (Locale.GetText ("Response is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
322 return context.Response;
327 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
328 public HttpServerUtility Server {
331 return context.Server;
334 // This is so we can get the Server and call a few methods
335 // which are not context sensitive, see HttpServerUtilityTest
337 return new HttpServerUtility ((HttpContext) null);
342 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
343 public HttpSessionState Session {
345 // Only used for Session_End
350 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
352 HttpSessionState ret = context.Session;
354 throw HttpException.NewWithCode (Locale.GetText ("Session state is not available in the context."), WebEventCodes.RuntimeErrorRequestAbort);
361 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
363 get { return isite; }
365 set { isite = value; }
369 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
370 public IPrincipal User {
373 throw new HttpException (Locale.GetText ("No context is available."));
374 if (context.User == null)
375 throw new HttpException (Locale.GetText ("No currently authenticated user."));
381 static object PreSendRequestHeadersEvent = new object ();
382 public event EventHandler PreSendRequestHeaders
384 add { AddEventHandler (PreSendRequestHeadersEvent, value); }
385 remove { RemoveEventHandler (PreSendRequestHeadersEvent, value); }
388 internal void TriggerPreSendRequestHeaders ()
390 EventHandler handler = Events [PreSendRequestHeadersEvent] as EventHandler;
392 handler (this, EventArgs.Empty);
395 static object PreSendRequestContentEvent = new object ();
396 public event EventHandler PreSendRequestContent
398 add { AddEventHandler (PreSendRequestContentEvent, value); }
399 remove { RemoveEventHandler (PreSendRequestContentEvent, value); }
402 internal void TriggerPreSendRequestContent ()
404 EventHandler handler = Events [PreSendRequestContentEvent] as EventHandler;
406 handler (this, EventArgs.Empty);
409 static object AcquireRequestStateEvent = new object ();
410 public event EventHandler AcquireRequestState
412 add { AddEventHandler (AcquireRequestStateEvent, value); }
413 remove { RemoveEventHandler (AcquireRequestStateEvent, value); }
416 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
418 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
419 AcquireRequestState += new EventHandler (invoker.Invoke);
422 static object AuthenticateRequestEvent = new object ();
423 public event EventHandler AuthenticateRequest
425 add { AddEventHandler (AuthenticateRequestEvent, value); }
426 remove { RemoveEventHandler (AuthenticateRequestEvent, value); }
429 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
431 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
432 AuthenticateRequest += new EventHandler (invoker.Invoke);
435 static object AuthorizeRequestEvent = new object ();
436 public event EventHandler AuthorizeRequest
438 add { AddEventHandler (AuthorizeRequestEvent, value); }
439 remove { RemoveEventHandler (AuthorizeRequestEvent, value); }
442 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
444 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
445 AuthorizeRequest += new EventHandler (invoker.Invoke);
448 static object BeginRequestEvent = new object ();
449 public event EventHandler BeginRequest
452 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
453 if (InApplicationStart)
455 AddEventHandler (BeginRequestEvent, value);
458 if (InApplicationStart)
460 RemoveEventHandler (BeginRequestEvent, value);
464 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
466 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
467 BeginRequest += new EventHandler (invoker.Invoke);
470 static object EndRequestEvent = new object ();
471 public event EventHandler EndRequest
474 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
475 if (InApplicationStart)
477 AddEventHandler (EndRequestEvent, value);
480 if (InApplicationStart)
482 RemoveEventHandler (EndRequestEvent, value);
486 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
488 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
489 EndRequest += new EventHandler (invoker.Invoke);
492 static object PostRequestHandlerExecuteEvent = new object ();
493 public event EventHandler PostRequestHandlerExecute
495 add { AddEventHandler (PostRequestHandlerExecuteEvent, value); }
496 remove { RemoveEventHandler (PostRequestHandlerExecuteEvent, value); }
499 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
501 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
502 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
505 static object PreRequestHandlerExecuteEvent = new object ();
506 public event EventHandler PreRequestHandlerExecute
508 add { AddEventHandler (PreRequestHandlerExecuteEvent, value); }
509 remove { RemoveEventHandler (PreRequestHandlerExecuteEvent, value); }
512 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
514 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
515 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
518 static object ReleaseRequestStateEvent = new object ();
519 public event EventHandler ReleaseRequestState
521 add { AddEventHandler (ReleaseRequestStateEvent, value); }
522 remove { RemoveEventHandler (ReleaseRequestStateEvent, value); }
525 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
527 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
528 ReleaseRequestState += new EventHandler (invoker.Invoke);
531 static object ResolveRequestCacheEvent = new object ();
532 public event EventHandler ResolveRequestCache
534 add { AddEventHandler (ResolveRequestCacheEvent, value); }
535 remove { RemoveEventHandler (ResolveRequestCacheEvent, value); }
538 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
540 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
541 ResolveRequestCache += new EventHandler (invoker.Invoke);
544 static object UpdateRequestCacheEvent = new object ();
545 public event EventHandler UpdateRequestCache
547 add { AddEventHandler (UpdateRequestCacheEvent, value); }
548 remove { RemoveEventHandler (UpdateRequestCacheEvent, value); }
551 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
553 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
554 UpdateRequestCache += new EventHandler (invoker.Invoke);
557 static object PostAuthenticateRequestEvent = new object ();
558 public event EventHandler PostAuthenticateRequest
560 add { AddEventHandler (PostAuthenticateRequestEvent, value); }
561 remove { RemoveEventHandler (PostAuthenticateRequestEvent, value); }
564 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
566 AddOnPostAuthenticateRequestAsync (bh, eh, null);
569 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
571 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
572 PostAuthenticateRequest += new EventHandler (invoker.Invoke);
575 static object PostAuthorizeRequestEvent = new object ();
576 public event EventHandler PostAuthorizeRequest
578 add { AddEventHandler (PostAuthorizeRequestEvent, value); }
579 remove { RemoveEventHandler (PostAuthorizeRequestEvent, value); }
582 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
584 AddOnPostAuthorizeRequestAsync (bh, eh, null);
587 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
589 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
590 PostAuthorizeRequest += new EventHandler (invoker.Invoke);
593 static object PostResolveRequestCacheEvent = new object ();
594 public event EventHandler PostResolveRequestCache
596 add { AddEventHandler (PostResolveRequestCacheEvent, value); }
597 remove { RemoveEventHandler (PostResolveRequestCacheEvent, value); }
600 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
602 AddOnPostResolveRequestCacheAsync (bh, eh, null);
605 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
607 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
608 PostResolveRequestCache += new EventHandler (invoker.Invoke);
611 static object PostMapRequestHandlerEvent = new object ();
612 public event EventHandler PostMapRequestHandler
614 add { AddEventHandler (PostMapRequestHandlerEvent, value); }
615 remove { RemoveEventHandler (PostMapRequestHandlerEvent, value); }
618 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
620 AddOnPostMapRequestHandlerAsync (bh, eh, null);
623 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh, object data)
625 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
626 PostMapRequestHandler += new EventHandler (invoker.Invoke);
629 static object PostAcquireRequestStateEvent = new object ();
630 public event EventHandler PostAcquireRequestState
632 add { AddEventHandler (PostAcquireRequestStateEvent, value); }
633 remove { RemoveEventHandler (PostAcquireRequestStateEvent, value); }
636 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
638 AddOnPostAcquireRequestStateAsync (bh, eh, null);
641 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
643 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
644 PostAcquireRequestState += new EventHandler (invoker.Invoke);
647 static object PostReleaseRequestStateEvent = new object ();
648 public event EventHandler PostReleaseRequestState
650 add { AddEventHandler (PostReleaseRequestStateEvent, value); }
651 remove { RemoveEventHandler (PostReleaseRequestStateEvent, value); }
654 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
656 AddOnPostReleaseRequestStateAsync (bh, eh, null);
659 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
661 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
662 PostReleaseRequestState += new EventHandler (invoker.Invoke);
665 static object PostUpdateRequestCacheEvent = new object ();
666 public event EventHandler PostUpdateRequestCache
668 add { AddEventHandler (PostUpdateRequestCacheEvent, value); }
669 remove { RemoveEventHandler (PostUpdateRequestCacheEvent, value); }
672 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
674 AddOnPostUpdateRequestCacheAsync (bh, eh, null);
677 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
679 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
680 PostUpdateRequestCache += new EventHandler (invoker.Invoke);
684 // The new overloads that take a data parameter
686 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
688 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
689 AcquireRequestState += new EventHandler (invoker.Invoke);
692 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
694 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
695 AuthenticateRequest += new EventHandler (invoker.Invoke);
698 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
700 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
701 AuthorizeRequest += new EventHandler (invoker.Invoke);
704 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
706 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
707 BeginRequest += new EventHandler (invoker.Invoke);
710 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
712 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
713 EndRequest += new EventHandler (invoker.Invoke);
716 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
718 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
719 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
722 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
724 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
725 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
728 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
730 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
731 ReleaseRequestState += new EventHandler (invoker.Invoke);
734 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
736 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
737 ResolveRequestCache += new EventHandler (invoker.Invoke);
740 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
742 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
743 UpdateRequestCache += new EventHandler (invoker.Invoke);
747 // They are for use with the IIS7 integrated mode, but have been added for
749 static object LogRequestEvent = new object ();
750 public event EventHandler LogRequest
752 add { AddEventHandler (LogRequestEvent, value); }
753 remove { RemoveEventHandler (LogRequestEvent, value); }
756 public void AddOnLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
758 AddOnLogRequestAsync (bh, eh, null);
761 public void AddOnLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
763 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
764 LogRequest += new EventHandler (invoker.Invoke);
767 static object MapRequestHandlerEvent = new object ();
768 public event EventHandler MapRequestHandler
770 add { AddEventHandler (MapRequestHandlerEvent, value); }
771 remove { RemoveEventHandler (MapRequestHandlerEvent, value); }
774 public void AddOnMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
776 AddOnMapRequestHandlerAsync (bh, eh, null);
779 public void AddOnMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
781 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
782 MapRequestHandler += new EventHandler (invoker.Invoke);
785 static object PostLogRequestEvent = new object ();
786 public event EventHandler PostLogRequest
788 add { AddEventHandler (PostLogRequestEvent, value); }
789 remove { RemoveEventHandler (PostLogRequestEvent, value); }
792 public void AddOnPostLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
794 AddOnPostLogRequestAsync (bh, eh, null);
797 public void AddOnPostLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
799 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
800 PostLogRequest += new EventHandler (invoker.Invoke);
803 internal event EventHandler DefaultAuthentication;
805 void AddEventHandler (object key, EventHandler handler)
807 if (fullInitComplete)
810 Events.AddHandler (key, handler);
813 void RemoveEventHandler (object key, EventHandler handler)
815 if (fullInitComplete)
818 Events.RemoveHandler (key, handler);
822 // Bypass all the event on the Http pipeline and go directly to EndRequest
824 public void CompleteRequest ()
826 stop_processing = true;
829 internal bool RequestCompleted {
830 set { stop_processing = value; }
833 internal void DisposeInternal ()
836 HttpModuleCollection coll = new HttpModuleCollection ();
837 Interlocked.Exchange (ref modcoll, coll);
839 for (int i = coll.Count - 1; i >= 0; i--) {
840 coll.Get (i).Dispose ();
845 EventHandler eh = nonApplicationEvents [disposedEvent] as EventHandler;
847 eh (this, EventArgs.Empty);
853 public virtual void Dispose ()
858 public virtual string GetOutputCacheProviderName (HttpContext context)
860 // LAMESPEC: doesn't throw ProviderException if context is null
861 return OutputCache.DefaultProviderName;
865 public virtual string GetVaryByCustomString (HttpContext context, string custom)
867 if (custom == null) // Sigh
868 throw new NullReferenceException ();
870 if (0 == String.Compare (custom, "browser", true, Helpers.InvariantCulture))
871 return context.Request.Browser.Type;
876 bool ShouldHandleException (Exception e)
878 if (e is ParseException)
885 // If we catch an error, queue this error
887 void ProcessError (Exception e)
889 bool first = context.Error == null;
890 context.AddError (e);
891 if (first && ShouldHandleException (e)) {
892 EventHandler eh = nonApplicationEvents [errorEvent] as EventHandler;
895 eh (this, EventArgs.Empty);
897 context.ClearError ();
898 } catch (ThreadAbortException taex){
899 context.ClearError ();
900 if (FlagEnd.Value == taex.ExceptionState || HttpRuntime.DomainUnloading)
901 // This happens on Redirect(), End() and
902 // when unloading the AppDomain
903 Thread.ResetAbort ();
905 // This happens on Thread.Abort()
906 context.AddError (taex);
907 } catch (Exception ee){
908 context.AddError (ee);
912 stop_processing = true;
914 // we want to remove configuration from the cache in case of
915 // invalid resource not exists to prevent DOS attack.
916 HttpException httpEx = e as HttpException;
917 if (httpEx != null && httpEx.GetHttpCode () == 404) {
918 removeConfigurationFromCache = true;
923 // Ticks the clock: next step on the pipeline.
925 internal void Tick ()
929 if (context.Error is UnifyRequestException) {
930 Exception ex = context.Error.InnerException;
931 context.ClearError ();
932 vmw.common.TypeUtils.Throw (ex);
936 if (pipeline.MoveNext ()){
937 if ((bool)pipeline.Current)
942 catch (Exception ex) {
943 if (ex is ThreadAbortException &&
944 ((ThreadAbortException) ex).ExceptionState == FlagEnd.Value)
946 if (context.WorkerRequest is IHttpUnifyWorkerRequest) {
947 context.ClearError ();
948 context.AddError (new UnifyRequestException (ex));
955 } catch (ThreadAbortException taex) {
956 object obj = taex.ExceptionState;
957 Thread.ResetAbort ();
958 if (obj is StepTimeout)
959 ProcessError (HttpException.NewWithCode ("The request timed out.", WebEventCodes.RequestTransactionAbort));
961 context.ClearError ();
962 if (FlagEnd.Value != obj && !HttpRuntime.DomainUnloading)
963 context.AddError (taex);
966 stop_processing = true;
968 } catch (Exception e) {
969 ThreadAbortException inner = e.InnerException as ThreadAbortException;
970 if (inner != null && FlagEnd.Value == inner.ExceptionState && !HttpRuntime.DomainUnloading) {
971 context.ClearError ();
972 Thread.ResetAbort ();
976 stop_processing = true;
990 // Invoked when our async callback called from RunHooks completes,
991 // we restart the pipeline here.
993 void async_callback_completed_cb (IAsyncResult ar)
995 if (current_ai.end != null){
998 } catch (Exception e) {
1006 void async_handler_complete_cb (IAsyncResult ar)
1008 IHttpAsyncHandler async_handler = ar != null ? ar.AsyncState as IHttpAsyncHandler : null;
1011 if (async_handler != null)
1012 async_handler.EndProcessRequest (ar);
1013 } catch (Exception e){
1021 // This enumerator yields whether processing must be stopped:
1022 // true: processing of the pipeline must be stopped
1023 // false: processing of the pipeline must not be stopped
1025 IEnumerable RunHooks (Delegate list)
1027 Delegate [] delegates = list.GetInvocationList ();
1029 foreach (EventHandler d in delegates){
1030 if (d.Target != null && (d.Target is AsyncInvoker)){
1031 current_ai = (AsyncInvoker) d.Target;
1036 context.BeginTimeoutPossible ();
1037 current_ai.begin (this, EventArgs.Empty, async_callback_completed_cb, current_ai.data);
1040 context.EndTimeoutPossible ();
1044 // If things are still moving forward, yield this
1048 yield return stop_processing;
1049 else if (stop_processing)
1053 context.BeginTimeoutPossible ();
1054 d (this, EventArgs.Empty);
1056 context.EndTimeoutPossible ();
1058 if (stop_processing)
1064 static void FinalErrorWrite (HttpResponse response, string error)
1067 response.Write (error);
1068 response.Flush (true);
1076 if (context.Error == null){
1078 context.Response.Flush (true);
1079 } catch (Exception e){
1080 context.AddError (e);
1084 Exception error = context.Error;
1086 HttpResponse response = context.Response;
1088 if (!response.HeadersSent){
1089 response.ClearHeaders ();
1090 response.ClearContent ();
1092 if (error is HttpException){
1093 response.StatusCode = ((HttpException)error).GetHttpCode ();
1095 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1096 response.StatusCode = 500;
1098 HttpException httpEx = (HttpException) error;
1099 if (!RedirectCustomError (ref httpEx))
1100 FinalErrorWrite (response, httpEx.GetHtmlErrorMessage ());
1102 response.Flush (true);
1104 if (!(error is HttpException))
1105 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1106 FinalErrorWrite (response, ((HttpException) error).GetHtmlErrorMessage ());
1113 // Invoked at the end of the pipeline execution
1115 void PipelineDone ()
1118 EventHandler handler = Events [EndRequestEvent] as EventHandler;
1119 if (handler != null)
1120 handler (this, EventArgs.Empty);
1121 } catch (Exception e){
1127 } catch (ThreadAbortException taex) {
1128 ProcessError (taex);
1129 Thread.ResetAbort ();
1130 } catch (Exception e) {
1131 Console.WriteLine ("Internal error: OutputPage threw an exception " + e);
1133 context.WorkerRequest.EndOfRequest();
1134 if (factory != null && context.Handler != null){
1135 factory.ReleaseHandler (context.Handler);
1136 context.Handler = null;
1139 context.PopHandler ();
1141 // context = null; -> moved to PostDone
1147 if (begin_iar != null)
1148 begin_iar.Complete ();
1152 requests_total_counter.Increment ();
1162 public Tim (string name) {
1166 public string Name {
1167 get { return name; }
1168 set { name = value; }
1171 public void Start () {
1172 start = DateTime.UtcNow;
1175 public void Stop () {
1176 Console.WriteLine ("{0}: {1}ms", name, (DateTime.UtcNow - start).TotalMilliseconds);
1181 [Conditional ("PIPELINE_TIMER")]
1182 void StartTimer (string name)
1190 [Conditional ("PIPELINE_TIMER")]
1197 // Events fired as described in `Http Runtime Support, HttpModules,
1198 // Handling Public Events'
1200 IEnumerator Pipeline ()
1202 Delegate eventHandler;
1203 if (stop_processing)
1206 HttpRequest req = context.Request;
1210 context.MapRequestHandlerDone = false;
1211 StartTimer ("BeginRequest");
1212 eventHandler = Events [BeginRequestEvent];
1213 if (eventHandler != null) {
1214 foreach (bool stop in RunHooks (eventHandler))
1219 StartTimer ("AuthenticateRequest");
1220 eventHandler = Events [AuthenticateRequestEvent];
1221 if (eventHandler != null)
1222 foreach (bool stop in RunHooks (eventHandler))
1226 StartTimer ("DefaultAuthentication");
1227 if (DefaultAuthentication != null)
1228 foreach (bool stop in RunHooks (DefaultAuthentication))
1232 StartTimer ("PostAuthenticateRequest");
1233 eventHandler = Events [PostAuthenticateRequestEvent];
1234 if (eventHandler != null)
1235 foreach (bool stop in RunHooks (eventHandler))
1239 StartTimer ("AuthorizeRequest");
1240 eventHandler = Events [AuthorizeRequestEvent];
1241 if (eventHandler != null)
1242 foreach (bool stop in RunHooks (eventHandler))
1246 StartTimer ("PostAuthorizeRequest");
1247 eventHandler = Events [PostAuthorizeRequestEvent];
1248 if (eventHandler != null)
1249 foreach (bool stop in RunHooks (eventHandler))
1253 StartTimer ("ResolveRequestCache");
1254 eventHandler = Events [ResolveRequestCacheEvent];
1255 if (eventHandler != null)
1256 foreach (bool stop in RunHooks (eventHandler))
1260 StartTimer ("PostResolveRequestCache");
1261 eventHandler = Events [PostResolveRequestCacheEvent];
1262 if (eventHandler != null)
1263 foreach (bool stop in RunHooks (eventHandler))
1267 StartTimer ("MapRequestHandler");
1268 // As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
1269 eventHandler = Events [MapRequestHandlerEvent];
1270 if (eventHandler != null)
1271 foreach (bool stop in RunHooks (eventHandler))
1274 context.MapRequestHandlerDone = true;
1276 StartTimer ("GetHandler");
1277 // Obtain the handler for the request.
1278 IHttpHandler handler = null;
1280 handler = GetHandler (context, context.Request.CurrentExecutionFilePath);
1281 context.Handler = handler;
1282 context.PushHandler (handler);
1283 } catch (FileNotFoundException fnf){
1284 if (context.Request.IsLocal)
1285 ProcessError (HttpException.NewWithCode (404,
1286 String.Format ("File not found {0}", fnf.FileName),
1288 context.Request.FilePath,
1289 WebEventCodes.RuntimeErrorRequestAbort));
1291 ProcessError (HttpException.NewWithCode (404,
1292 "File not found: " + Path.GetFileName (fnf.FileName),
1293 context.Request.FilePath,
1294 WebEventCodes.RuntimeErrorRequestAbort));
1295 } catch (DirectoryNotFoundException dnf){
1296 if (!context.Request.IsLocal)
1297 dnf = null; // Do not "leak" real path information
1298 ProcessError (HttpException.NewWithCode (404, "Directory not found", dnf, WebEventCodes.RuntimeErrorRequestAbort));
1299 } catch (Exception e) {
1304 if (stop_processing)
1307 StartTimer ("PostMapRequestHandler");
1308 eventHandler = Events [PostMapRequestHandlerEvent];
1309 if (eventHandler != null)
1310 foreach (bool stop in RunHooks (eventHandler))
1314 StartTimer ("AcquireRequestState");
1315 eventHandler = Events [AcquireRequestStateEvent];
1316 if (eventHandler != null){
1317 foreach (bool stop in RunHooks (eventHandler))
1322 StartTimer ("PostAcquireRequestState");
1323 eventHandler = Events [PostAcquireRequestStateEvent];
1324 if (eventHandler != null){
1325 foreach (bool stop in RunHooks (eventHandler))
1331 // From this point on, we need to ensure that we call
1332 // ReleaseRequestState, so the code below jumps to
1333 // `release:' to guarantee it rather than yielding.
1335 StartTimer ("PreRequestHandlerExecute");
1336 eventHandler = Events [PreRequestHandlerExecuteEvent];
1337 if (eventHandler != null)
1338 foreach (bool stop in RunHooks (eventHandler))
1346 bool doProcessHandler = false;
1349 IHttpHandler ctxHandler = context.Handler;
1350 if (ctxHandler != null && handler != ctxHandler) {
1351 context.PopHandler ();
1352 handler = ctxHandler;
1353 context.PushHandler (handler);
1356 StartTimer ("ProcessRequest");
1358 context.BeginTimeoutPossible ();
1359 if (handler != null){
1360 IHttpAsyncHandler async_handler = handler as IHttpAsyncHandler;
1362 if (async_handler != null){
1365 async_handler.BeginProcessRequest (context, async_handler_complete_cb, handler);
1368 handler.ProcessRequest (context);
1370 IHttpExtendedHandler extHandler=handler as IHttpExtendedHandler;
1371 doProcessHandler = extHandler != null && !extHandler.IsCompleted;
1375 throw new InvalidOperationException ("No handler for the current request.");
1376 if (context.Error != null)
1377 throw new TargetInvocationException(context.Error);
1380 context.EndTimeoutPossible ();
1384 if (doProcessHandler) {
1386 goto processHandler;
1390 yield return stop_processing;
1391 else if (stop_processing)
1394 // These are executed after the application has returned
1396 StartTimer ("PostRequestHandlerExecute");
1397 eventHandler = Events [PostRequestHandlerExecuteEvent];
1398 if (eventHandler != null)
1399 foreach (bool stop in RunHooks (eventHandler))
1405 StartTimer ("ReleaseRequestState");
1406 eventHandler = Events [ReleaseRequestStateEvent];
1407 if (eventHandler != null){
1408 #pragma warning disable 219
1409 foreach (bool stop in RunHooks (eventHandler)) {
1411 // Ignore the stop signal while release the state
1415 #pragma warning restore 219
1419 if (stop_processing)
1422 StartTimer ("PostReleaseRequestState");
1423 eventHandler = Events [PostReleaseRequestStateEvent];
1424 if (eventHandler != null)
1425 foreach (bool stop in RunHooks (eventHandler))
1429 StartTimer ("Filter");
1430 if (context.Error == null)
1431 context.Response.DoFilter (true);
1434 StartTimer ("UpdateRequestCache");
1435 eventHandler = Events [UpdateRequestCacheEvent];
1436 if (eventHandler != null)
1437 foreach (bool stop in RunHooks (eventHandler))
1441 StartTimer ("PostUpdateRequestCache");
1442 eventHandler = Events [PostUpdateRequestCacheEvent];
1443 if (eventHandler != null)
1444 foreach (bool stop in RunHooks (eventHandler))
1448 StartTimer ("LogRequest");
1449 eventHandler = Events [LogRequestEvent];
1450 if (eventHandler != null)
1451 foreach (bool stop in RunHooks (eventHandler))
1455 StartTimer ("PostLogRequest");
1456 eventHandler = Events [PostLogRequestEvent];
1457 if (eventHandler != null)
1458 foreach (bool stop in RunHooks (eventHandler))
1462 StartTimer ("PipelineDone");
1468 internal CultureInfo GetThreadCulture (HttpRequest request, CultureInfo culture, bool isAuto)
1472 CultureInfo ret = null;
1473 string[] languages = request.UserLanguages;
1475 if (languages != null && languages.Length > 0)
1476 ret = CultureInfo.CreateSpecificCulture (languages[0]);
1489 GlobalizationSection cfg;
1490 cfg = (GlobalizationSection) WebConfigurationManager.GetSection ("system.web/globalization");
1491 app_culture = cfg.GetCulture ();
1492 autoCulture = cfg.IsAutoCulture;
1493 appui_culture = cfg.GetUICulture ();
1494 autoUICulture = cfg.IsAutoUICulture;
1496 context.StartTimeoutTimer ();
1498 Thread th = Thread.CurrentThread;
1499 if (app_culture != null) {
1500 prev_app_culture = th.CurrentCulture;
1501 CultureInfo new_app_culture = GetThreadCulture (Request, app_culture, autoCulture);
1502 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1503 th.CurrentCulture = new_app_culture;
1506 if (appui_culture != null) {
1507 prev_appui_culture = th.CurrentUICulture;
1508 CultureInfo new_app_culture = GetThreadCulture (Request, appui_culture, autoUICulture);
1509 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1510 th.CurrentUICulture = new_app_culture;
1513 prev_user = Thread.CurrentPrincipal;
1518 if (removeConfigurationFromCache) {
1519 WebConfigurationManager.RemoveConfigurationFromCache (context);
1520 removeConfigurationFromCache = false;
1523 Thread th = Thread.CurrentThread;
1524 if (Thread.CurrentPrincipal != prev_user)
1525 Thread.CurrentPrincipal = prev_user;
1526 if (prev_appui_culture != null && prev_appui_culture != th.CurrentUICulture)
1527 th.CurrentUICulture = prev_appui_culture;
1528 if (prev_app_culture != null && prev_app_culture != th.CurrentCulture)
1529 th.CurrentCulture = prev_app_culture;
1532 if (context == null)
1533 context = HttpContext.Current;
1534 context.StopTimeoutTimer ();
1536 context.Request.ReleaseResources ();
1537 context.Response.ReleaseResources ();
1540 HttpContext.Current = null;
1543 void Start (object x)
1545 var cultures = x as CultureInfo [];
1546 if (cultures != null && cultures.Length == 2) {
1547 Thread ct = Thread.CurrentThread;
1548 ct.CurrentCulture = cultures [0];
1549 ct.CurrentUICulture = cultures [1];
1553 if (initialization_exception != null) {
1554 Exception e = initialization_exception;
1555 HttpException exc = HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort);
1556 context.Response.StatusCode = 500;
1557 FinalErrorWrite (context.Response, exc.GetHtmlErrorMessage ());
1562 HttpContext.Current = Context;
1564 pipeline = Pipeline ();
1568 const string HANDLER_CACHE = "@@HttpHandlerCache@@";
1570 internal static Hashtable GetHandlerCache ()
1572 Cache cache = HttpRuntime.InternalCache;
1573 Hashtable ret = cache [HANDLER_CACHE] as Hashtable;
1576 ret = new Hashtable ();
1577 cache.Insert (HANDLER_CACHE, ret);
1583 internal static void ClearHandlerCache ()
1585 Hashtable cache = GetHandlerCache ();
1589 object LocateHandler (HttpRequest req, string verb, string url)
1591 Hashtable cache = GetHandlerCache ();
1592 string id = String.Concat (verb, url);
1593 object ret = cache [id];
1599 HttpHandlersSection httpHandlersSection = WebConfigurationManager.GetSection ("system.web/httpHandlers", req.Path, req.Context) as HttpHandlersSection;
1600 ret = httpHandlersSection.LocateHandler (verb, url, out allowCache);
1602 IHttpHandler handler = ret as IHttpHandler;
1603 if (allowCache && handler != null && handler.IsReusable)
1609 internal IHttpHandler GetHandler (HttpContext context, string url)
1611 return GetHandler (context, url, false);
1614 // Used by HttpServerUtility.Execute
1615 internal IHttpHandler GetHandler (HttpContext context, string url, bool ignoreContextHandler)
1617 if (!ignoreContextHandler && context.Handler != null)
1618 return context.Handler;
1620 HttpRequest request = context.Request;
1621 string verb = request.RequestType;
1623 IHttpHandler handler = null;
1624 object o = LocateHandler (request, verb, url);
1626 factory = o as IHttpHandlerFactory;
1627 if (factory == null) {
1628 handler = (IHttpHandler) o;
1630 handler = factory.GetHandler (context, verb, url, request.MapPath (url));
1636 void IHttpHandler.ProcessRequest (HttpContext context)
1639 this.context = context;
1647 // This is used by FireOnAppStart, when we init the application
1648 // as the context is required to be set at that point (the user
1649 // might call methods that require it on that hook).
1651 internal void SetContext (HttpContext context)
1653 this.context = context;
1656 internal void SetSession (HttpSessionState session)
1658 this.session = session;
1661 IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
1663 this.context = context;
1666 begin_iar = new AsyncRequestState (done, cb, extraData);
1668 CultureInfo[] cultures = new CultureInfo [2];
1669 cultures [0] = Thread.CurrentThread.CurrentCulture;
1670 cultures [1] = Thread.CurrentThread.CurrentUICulture;
1672 if (Thread.CurrentThread.IsThreadPoolThread)
1675 ThreadPool.QueueUserWorkItem (x => {
1678 } catch (Exception e) {
1679 Console.Error.WriteLine (e);
1686 void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
1692 if (!result.IsCompleted)
1693 result.AsyncWaitHandle.WaitOne ();
1697 public virtual void Init ()
1701 bool IHttpHandler.IsReusable {
1708 internal void ClearError ()
1710 context.ClearError ();
1713 bool RedirectErrorPage (string error_page)
1715 if (context.Request.QueryString ["aspxerrorpath"] != null)
1718 Response.Redirect (error_page + "?aspxerrorpath=" + Request.Path, false);
1722 bool RedirectCustomError (ref HttpException httpEx)
1725 if (!context.IsCustomErrorEnabledUnsafe)
1728 CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");
1729 if (config == null) {
1730 if (context.ErrorPage != null)
1731 return RedirectErrorPage (context.ErrorPage);
1736 CustomError err = config.Errors [context.Response.StatusCode.ToString()];
1737 string redirect = err == null ? null : err.Redirect;
1738 if (redirect == null) {
1739 redirect = context.ErrorPage;
1740 if (redirect == null)
1741 redirect = config.DefaultRedirect;
1744 if (redirect == null)
1747 if (config.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite) {
1748 context.Server.Execute (redirect);
1752 return RedirectErrorPage (redirect);
1754 catch (Exception ex) {
1755 httpEx = HttpException.NewWithCode (500, String.Empty, ex, WebEventCodes.WebErrorOtherError);
1760 internal static string BinDirectory
1763 if (binDirectory == null) {
1764 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
1765 string baseDir = setup.ApplicationBase;
1768 foreach (string dir in BinDirs) {
1769 bindir = Path.Combine (baseDir, dir);
1770 if (!Directory.Exists (bindir))
1772 binDirectory = bindir;
1777 return binDirectory;
1781 internal static string[] BinDirectoryAssemblies
1784 ArrayList binDlls = null;
1787 string bindir = BinDirectory;
1788 if (bindir != null) {
1789 binDlls = new ArrayList ();
1790 dlls = Directory.GetFiles (bindir, "*.dll");
1791 binDlls.AddRange (dlls);
1794 if (binDlls == null)
1795 return new string[] {};
1797 return (string[]) binDlls.ToArray (typeof (string));
1801 internal static Type LoadType (string typeName)
1803 return LoadType (typeName, false);
1806 internal static Type LoadType (string typeName, bool throwOnMissing)
1808 Type type = Type.GetType (typeName);
1812 Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
1813 foreach (Assembly ass in assemblies) {
1814 type = ass.GetType (typeName, false);
1819 IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
1820 if (tla != null && tla.Count > 0) {
1821 foreach (Assembly asm in tla) {
1824 type = asm.GetType (typeName, false);
1830 Exception loadException = null;
1833 type = LoadTypeFromBin (typeName);
1834 } catch (Exception ex) {
1841 throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName), loadException);
1846 internal static Type LoadType <TBaseType> (string typeName, bool throwOnMissing)
1848 Type ret = LoadType (typeName, throwOnMissing);
1850 if (typeof (TBaseType).IsAssignableFrom (ret))
1854 throw new TypeLoadException (String.Format ("Type '{0}' found but it doesn't derive from base type '{1}'.", typeName, typeof (TBaseType)));
1859 internal static Type LoadTypeFromBin (string typeName)
1863 foreach (string s in BinDirectoryAssemblies) {
1864 Assembly binA = null;
1867 binA = Assembly.LoadFrom (s);
1868 } catch (FileLoadException) {
1871 } catch (BadImageFormatException) {
1876 type = binA.GetType (typeName, false);
1888 // Based on Fritz' Onion's AsyncRequestState class for asynchronous IHttpAsyncHandlers
1890 class AsyncRequestState : IAsyncResult {
1894 ManualResetEvent complete_event = null;
1896 internal AsyncRequestState (ManualResetEvent complete_event, AsyncCallback cb, object cb_data)
1899 this.cb_data = cb_data;
1900 this.complete_event = complete_event;
1903 internal void Complete ()
1908 // TODO: if this throws an error, we have no way of reporting it
1909 // Not really too bad, since the only failure might be
1910 // `HttpRuntime.request_processed'.
1917 complete_event.Set ();
1920 public object AsyncState {
1926 public bool CompletedSynchronously {
1932 public bool IsCompleted {
1938 public WaitHandle AsyncWaitHandle {
1940 return complete_event;
1945 #region Helper classes
1948 // A wrapper to keep track of begin/end pairs
1950 class AsyncInvoker {
1951 public BeginEventHandler begin;
1952 public EndEventHandler end;
1955 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, object d)
1962 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh)
1968 public void Invoke (object sender, EventArgs e)
1970 throw new Exception ("This is just a dummy");