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;
87 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
88 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
91 public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
93 static readonly object disposedEvent = new object ();
94 static readonly object errorEvent = new object ();
96 // we do this static rather than per HttpApplication because
97 // mono's perfcounters use the counter instance parameter for
98 // the process to access shared memory.
99 internal static PerformanceCounter requests_total_counter = new PerformanceCounter ("ASP.NET", "Requests Total");
101 internal static readonly string [] BinDirs = {"Bin", "bin"};
102 object this_lock = new object();
105 HttpSessionState session;
108 // The source, and the exposed API (cache).
109 volatile HttpModuleCollection modcoll;
111 string assemblyLocation;
114 // The factory for the handler currently running.
116 IHttpHandlerFactory factory;
119 // Whether the thread culture is to be auto-set.
120 // Used only in the 2.0 profile, always false for 1.x
126 // Whether the pipeline should be stopped
128 bool stop_processing;
131 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
133 bool in_application_start;
138 IEnumerator pipeline;
140 // To flag when we are done processing a request from BeginProcessRequest.
141 ManualResetEvent done;
143 // The current IAsyncResult for the running async request handler in the pipeline
144 AsyncRequestState begin_iar;
146 // Tracks the current AsyncInvocation being dispatched
147 AsyncInvoker current_ai;
149 EventHandlerList events;
150 EventHandlerList nonApplicationEvents = new EventHandlerList ();
152 // Culture and IPrincipal
153 CultureInfo app_culture;
154 CultureInfo appui_culture;
155 CultureInfo prev_app_culture;
156 CultureInfo prev_appui_culture;
157 IPrincipal prev_user;
159 static string binDirectory;
161 static volatile Exception initialization_exception;
162 bool removeConfigurationFromCache;
163 bool fullInitComplete = false;
166 // These are used to detect the case where the EndXXX method is invoked
167 // from within the BeginXXXX delegate, so we detect whether we kick the
168 // pipeline from here, or from the the RunHook routine
173 public virtual event EventHandler Disposed {
174 add { nonApplicationEvents.AddHandler (disposedEvent, value); }
175 remove { nonApplicationEvents.RemoveHandler (disposedEvent, value); }
178 public virtual event EventHandler Error {
179 add { nonApplicationEvents.AddHandler (errorEvent, value); }
180 remove { nonApplicationEvents.RemoveHandler (errorEvent, value); }
183 public HttpApplication ()
185 done = new ManualResetEvent (false);
188 internal void InitOnce (bool full_init)
190 if (initialization_exception != null)
197 if (initialization_exception != null)
203 bool mustNullContext = context == null;
205 HttpModulesSection modules;
206 modules = (HttpModulesSection) WebConfigurationManager.GetWebApplicationSection ("system.web/httpModules");
207 HttpContext saved = HttpContext.Current;
208 HttpContext.Current = new HttpContext (new System.Web.Hosting.SimpleWorkerRequest (String.Empty, String.Empty, new StringWriter()));
210 context = HttpContext.Current;
211 HttpModuleCollection coll = modules.LoadModules (this);
212 Interlocked.CompareExchange (ref modcoll, coll, null);
213 HttpContext.Current = saved;
216 HttpApplicationFactory.AttachEvents (this);
218 fullInitComplete = true;
220 } catch (Exception e) {
221 initialization_exception = e;
222 Console.Error.WriteLine("Exception while initOnce: "+e.ToString());
223 // Once initialization_exception != null, we always respond with this exception
224 // You have to restart the HttpApplication to "unlock" it
225 Console.Error.WriteLine("Please restart your app to unlock it");
233 internal bool InApplicationStart {
234 get { return in_application_start; }
235 set { in_application_start = value; }
238 internal string AssemblyLocation {
240 if (assemblyLocation == null)
241 assemblyLocation = GetType ().Assembly.Location;
242 return assemblyLocation;
246 internal static Exception InitializationException {
247 get { return initialization_exception; }
251 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
252 public HttpApplicationState Application {
254 return HttpApplicationFactory.ApplicationState;
259 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
260 public HttpContext Context {
266 protected EventHandlerList Events {
269 events = new EventHandlerList ();
276 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
277 public HttpModuleCollection Modules {
278 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
281 modcoll = new HttpModuleCollection ();
288 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
289 public HttpRequest Request {
292 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
294 if (false == HttpApplicationFactory.ContextAvailable)
295 throw HttpException.NewWithCode (Locale.GetText ("Request is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
297 return context.Request;
302 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
303 public HttpResponse Response {
306 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
308 if (false == HttpApplicationFactory.ContextAvailable)
309 throw HttpException.NewWithCode (Locale.GetText ("Response is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
311 return context.Response;
316 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
317 public HttpServerUtility Server {
320 return context.Server;
323 // This is so we can get the Server and call a few methods
324 // which are not context sensitive, see HttpServerUtilityTest
326 return new HttpServerUtility ((HttpContext) null);
331 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
332 public HttpSessionState Session {
334 // Only used for Session_End
339 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
341 HttpSessionState ret = context.Session;
343 throw HttpException.NewWithCode (Locale.GetText ("Session state is not available in the context."), WebEventCodes.RuntimeErrorRequestAbort);
350 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
352 get { return isite; }
354 set { isite = value; }
358 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
359 public IPrincipal User {
362 throw new HttpException (Locale.GetText ("No context is available."));
363 if (context.User == null)
364 throw new HttpException (Locale.GetText ("No currently authenticated user."));
370 static object PreSendRequestHeadersEvent = new object ();
371 public event EventHandler PreSendRequestHeaders
373 add { AddEventHandler (PreSendRequestHeadersEvent, value); }
374 remove { RemoveEventHandler (PreSendRequestHeadersEvent, value); }
377 internal void TriggerPreSendRequestHeaders ()
379 EventHandler handler = Events [PreSendRequestHeadersEvent] as EventHandler;
381 handler (this, EventArgs.Empty);
384 static object PreSendRequestContentEvent = new object ();
385 public event EventHandler PreSendRequestContent
387 add { AddEventHandler (PreSendRequestContentEvent, value); }
388 remove { RemoveEventHandler (PreSendRequestContentEvent, value); }
391 internal void TriggerPreSendRequestContent ()
393 EventHandler handler = Events [PreSendRequestContentEvent] as EventHandler;
395 handler (this, EventArgs.Empty);
398 static object AcquireRequestStateEvent = new object ();
399 public event EventHandler AcquireRequestState
401 add { AddEventHandler (AcquireRequestStateEvent, value); }
402 remove { RemoveEventHandler (AcquireRequestStateEvent, value); }
405 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
407 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
408 AcquireRequestState += new EventHandler (invoker.Invoke);
411 static object AuthenticateRequestEvent = new object ();
412 public event EventHandler AuthenticateRequest
414 add { AddEventHandler (AuthenticateRequestEvent, value); }
415 remove { RemoveEventHandler (AuthenticateRequestEvent, value); }
418 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
420 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
421 AuthenticateRequest += new EventHandler (invoker.Invoke);
424 static object AuthorizeRequestEvent = new object ();
425 public event EventHandler AuthorizeRequest
427 add { AddEventHandler (AuthorizeRequestEvent, value); }
428 remove { RemoveEventHandler (AuthorizeRequestEvent, value); }
431 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
433 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
434 AuthorizeRequest += new EventHandler (invoker.Invoke);
437 static object BeginRequestEvent = new object ();
438 public event EventHandler BeginRequest
441 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
442 if (InApplicationStart)
444 AddEventHandler (BeginRequestEvent, value);
447 if (InApplicationStart)
449 RemoveEventHandler (BeginRequestEvent, value);
453 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
455 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
456 BeginRequest += new EventHandler (invoker.Invoke);
459 static object EndRequestEvent = new object ();
460 public event EventHandler EndRequest
463 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
464 if (InApplicationStart)
466 AddEventHandler (EndRequestEvent, value);
469 if (InApplicationStart)
471 RemoveEventHandler (EndRequestEvent, value);
475 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
477 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
478 EndRequest += new EventHandler (invoker.Invoke);
481 static object PostRequestHandlerExecuteEvent = new object ();
482 public event EventHandler PostRequestHandlerExecute
484 add { AddEventHandler (PostRequestHandlerExecuteEvent, value); }
485 remove { RemoveEventHandler (PostRequestHandlerExecuteEvent, value); }
488 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
490 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
491 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
494 static object PreRequestHandlerExecuteEvent = new object ();
495 public event EventHandler PreRequestHandlerExecute
497 add { AddEventHandler (PreRequestHandlerExecuteEvent, value); }
498 remove { RemoveEventHandler (PreRequestHandlerExecuteEvent, value); }
501 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
503 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
504 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
507 static object ReleaseRequestStateEvent = new object ();
508 public event EventHandler ReleaseRequestState
510 add { AddEventHandler (ReleaseRequestStateEvent, value); }
511 remove { RemoveEventHandler (ReleaseRequestStateEvent, value); }
514 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
516 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
517 ReleaseRequestState += new EventHandler (invoker.Invoke);
520 static object ResolveRequestCacheEvent = new object ();
521 public event EventHandler ResolveRequestCache
523 add { AddEventHandler (ResolveRequestCacheEvent, value); }
524 remove { RemoveEventHandler (ResolveRequestCacheEvent, value); }
527 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
529 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
530 ResolveRequestCache += new EventHandler (invoker.Invoke);
533 static object UpdateRequestCacheEvent = new object ();
534 public event EventHandler UpdateRequestCache
536 add { AddEventHandler (UpdateRequestCacheEvent, value); }
537 remove { RemoveEventHandler (UpdateRequestCacheEvent, value); }
540 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
542 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
543 UpdateRequestCache += new EventHandler (invoker.Invoke);
546 static object PostAuthenticateRequestEvent = new object ();
547 public event EventHandler PostAuthenticateRequest
549 add { AddEventHandler (PostAuthenticateRequestEvent, value); }
550 remove { RemoveEventHandler (PostAuthenticateRequestEvent, value); }
553 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
555 AddOnPostAuthenticateRequestAsync (bh, eh, null);
558 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
560 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
561 PostAuthenticateRequest += new EventHandler (invoker.Invoke);
564 static object PostAuthorizeRequestEvent = new object ();
565 public event EventHandler PostAuthorizeRequest
567 add { AddEventHandler (PostAuthorizeRequestEvent, value); }
568 remove { RemoveEventHandler (PostAuthorizeRequestEvent, value); }
571 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
573 AddOnPostAuthorizeRequestAsync (bh, eh, null);
576 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
578 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
579 PostAuthorizeRequest += new EventHandler (invoker.Invoke);
582 static object PostResolveRequestCacheEvent = new object ();
583 public event EventHandler PostResolveRequestCache
585 add { AddEventHandler (PostResolveRequestCacheEvent, value); }
586 remove { RemoveEventHandler (PostResolveRequestCacheEvent, value); }
589 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
591 AddOnPostResolveRequestCacheAsync (bh, eh, null);
594 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
596 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
597 PostResolveRequestCache += new EventHandler (invoker.Invoke);
600 static object PostMapRequestHandlerEvent = new object ();
601 public event EventHandler PostMapRequestHandler
603 add { AddEventHandler (PostMapRequestHandlerEvent, value); }
604 remove { RemoveEventHandler (PostMapRequestHandlerEvent, value); }
607 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
609 AddOnPostMapRequestHandlerAsync (bh, eh, null);
612 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh, object data)
614 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
615 PostMapRequestHandler += new EventHandler (invoker.Invoke);
618 static object PostAcquireRequestStateEvent = new object ();
619 public event EventHandler PostAcquireRequestState
621 add { AddEventHandler (PostAcquireRequestStateEvent, value); }
622 remove { RemoveEventHandler (PostAcquireRequestStateEvent, value); }
625 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
627 AddOnPostAcquireRequestStateAsync (bh, eh, null);
630 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
632 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
633 PostAcquireRequestState += new EventHandler (invoker.Invoke);
636 static object PostReleaseRequestStateEvent = new object ();
637 public event EventHandler PostReleaseRequestState
639 add { AddEventHandler (PostReleaseRequestStateEvent, value); }
640 remove { RemoveEventHandler (PostReleaseRequestStateEvent, value); }
643 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
645 AddOnPostReleaseRequestStateAsync (bh, eh, null);
648 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
650 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
651 PostReleaseRequestState += new EventHandler (invoker.Invoke);
654 static object PostUpdateRequestCacheEvent = new object ();
655 public event EventHandler PostUpdateRequestCache
657 add { AddEventHandler (PostUpdateRequestCacheEvent, value); }
658 remove { RemoveEventHandler (PostUpdateRequestCacheEvent, value); }
661 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
663 AddOnPostUpdateRequestCacheAsync (bh, eh, null);
666 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
668 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
669 PostUpdateRequestCache += new EventHandler (invoker.Invoke);
673 // The new overloads that take a data parameter
675 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
677 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
678 AcquireRequestState += new EventHandler (invoker.Invoke);
681 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
683 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
684 AuthenticateRequest += new EventHandler (invoker.Invoke);
687 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
689 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
690 AuthorizeRequest += new EventHandler (invoker.Invoke);
693 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
695 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
696 BeginRequest += new EventHandler (invoker.Invoke);
699 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
701 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
702 EndRequest += new EventHandler (invoker.Invoke);
705 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
707 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
708 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
711 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
713 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
714 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
717 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
719 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
720 ReleaseRequestState += new EventHandler (invoker.Invoke);
723 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
725 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
726 ResolveRequestCache += new EventHandler (invoker.Invoke);
729 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
731 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
732 UpdateRequestCache += new EventHandler (invoker.Invoke);
736 // They are for use with the IIS7 integrated mode, but have been added for
738 static object LogRequestEvent = new object ();
739 public event EventHandler LogRequest
741 add { AddEventHandler (LogRequestEvent, value); }
742 remove { RemoveEventHandler (LogRequestEvent, value); }
745 public void AddOnLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
747 AddOnLogRequestAsync (bh, eh, null);
750 public void AddOnLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
752 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
753 LogRequest += new EventHandler (invoker.Invoke);
756 static object MapRequestHandlerEvent = new object ();
757 public event EventHandler MapRequestHandler
759 add { AddEventHandler (MapRequestHandlerEvent, value); }
760 remove { RemoveEventHandler (MapRequestHandlerEvent, value); }
763 public void AddOnMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
765 AddOnMapRequestHandlerAsync (bh, eh, null);
768 public void AddOnMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
770 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
771 MapRequestHandler += new EventHandler (invoker.Invoke);
774 static object PostLogRequestEvent = new object ();
775 public event EventHandler PostLogRequest
777 add { AddEventHandler (PostLogRequestEvent, value); }
778 remove { RemoveEventHandler (PostLogRequestEvent, value); }
781 public void AddOnPostLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
783 AddOnPostLogRequestAsync (bh, eh, null);
786 public void AddOnPostLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
788 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
789 PostLogRequest += new EventHandler (invoker.Invoke);
792 internal event EventHandler DefaultAuthentication;
794 void AddEventHandler (object key, EventHandler handler)
796 if (fullInitComplete)
799 Events.AddHandler (key, handler);
802 void RemoveEventHandler (object key, EventHandler handler)
804 if (fullInitComplete)
807 Events.RemoveHandler (key, handler);
811 // Bypass all the event on the Http pipeline and go directly to EndRequest
813 public void CompleteRequest ()
815 stop_processing = true;
818 internal bool RequestCompleted {
819 set { stop_processing = value; }
822 internal void DisposeInternal ()
825 HttpModuleCollection coll = new HttpModuleCollection ();
826 Interlocked.Exchange (ref modcoll, coll);
828 for (int i = coll.Count - 1; i >= 0; i--) {
829 coll.Get (i).Dispose ();
834 EventHandler eh = nonApplicationEvents [disposedEvent] as EventHandler;
836 eh (this, EventArgs.Empty);
842 public virtual void Dispose ()
847 public virtual string GetOutputCacheProviderName (HttpContext context)
849 // LAMESPEC: doesn't throw ProviderException if context is null
850 return OutputCache.DefaultProviderName;
854 public virtual string GetVaryByCustomString (HttpContext context, string custom)
856 if (custom == null) // Sigh
857 throw new NullReferenceException ();
859 if (0 == String.Compare (custom, "browser", true, Helpers.InvariantCulture))
860 return context.Request.Browser.Type;
865 bool ShouldHandleException (Exception e)
867 if (e is ParseException)
874 // If we catch an error, queue this error
876 void ProcessError (Exception e)
878 bool first = context.Error == null;
879 context.AddError (e);
880 if (first && ShouldHandleException (e)) {
881 EventHandler eh = nonApplicationEvents [errorEvent] as EventHandler;
884 eh (this, EventArgs.Empty);
886 context.ClearError ();
887 } catch (ThreadAbortException taex){
888 context.ClearError ();
889 if (FlagEnd.Value == taex.ExceptionState || HttpRuntime.DomainUnloading)
890 // This happens on Redirect(), End() and
891 // when unloading the AppDomain
892 Thread.ResetAbort ();
894 // This happens on Thread.Abort()
895 context.AddError (taex);
896 } catch (Exception ee){
897 context.AddError (ee);
901 stop_processing = true;
903 // we want to remove configuration from the cache in case of
904 // invalid resource not exists to prevent DOS attack.
905 HttpException httpEx = e as HttpException;
906 if (httpEx != null && httpEx.GetHttpCode () == 404) {
907 removeConfigurationFromCache = true;
912 // Ticks the clock: next step on the pipeline.
914 internal void Tick ()
917 if (pipeline.MoveNext ()){
918 if ((bool)pipeline.Current)
921 } catch (ThreadAbortException taex) {
922 object obj = taex.ExceptionState;
923 Thread.ResetAbort ();
924 if (obj is StepTimeout)
925 ProcessError (HttpException.NewWithCode ("The request timed out.", WebEventCodes.RequestTransactionAbort));
927 context.ClearError ();
928 if (FlagEnd.Value != obj && !HttpRuntime.DomainUnloading)
929 context.AddError (taex);
932 stop_processing = true;
934 } catch (Exception e) {
935 ThreadAbortException inner = e.InnerException as ThreadAbortException;
936 if (inner != null && FlagEnd.Value == inner.ExceptionState && !HttpRuntime.DomainUnloading) {
937 context.ClearError ();
938 Thread.ResetAbort ();
942 stop_processing = true;
956 // Invoked when our async callback called from RunHooks completes,
957 // we restart the pipeline here.
959 void async_callback_completed_cb (IAsyncResult ar)
961 if (current_ai.end != null){
964 } catch (Exception e) {
972 void async_handler_complete_cb (IAsyncResult ar)
974 IHttpAsyncHandler async_handler = ar != null ? ar.AsyncState as IHttpAsyncHandler : null;
977 if (async_handler != null)
978 async_handler.EndProcessRequest (ar);
979 } catch (Exception e){
987 // This enumerator yields whether processing must be stopped:
988 // true: processing of the pipeline must be stopped
989 // false: processing of the pipeline must not be stopped
991 IEnumerable RunHooks (Delegate list)
993 Delegate [] delegates = list.GetInvocationList ();
995 foreach (EventHandler d in delegates){
996 if (d.Target != null && (d.Target is AsyncInvoker)){
997 current_ai = (AsyncInvoker) d.Target;
1002 context.BeginTimeoutPossible ();
1003 current_ai.begin (this, EventArgs.Empty, async_callback_completed_cb, current_ai.data);
1006 context.EndTimeoutPossible ();
1010 // If things are still moving forward, yield this
1014 yield return stop_processing;
1015 else if (stop_processing)
1019 context.BeginTimeoutPossible ();
1020 d (this, EventArgs.Empty);
1022 context.EndTimeoutPossible ();
1024 if (stop_processing)
1030 static void FinalErrorWrite (HttpResponse response, string error)
1033 response.Write (error);
1034 response.Flush (true);
1042 if (context.Error == null){
1044 context.Response.Flush (true);
1045 } catch (Exception e){
1046 context.AddError (e);
1050 Exception error = context.Error;
1052 HttpResponse response = context.Response;
1054 if (!response.HeadersSent){
1055 response.ClearHeaders ();
1056 response.ClearContent ();
1058 if (error is HttpException){
1059 response.StatusCode = ((HttpException)error).GetHttpCode ();
1061 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1062 response.StatusCode = 500;
1064 HttpException httpEx = (HttpException) error;
1065 if (!RedirectCustomError (ref httpEx))
1066 FinalErrorWrite (response, httpEx.GetHtmlErrorMessage ());
1068 response.Flush (true);
1070 if (!(error is HttpException))
1071 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1072 FinalErrorWrite (response, ((HttpException) error).GetHtmlErrorMessage ());
1079 // Invoked at the end of the pipeline execution
1081 void PipelineDone ()
1084 EventHandler handler = Events [EndRequestEvent] as EventHandler;
1085 if (handler != null)
1086 handler (this, EventArgs.Empty);
1087 } catch (Exception e){
1093 } catch (ThreadAbortException taex) {
1094 ProcessError (taex);
1095 Thread.ResetAbort ();
1096 } catch (Exception e) {
1097 Console.WriteLine ("Internal error: OutputPage threw an exception " + e);
1099 context.WorkerRequest.EndOfRequest();
1100 if (factory != null && context.Handler != null){
1101 factory.ReleaseHandler (context.Handler);
1102 context.Handler = null;
1105 context.PopHandler ();
1107 // context = null; -> moved to PostDone
1113 if (begin_iar != null)
1114 begin_iar.Complete ();
1118 requests_total_counter.Increment ();
1128 public Tim (string name) {
1132 public string Name {
1133 get { return name; }
1134 set { name = value; }
1137 public void Start () {
1138 start = DateTime.UtcNow;
1141 public void Stop () {
1142 Console.WriteLine ("{0}: {1}ms", name, (DateTime.UtcNow - start).TotalMilliseconds);
1147 [Conditional ("PIPELINE_TIMER")]
1148 void StartTimer (string name)
1156 [Conditional ("PIPELINE_TIMER")]
1163 // Events fired as described in `Http Runtime Support, HttpModules,
1164 // Handling Public Events'
1166 IEnumerator Pipeline ()
1168 Delegate eventHandler;
1169 if (stop_processing)
1172 HttpRequest req = context.Request;
1176 context.MapRequestHandlerDone = false;
1177 StartTimer ("BeginRequest");
1178 eventHandler = Events [BeginRequestEvent];
1179 if (eventHandler != null) {
1180 foreach (bool stop in RunHooks (eventHandler))
1185 StartTimer ("AuthenticateRequest");
1186 eventHandler = Events [AuthenticateRequestEvent];
1187 if (eventHandler != null)
1188 foreach (bool stop in RunHooks (eventHandler))
1192 StartTimer ("DefaultAuthentication");
1193 if (DefaultAuthentication != null)
1194 foreach (bool stop in RunHooks (DefaultAuthentication))
1198 StartTimer ("PostAuthenticateRequest");
1199 eventHandler = Events [PostAuthenticateRequestEvent];
1200 if (eventHandler != null)
1201 foreach (bool stop in RunHooks (eventHandler))
1205 StartTimer ("AuthorizeRequest");
1206 eventHandler = Events [AuthorizeRequestEvent];
1207 if (eventHandler != null)
1208 foreach (bool stop in RunHooks (eventHandler))
1212 StartTimer ("PostAuthorizeRequest");
1213 eventHandler = Events [PostAuthorizeRequestEvent];
1214 if (eventHandler != null)
1215 foreach (bool stop in RunHooks (eventHandler))
1219 StartTimer ("ResolveRequestCache");
1220 eventHandler = Events [ResolveRequestCacheEvent];
1221 if (eventHandler != null)
1222 foreach (bool stop in RunHooks (eventHandler))
1226 StartTimer ("PostResolveRequestCache");
1227 eventHandler = Events [PostResolveRequestCacheEvent];
1228 if (eventHandler != null)
1229 foreach (bool stop in RunHooks (eventHandler))
1233 StartTimer ("MapRequestHandler");
1234 // As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
1235 eventHandler = Events [MapRequestHandlerEvent];
1236 if (eventHandler != null)
1237 foreach (bool stop in RunHooks (eventHandler))
1240 context.MapRequestHandlerDone = true;
1242 StartTimer ("GetHandler");
1243 // Obtain the handler for the request.
1244 IHttpHandler handler = null;
1246 handler = GetHandler (context, context.Request.CurrentExecutionFilePath);
1247 context.Handler = handler;
1248 context.PushHandler (handler);
1249 } catch (FileNotFoundException fnf){
1250 if (context.Request.IsLocal)
1251 ProcessError (HttpException.NewWithCode (404,
1252 String.Format ("File not found {0}", fnf.FileName),
1254 context.Request.FilePath,
1255 WebEventCodes.RuntimeErrorRequestAbort));
1257 ProcessError (HttpException.NewWithCode (404,
1258 "File not found: " + Path.GetFileName (fnf.FileName),
1259 context.Request.FilePath,
1260 WebEventCodes.RuntimeErrorRequestAbort));
1261 } catch (DirectoryNotFoundException dnf){
1262 if (!context.Request.IsLocal)
1263 dnf = null; // Do not "leak" real path information
1264 ProcessError (HttpException.NewWithCode (404, "Directory not found", dnf, WebEventCodes.RuntimeErrorRequestAbort));
1265 } catch (Exception e) {
1270 if (stop_processing)
1273 StartTimer ("PostMapRequestHandler");
1274 eventHandler = Events [PostMapRequestHandlerEvent];
1275 if (eventHandler != null)
1276 foreach (bool stop in RunHooks (eventHandler))
1280 StartTimer ("AcquireRequestState");
1281 eventHandler = Events [AcquireRequestStateEvent];
1282 if (eventHandler != null){
1283 foreach (bool stop in RunHooks (eventHandler))
1288 StartTimer ("PostAcquireRequestState");
1289 eventHandler = Events [PostAcquireRequestStateEvent];
1290 if (eventHandler != null){
1291 foreach (bool stop in RunHooks (eventHandler))
1297 // From this point on, we need to ensure that we call
1298 // ReleaseRequestState, so the code below jumps to
1299 // `release:' to guarantee it rather than yielding.
1301 StartTimer ("PreRequestHandlerExecute");
1302 eventHandler = Events [PreRequestHandlerExecuteEvent];
1303 if (eventHandler != null)
1304 foreach (bool stop in RunHooks (eventHandler))
1311 IHttpHandler ctxHandler = context.Handler;
1312 if (ctxHandler != null && handler != ctxHandler) {
1313 context.PopHandler ();
1314 handler = ctxHandler;
1315 context.PushHandler (handler);
1318 StartTimer ("ProcessRequest");
1320 context.BeginTimeoutPossible ();
1321 if (handler != null){
1322 IHttpAsyncHandler async_handler = handler as IHttpAsyncHandler;
1324 if (async_handler != null){
1327 async_handler.BeginProcessRequest (context, async_handler_complete_cb, handler);
1330 handler.ProcessRequest (context);
1333 throw new InvalidOperationException ("No handler for the current request.");
1334 if (context.Error != null)
1335 throw new TargetInvocationException(context.Error);
1338 context.EndTimeoutPossible ();
1342 yield return stop_processing;
1343 else if (stop_processing)
1346 // These are executed after the application has returned
1348 StartTimer ("PostRequestHandlerExecute");
1349 eventHandler = Events [PostRequestHandlerExecuteEvent];
1350 if (eventHandler != null)
1351 foreach (bool stop in RunHooks (eventHandler))
1357 StartTimer ("ReleaseRequestState");
1358 eventHandler = Events [ReleaseRequestStateEvent];
1359 if (eventHandler != null){
1360 #pragma warning disable 219
1361 foreach (bool stop in RunHooks (eventHandler)) {
1363 // Ignore the stop signal while release the state
1367 #pragma warning restore 219
1371 if (stop_processing)
1374 StartTimer ("PostReleaseRequestState");
1375 eventHandler = Events [PostReleaseRequestStateEvent];
1376 if (eventHandler != null)
1377 foreach (bool stop in RunHooks (eventHandler))
1381 StartTimer ("Filter");
1382 if (context.Error == null)
1383 context.Response.DoFilter (true);
1386 StartTimer ("UpdateRequestCache");
1387 eventHandler = Events [UpdateRequestCacheEvent];
1388 if (eventHandler != null)
1389 foreach (bool stop in RunHooks (eventHandler))
1393 StartTimer ("PostUpdateRequestCache");
1394 eventHandler = Events [PostUpdateRequestCacheEvent];
1395 if (eventHandler != null)
1396 foreach (bool stop in RunHooks (eventHandler))
1400 StartTimer ("LogRequest");
1401 eventHandler = Events [LogRequestEvent];
1402 if (eventHandler != null)
1403 foreach (bool stop in RunHooks (eventHandler))
1407 StartTimer ("PostLogRequest");
1408 eventHandler = Events [PostLogRequestEvent];
1409 if (eventHandler != null)
1410 foreach (bool stop in RunHooks (eventHandler))
1414 StartTimer ("PipelineDone");
1420 internal CultureInfo GetThreadCulture (HttpRequest request, CultureInfo culture, bool isAuto)
1424 CultureInfo ret = null;
1425 string[] languages = request.UserLanguages;
1427 if (languages != null && languages.Length > 0)
1428 ret = CultureInfo.CreateSpecificCulture (languages[0]);
1441 GlobalizationSection cfg;
1442 cfg = (GlobalizationSection) WebConfigurationManager.GetSection ("system.web/globalization");
1443 app_culture = cfg.GetCulture ();
1444 autoCulture = cfg.IsAutoCulture;
1445 appui_culture = cfg.GetUICulture ();
1446 autoUICulture = cfg.IsAutoUICulture;
1447 context.StartTimeoutTimer ();
1448 Thread th = Thread.CurrentThread;
1449 if (app_culture != null) {
1450 prev_app_culture = th.CurrentCulture;
1451 CultureInfo new_app_culture = GetThreadCulture (Request, app_culture, autoCulture);
1452 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1453 th.CurrentCulture = new_app_culture;
1456 if (appui_culture != null) {
1457 prev_appui_culture = th.CurrentUICulture;
1458 CultureInfo new_app_culture = GetThreadCulture (Request, appui_culture, autoUICulture);
1459 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1460 th.CurrentUICulture = new_app_culture;
1463 prev_user = Thread.CurrentPrincipal;
1468 if (removeConfigurationFromCache) {
1469 WebConfigurationManager.RemoveConfigurationFromCache (context);
1470 removeConfigurationFromCache = false;
1473 Thread th = Thread.CurrentThread;
1474 if (Thread.CurrentPrincipal != prev_user)
1475 Thread.CurrentPrincipal = prev_user;
1476 if (prev_appui_culture != null && prev_appui_culture != th.CurrentUICulture)
1477 th.CurrentUICulture = prev_appui_culture;
1478 if (prev_app_culture != null && prev_app_culture != th.CurrentCulture)
1479 th.CurrentCulture = prev_app_culture;
1481 if (context == null)
1482 context = HttpContext.Current;
1483 context.StopTimeoutTimer ();
1484 context.Request.ReleaseResources ();
1485 context.Response.ReleaseResources ();
1488 HttpContext.Current = null;
1491 void Start (object x)
1493 var cultures = x as CultureInfo [];
1494 if (cultures != null && cultures.Length == 2) {
1495 Thread ct = Thread.CurrentThread;
1496 ct.CurrentCulture = cultures [0];
1497 ct.CurrentUICulture = cultures [1];
1501 if (initialization_exception != null) {
1502 Exception e = initialization_exception;
1503 HttpException exc = HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort);
1504 context.Response.StatusCode = 500;
1505 FinalErrorWrite (context.Response, exc.GetHtmlErrorMessage ());
1510 HttpContext.Current = Context;
1512 pipeline = Pipeline ();
1516 const string HANDLER_CACHE = "@@HttpHandlerCache@@";
1518 internal static Hashtable GetHandlerCache ()
1520 Cache cache = HttpRuntime.InternalCache;
1521 Hashtable ret = cache [HANDLER_CACHE] as Hashtable;
1524 ret = new Hashtable ();
1525 cache.Insert (HANDLER_CACHE, ret);
1531 internal static void ClearHandlerCache ()
1533 Hashtable cache = GetHandlerCache ();
1537 object LocateHandler (HttpRequest req, string verb, string url)
1539 Hashtable cache = GetHandlerCache ();
1540 string id = String.Concat (verb, url);
1541 object ret = cache [id];
1547 HttpHandlersSection httpHandlersSection = WebConfigurationManager.GetSection ("system.web/httpHandlers", req.Path, req.Context) as HttpHandlersSection;
1548 ret = httpHandlersSection.LocateHandler (verb, url, out allowCache);
1550 IHttpHandler handler = ret as IHttpHandler;
1551 if (allowCache && handler != null && handler.IsReusable)
1557 internal IHttpHandler GetHandler (HttpContext context, string url)
1559 return GetHandler (context, url, false);
1562 // Used by HttpServerUtility.Execute
1563 internal IHttpHandler GetHandler (HttpContext context, string url, bool ignoreContextHandler)
1565 if (!ignoreContextHandler && context.Handler != null)
1566 return context.Handler;
1568 HttpRequest request = context.Request;
1569 string verb = request.RequestType;
1571 IHttpHandler handler = null;
1572 object o = LocateHandler (request, verb, url);
1574 factory = o as IHttpHandlerFactory;
1575 if (factory == null) {
1576 handler = (IHttpHandler) o;
1578 handler = factory.GetHandler (context, verb, url, request.MapPath (url));
1584 void IHttpHandler.ProcessRequest (HttpContext context)
1587 this.context = context;
1595 // This is used by FireOnAppStart, when we init the application
1596 // as the context is required to be set at that point (the user
1597 // might call methods that require it on that hook).
1599 internal void SetContext (HttpContext context)
1601 this.context = context;
1604 internal void SetSession (HttpSessionState session)
1606 this.session = session;
1609 IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
1611 this.context = context;
1614 begin_iar = new AsyncRequestState (done, cb, extraData);
1616 CultureInfo[] cultures = new CultureInfo [2];
1617 cultures [0] = Thread.CurrentThread.CurrentCulture;
1618 cultures [1] = Thread.CurrentThread.CurrentUICulture;
1620 if (Thread.CurrentThread.IsThreadPoolThread)
1623 ThreadPool.QueueUserWorkItem (x => {
1626 } catch (Exception e) {
1627 Console.Error.WriteLine (e);
1634 void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
1636 if (!result.IsCompleted)
1637 result.AsyncWaitHandle.WaitOne ();
1641 public virtual void Init ()
1645 bool IHttpHandler.IsReusable {
1652 internal void ClearError ()
1654 context.ClearError ();
1657 bool RedirectErrorPage (string error_page)
1659 if (context.Request.QueryString ["aspxerrorpath"] != null)
1662 Response.Redirect (error_page + "?aspxerrorpath=" + Request.Path, false);
1666 bool RedirectCustomError (ref HttpException httpEx)
1669 if (!context.IsCustomErrorEnabledUnsafe)
1672 CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");
1673 if (config == null) {
1674 if (context.ErrorPage != null)
1675 return RedirectErrorPage (context.ErrorPage);
1680 CustomError err = config.Errors [context.Response.StatusCode.ToString()];
1681 string redirect = err == null ? null : err.Redirect;
1682 if (redirect == null) {
1683 redirect = context.ErrorPage;
1684 if (redirect == null)
1685 redirect = config.DefaultRedirect;
1688 if (redirect == null)
1691 if (config.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite) {
1692 context.Server.Execute (redirect);
1696 return RedirectErrorPage (redirect);
1698 catch (Exception ex) {
1699 httpEx = HttpException.NewWithCode (500, String.Empty, ex, WebEventCodes.WebErrorOtherError);
1704 internal static string BinDirectory
1707 if (binDirectory == null) {
1708 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
1709 string baseDir = setup.ApplicationBase;
1712 foreach (string dir in BinDirs) {
1713 bindir = Path.Combine (baseDir, dir);
1714 if (!Directory.Exists (bindir))
1716 binDirectory = bindir;
1721 return binDirectory;
1725 internal static string[] BinDirectoryAssemblies
1728 ArrayList binDlls = null;
1731 string bindir = BinDirectory;
1732 if (bindir != null) {
1733 binDlls = new ArrayList ();
1734 dlls = Directory.GetFiles (bindir, "*.dll");
1735 binDlls.AddRange (dlls);
1738 if (binDlls == null)
1739 return new string[] {};
1741 return (string[]) binDlls.ToArray (typeof (string));
1745 internal static Type LoadType (string typeName)
1747 return LoadType (typeName, false);
1750 internal static Type LoadType (string typeName, bool throwOnMissing)
1752 Type type = Type.GetType (typeName);
1756 Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
1757 foreach (Assembly ass in assemblies) {
1758 type = ass.GetType (typeName, false);
1763 IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
1764 if (tla != null && tla.Count > 0) {
1765 foreach (Assembly asm in tla) {
1768 type = asm.GetType (typeName, false);
1774 Exception loadException = null;
1777 type = LoadTypeFromBin (typeName);
1778 } catch (Exception ex) {
1785 throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName), loadException);
1790 internal static Type LoadType <TBaseType> (string typeName, bool throwOnMissing)
1792 Type ret = LoadType (typeName, throwOnMissing);
1794 if (typeof (TBaseType).IsAssignableFrom (ret))
1798 throw new TypeLoadException (String.Format ("Type '{0}' found but it doesn't derive from base type '{1}'.", typeName, typeof (TBaseType)));
1803 internal static Type LoadTypeFromBin (string typeName)
1807 foreach (string s in BinDirectoryAssemblies) {
1808 Assembly binA = null;
1811 binA = Assembly.LoadFrom (s);
1812 } catch (FileLoadException) {
1815 } catch (BadImageFormatException) {
1820 type = binA.GetType (typeName, false);
1832 // Based on Fritz' Onion's AsyncRequestState class for asynchronous IHttpAsyncHandlers
1834 class AsyncRequestState : IAsyncResult {
1838 ManualResetEvent complete_event = null;
1840 internal AsyncRequestState (ManualResetEvent complete_event, AsyncCallback cb, object cb_data)
1843 this.cb_data = cb_data;
1844 this.complete_event = complete_event;
1847 internal void Complete ()
1852 // TODO: if this throws an error, we have no way of reporting it
1853 // Not really too bad, since the only failure might be
1854 // `HttpRuntime.request_processed'.
1861 complete_event.Set ();
1864 public object AsyncState {
1870 public bool CompletedSynchronously {
1876 public bool IsCompleted {
1882 public WaitHandle AsyncWaitHandle {
1884 return complete_event;
1889 #region Helper classes
1892 // A wrapper to keep track of begin/end pairs
1894 class AsyncInvoker {
1895 public BeginEventHandler begin;
1896 public EndEventHandler end;
1899 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, object d)
1906 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh)
1912 public void Invoke (object sender, EventArgs e)
1914 throw new Exception ("This is just a dummy");