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 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 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)
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()));
209 modcoll = modules.LoadModules (this);
210 HttpContext.Current = saved;
213 HttpApplicationFactory.AttachEvents (this);
215 fullInitComplete = true;
220 internal bool InApplicationStart {
221 get { return in_application_start; }
222 set { in_application_start = value; }
225 internal string AssemblyLocation {
227 if (assemblyLocation == null)
228 assemblyLocation = GetType ().Assembly.Location;
229 return assemblyLocation;
233 internal static Exception InitializationException {
234 get { return initialization_exception; }
238 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
239 public HttpApplicationState Application {
241 return HttpApplicationFactory.ApplicationState;
246 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
247 public HttpContext Context {
253 protected EventHandlerList Events {
256 events = new EventHandlerList ();
263 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
264 public HttpModuleCollection Modules {
265 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
269 modcoll = new HttpModuleCollection ();
277 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
278 public HttpRequest Request {
281 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
283 if (false == HttpApplicationFactory.ContextAvailable)
284 throw HttpException.NewWithCode (Locale.GetText ("Request is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
286 return context.Request;
291 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
292 public HttpResponse Response {
295 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
297 if (false == HttpApplicationFactory.ContextAvailable)
298 throw HttpException.NewWithCode (Locale.GetText ("Response is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
300 return context.Response;
305 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
306 public HttpServerUtility Server {
309 return context.Server;
312 // This is so we can get the Server and call a few methods
313 // which are not context sensitive, see HttpServerUtilityTest
315 return new HttpServerUtility ((HttpContext) null);
320 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
321 public HttpSessionState Session {
323 // Only used for Session_End
328 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
330 HttpSessionState ret = context.Session;
332 throw HttpException.NewWithCode (Locale.GetText ("Session state is not available in the context."), WebEventCodes.RuntimeErrorRequestAbort);
339 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
341 get { return isite; }
343 set { isite = value; }
347 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
348 public IPrincipal User {
351 throw new HttpException (Locale.GetText ("No context is available."));
352 if (context.User == null)
353 throw new HttpException (Locale.GetText ("No currently authenticated user."));
359 static object PreSendRequestHeadersEvent = new object ();
360 public event EventHandler PreSendRequestHeaders
362 add { AddEventHandler (PreSendRequestHeadersEvent, value); }
363 remove { RemoveEventHandler (PreSendRequestHeadersEvent, value); }
366 internal void TriggerPreSendRequestHeaders ()
368 EventHandler handler = Events [PreSendRequestHeadersEvent] as EventHandler;
370 handler (this, EventArgs.Empty);
373 static object PreSendRequestContentEvent = new object ();
374 public event EventHandler PreSendRequestContent
376 add { AddEventHandler (PreSendRequestContentEvent, value); }
377 remove { RemoveEventHandler (PreSendRequestContentEvent, value); }
380 internal void TriggerPreSendRequestContent ()
382 EventHandler handler = Events [PreSendRequestContentEvent] as EventHandler;
384 handler (this, EventArgs.Empty);
387 static object AcquireRequestStateEvent = new object ();
388 public event EventHandler AcquireRequestState
390 add { AddEventHandler (AcquireRequestStateEvent, value); }
391 remove { RemoveEventHandler (AcquireRequestStateEvent, value); }
394 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
396 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
397 AcquireRequestState += new EventHandler (invoker.Invoke);
400 static object AuthenticateRequestEvent = new object ();
401 public event EventHandler AuthenticateRequest
403 add { AddEventHandler (AuthenticateRequestEvent, value); }
404 remove { RemoveEventHandler (AuthenticateRequestEvent, value); }
407 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
409 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
410 AuthenticateRequest += new EventHandler (invoker.Invoke);
413 static object AuthorizeRequestEvent = new object ();
414 public event EventHandler AuthorizeRequest
416 add { AddEventHandler (AuthorizeRequestEvent, value); }
417 remove { RemoveEventHandler (AuthorizeRequestEvent, value); }
420 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
422 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
423 AuthorizeRequest += new EventHandler (invoker.Invoke);
426 static object BeginRequestEvent = new object ();
427 public event EventHandler BeginRequest
430 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
431 if (InApplicationStart)
433 AddEventHandler (BeginRequestEvent, value);
436 if (InApplicationStart)
438 RemoveEventHandler (BeginRequestEvent, value);
442 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
444 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
445 BeginRequest += new EventHandler (invoker.Invoke);
448 static object EndRequestEvent = new object ();
449 public event EventHandler EndRequest
452 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
453 if (InApplicationStart)
455 AddEventHandler (EndRequestEvent, value);
458 if (InApplicationStart)
460 RemoveEventHandler (EndRequestEvent, value);
464 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
466 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
467 EndRequest += new EventHandler (invoker.Invoke);
470 static object PostRequestHandlerExecuteEvent = new object ();
471 public event EventHandler PostRequestHandlerExecute
473 add { AddEventHandler (PostRequestHandlerExecuteEvent, value); }
474 remove { RemoveEventHandler (PostRequestHandlerExecuteEvent, value); }
477 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
479 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
480 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
483 static object PreRequestHandlerExecuteEvent = new object ();
484 public event EventHandler PreRequestHandlerExecute
486 add { AddEventHandler (PreRequestHandlerExecuteEvent, value); }
487 remove { RemoveEventHandler (PreRequestHandlerExecuteEvent, value); }
490 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
492 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
493 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
496 static object ReleaseRequestStateEvent = new object ();
497 public event EventHandler ReleaseRequestState
499 add { AddEventHandler (ReleaseRequestStateEvent, value); }
500 remove { RemoveEventHandler (ReleaseRequestStateEvent, value); }
503 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
505 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
506 ReleaseRequestState += new EventHandler (invoker.Invoke);
509 static object ResolveRequestCacheEvent = new object ();
510 public event EventHandler ResolveRequestCache
512 add { AddEventHandler (ResolveRequestCacheEvent, value); }
513 remove { RemoveEventHandler (ResolveRequestCacheEvent, value); }
516 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
518 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
519 ResolveRequestCache += new EventHandler (invoker.Invoke);
522 static object UpdateRequestCacheEvent = new object ();
523 public event EventHandler UpdateRequestCache
525 add { AddEventHandler (UpdateRequestCacheEvent, value); }
526 remove { RemoveEventHandler (UpdateRequestCacheEvent, value); }
529 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
531 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
532 UpdateRequestCache += new EventHandler (invoker.Invoke);
535 static object PostAuthenticateRequestEvent = new object ();
536 public event EventHandler PostAuthenticateRequest
538 add { AddEventHandler (PostAuthenticateRequestEvent, value); }
539 remove { RemoveEventHandler (PostAuthenticateRequestEvent, value); }
542 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
544 AddOnPostAuthenticateRequestAsync (bh, eh, null);
547 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
549 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
550 PostAuthenticateRequest += new EventHandler (invoker.Invoke);
553 static object PostAuthorizeRequestEvent = new object ();
554 public event EventHandler PostAuthorizeRequest
556 add { AddEventHandler (PostAuthorizeRequestEvent, value); }
557 remove { RemoveEventHandler (PostAuthorizeRequestEvent, value); }
560 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
562 AddOnPostAuthorizeRequestAsync (bh, eh, null);
565 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
567 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
568 PostAuthorizeRequest += new EventHandler (invoker.Invoke);
571 static object PostResolveRequestCacheEvent = new object ();
572 public event EventHandler PostResolveRequestCache
574 add { AddEventHandler (PostResolveRequestCacheEvent, value); }
575 remove { RemoveEventHandler (PostResolveRequestCacheEvent, value); }
578 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
580 AddOnPostResolveRequestCacheAsync (bh, eh, null);
583 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
585 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
586 PostResolveRequestCache += new EventHandler (invoker.Invoke);
589 static object PostMapRequestHandlerEvent = new object ();
590 public event EventHandler PostMapRequestHandler
592 add { AddEventHandler (PostMapRequestHandlerEvent, value); }
593 remove { RemoveEventHandler (PostMapRequestHandlerEvent, value); }
596 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
598 AddOnPostMapRequestHandlerAsync (bh, eh, null);
601 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh, object data)
603 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
604 PostMapRequestHandler += new EventHandler (invoker.Invoke);
607 static object PostAcquireRequestStateEvent = new object ();
608 public event EventHandler PostAcquireRequestState
610 add { AddEventHandler (PostAcquireRequestStateEvent, value); }
611 remove { RemoveEventHandler (PostAcquireRequestStateEvent, value); }
614 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
616 AddOnPostAcquireRequestStateAsync (bh, eh, null);
619 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
621 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
622 PostAcquireRequestState += new EventHandler (invoker.Invoke);
625 static object PostReleaseRequestStateEvent = new object ();
626 public event EventHandler PostReleaseRequestState
628 add { AddEventHandler (PostReleaseRequestStateEvent, value); }
629 remove { RemoveEventHandler (PostReleaseRequestStateEvent, value); }
632 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
634 AddOnPostReleaseRequestStateAsync (bh, eh, null);
637 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
639 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
640 PostReleaseRequestState += new EventHandler (invoker.Invoke);
643 static object PostUpdateRequestCacheEvent = new object ();
644 public event EventHandler PostUpdateRequestCache
646 add { AddEventHandler (PostUpdateRequestCacheEvent, value); }
647 remove { RemoveEventHandler (PostUpdateRequestCacheEvent, value); }
650 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
652 AddOnPostUpdateRequestCacheAsync (bh, eh, null);
655 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
657 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
658 PostUpdateRequestCache += new EventHandler (invoker.Invoke);
662 // The new overloads that take a data parameter
664 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
666 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
667 AcquireRequestState += new EventHandler (invoker.Invoke);
670 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
672 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
673 AuthenticateRequest += new EventHandler (invoker.Invoke);
676 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
678 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
679 AuthorizeRequest += new EventHandler (invoker.Invoke);
682 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
684 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
685 BeginRequest += new EventHandler (invoker.Invoke);
688 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
690 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
691 EndRequest += new EventHandler (invoker.Invoke);
694 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
696 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
697 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
700 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
702 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
703 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
706 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
708 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
709 ReleaseRequestState += new EventHandler (invoker.Invoke);
712 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
714 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
715 ResolveRequestCache += new EventHandler (invoker.Invoke);
718 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
720 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
721 UpdateRequestCache += new EventHandler (invoker.Invoke);
725 // They are for use with the IIS7 integrated mode, but have been added for
727 static object LogRequestEvent = new object ();
728 public event EventHandler LogRequest
730 add { AddEventHandler (LogRequestEvent, value); }
731 remove { RemoveEventHandler (LogRequestEvent, value); }
734 public void AddOnLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
736 AddOnLogRequestAsync (bh, eh, null);
739 public void AddOnLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
741 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
742 LogRequest += new EventHandler (invoker.Invoke);
745 static object MapRequestHandlerEvent = new object ();
746 public event EventHandler MapRequestHandler
748 add { AddEventHandler (MapRequestHandlerEvent, value); }
749 remove { RemoveEventHandler (MapRequestHandlerEvent, value); }
752 public void AddOnMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
754 AddOnMapRequestHandlerAsync (bh, eh, null);
757 public void AddOnMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
759 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
760 MapRequestHandler += new EventHandler (invoker.Invoke);
763 static object PostLogRequestEvent = new object ();
764 public event EventHandler PostLogRequest
766 add { AddEventHandler (PostLogRequestEvent, value); }
767 remove { RemoveEventHandler (PostLogRequestEvent, value); }
770 public void AddOnPostLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
772 AddOnPostLogRequestAsync (bh, eh, null);
775 public void AddOnPostLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
777 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
778 PostLogRequest += new EventHandler (invoker.Invoke);
781 internal event EventHandler DefaultAuthentication;
783 void AddEventHandler (object key, EventHandler handler)
785 if (fullInitComplete)
788 Events.AddHandler (key, handler);
791 void RemoveEventHandler (object key, EventHandler handler)
793 if (fullInitComplete)
796 Events.RemoveHandler (key, handler);
800 // Bypass all the event on the Http pipeline and go directly to EndRequest
802 public void CompleteRequest ()
804 stop_processing = true;
807 internal bool RequestCompleted {
808 set { stop_processing = value; }
811 internal void DisposeInternal ()
815 if (modcoll != null) {
816 for (int i = modcoll.Count - 1; i >= 0; i--) {
817 modcoll.Get (i).Dispose ();
823 EventHandler eh = nonApplicationEvents [disposedEvent] as EventHandler;
825 eh (this, EventArgs.Empty);
831 public virtual void Dispose ()
836 public virtual string GetOutputCacheProviderName (HttpContext context)
838 // LAMESPEC: doesn't throw ProviderException if context is null
839 return OutputCache.DefaultProviderName;
843 public virtual string GetVaryByCustomString (HttpContext context, string custom)
845 if (custom == null) // Sigh
846 throw new NullReferenceException ();
848 if (0 == String.Compare (custom, "browser", true, Helpers.InvariantCulture))
849 return context.Request.Browser.Type;
854 bool ShouldHandleException (Exception e)
856 if (e is ParseException)
863 // If we catch an error, queue this error
865 void ProcessError (Exception e)
867 bool first = context.Error == null;
868 context.AddError (e);
869 if (first && ShouldHandleException (e)) {
870 EventHandler eh = nonApplicationEvents [errorEvent] as EventHandler;
873 eh (this, EventArgs.Empty);
875 context.ClearError ();
876 } catch (ThreadAbortException taex){
877 context.ClearError ();
878 if (FlagEnd.Value == taex.ExceptionState || HttpRuntime.DomainUnloading)
879 // This happens on Redirect(), End() and
880 // when unloading the AppDomain
881 Thread.ResetAbort ();
883 // This happens on Thread.Abort()
884 context.AddError (taex);
885 } catch (Exception ee){
886 context.AddError (ee);
890 stop_processing = true;
892 // we want to remove configuration from the cache in case of
893 // invalid resource not exists to prevent DOS attack.
894 HttpException httpEx = e as HttpException;
895 if (httpEx != null && httpEx.GetHttpCode () == 404) {
896 removeConfigurationFromCache = true;
901 // Ticks the clock: next step on the pipeline.
903 internal void Tick ()
907 if (context.Error is UnifyRequestException) {
908 Exception ex = context.Error.InnerException;
909 context.ClearError ();
910 vmw.common.TypeUtils.Throw (ex);
914 if (pipeline.MoveNext ()){
915 if ((bool)pipeline.Current)
920 catch (Exception ex) {
921 if (ex is ThreadAbortException &&
922 ((ThreadAbortException) ex).ExceptionState == FlagEnd.Value)
924 if (context.WorkerRequest is IHttpUnifyWorkerRequest) {
925 context.ClearError ();
926 context.AddError (new UnifyRequestException (ex));
933 } catch (ThreadAbortException taex) {
934 object obj = taex.ExceptionState;
935 Thread.ResetAbort ();
936 if (obj is StepTimeout)
937 ProcessError (HttpException.NewWithCode ("The request timed out.", WebEventCodes.RequestTransactionAbort));
939 context.ClearError ();
940 if (FlagEnd.Value != obj && !HttpRuntime.DomainUnloading)
941 context.AddError (taex);
944 stop_processing = true;
946 } catch (Exception e) {
948 stop_processing = true;
962 // Invoked when our async callback called from RunHooks completes,
963 // we restart the pipeline here.
965 void async_callback_completed_cb (IAsyncResult ar)
967 if (current_ai.end != null){
970 } catch (Exception e) {
978 void async_handler_complete_cb (IAsyncResult ar)
980 IHttpAsyncHandler async_handler = ar != null ? ar.AsyncState as IHttpAsyncHandler : null;
983 if (async_handler != null)
984 async_handler.EndProcessRequest (ar);
985 } catch (Exception e){
993 // This enumerator yields whether processing must be stopped:
994 // true: processing of the pipeline must be stopped
995 // false: processing of the pipeline must not be stopped
997 IEnumerable RunHooks (Delegate list)
999 Delegate [] delegates = list.GetInvocationList ();
1001 foreach (EventHandler d in delegates){
1002 if (d.Target != null && (d.Target is AsyncInvoker)){
1003 current_ai = (AsyncInvoker) d.Target;
1008 context.BeginTimeoutPossible ();
1009 current_ai.begin (this, EventArgs.Empty, async_callback_completed_cb, current_ai.data);
1012 context.EndTimeoutPossible ();
1016 // If things are still moving forward, yield this
1020 yield return stop_processing;
1021 else if (stop_processing)
1025 context.BeginTimeoutPossible ();
1026 d (this, EventArgs.Empty);
1028 context.EndTimeoutPossible ();
1030 if (stop_processing)
1036 static void FinalErrorWrite (HttpResponse response, string error)
1039 response.Write (error);
1040 response.Flush (true);
1048 if (context.Error == null){
1050 context.Response.Flush (true);
1051 } catch (Exception e){
1052 context.AddError (e);
1056 Exception error = context.Error;
1058 HttpResponse response = context.Response;
1060 if (!response.HeadersSent){
1061 response.ClearHeaders ();
1062 response.ClearContent ();
1064 if (error is HttpException){
1065 response.StatusCode = ((HttpException)error).GetHttpCode ();
1067 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1068 response.StatusCode = 500;
1070 HttpException httpEx = (HttpException) error;
1071 if (!RedirectCustomError (ref httpEx))
1072 FinalErrorWrite (response, httpEx.GetHtmlErrorMessage ());
1074 response.Flush (true);
1076 if (!(error is HttpException))
1077 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1078 FinalErrorWrite (response, ((HttpException) error).GetHtmlErrorMessage ());
1085 // Invoked at the end of the pipeline execution
1087 void PipelineDone ()
1090 EventHandler handler = Events [EndRequestEvent] as EventHandler;
1091 if (handler != null)
1092 handler (this, EventArgs.Empty);
1093 } catch (Exception e){
1099 } catch (ThreadAbortException taex) {
1100 ProcessError (taex);
1101 Thread.ResetAbort ();
1102 } catch (Exception e) {
1103 Console.WriteLine ("Internal error: OutputPage threw an exception " + e);
1105 context.WorkerRequest.EndOfRequest();
1106 if (factory != null && context.Handler != null){
1107 factory.ReleaseHandler (context.Handler);
1108 context.Handler = null;
1111 context.PopHandler ();
1113 // context = null; -> moved to PostDone
1119 if (begin_iar != null)
1120 begin_iar.Complete ();
1124 requests_total_counter.Increment ();
1134 public Tim (string name) {
1138 public string Name {
1139 get { return name; }
1140 set { name = value; }
1143 public void Start () {
1144 start = DateTime.UtcNow;
1147 public void Stop () {
1148 Console.WriteLine ("{0}: {1}ms", name, (DateTime.UtcNow - start).TotalMilliseconds);
1153 [Conditional ("PIPELINE_TIMER")]
1154 void StartTimer (string name)
1162 [Conditional ("PIPELINE_TIMER")]
1169 // Events fired as described in `Http Runtime Support, HttpModules,
1170 // Handling Public Events'
1172 IEnumerator Pipeline ()
1174 Delegate eventHandler;
1175 if (stop_processing)
1178 HttpRequest req = context.Request;
1182 context.MapRequestHandlerDone = false;
1183 StartTimer ("BeginRequest");
1184 eventHandler = Events [BeginRequestEvent];
1185 if (eventHandler != null) {
1186 foreach (bool stop in RunHooks (eventHandler))
1191 StartTimer ("AuthenticateRequest");
1192 eventHandler = Events [AuthenticateRequestEvent];
1193 if (eventHandler != null)
1194 foreach (bool stop in RunHooks (eventHandler))
1198 StartTimer ("DefaultAuthentication");
1199 if (DefaultAuthentication != null)
1200 foreach (bool stop in RunHooks (DefaultAuthentication))
1204 StartTimer ("PostAuthenticateRequest");
1205 eventHandler = Events [PostAuthenticateRequestEvent];
1206 if (eventHandler != null)
1207 foreach (bool stop in RunHooks (eventHandler))
1211 StartTimer ("AuthorizeRequest");
1212 eventHandler = Events [AuthorizeRequestEvent];
1213 if (eventHandler != null)
1214 foreach (bool stop in RunHooks (eventHandler))
1218 StartTimer ("PostAuthorizeRequest");
1219 eventHandler = Events [PostAuthorizeRequestEvent];
1220 if (eventHandler != null)
1221 foreach (bool stop in RunHooks (eventHandler))
1225 StartTimer ("ResolveRequestCache");
1226 eventHandler = Events [ResolveRequestCacheEvent];
1227 if (eventHandler != null)
1228 foreach (bool stop in RunHooks (eventHandler))
1232 StartTimer ("PostResolveRequestCache");
1233 eventHandler = Events [PostResolveRequestCacheEvent];
1234 if (eventHandler != null)
1235 foreach (bool stop in RunHooks (eventHandler))
1239 StartTimer ("MapRequestHandler");
1240 // As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
1241 eventHandler = Events [MapRequestHandlerEvent];
1242 if (eventHandler != null)
1243 foreach (bool stop in RunHooks (eventHandler))
1246 context.MapRequestHandlerDone = true;
1248 StartTimer ("GetHandler");
1249 // Obtain the handler for the request.
1250 IHttpHandler handler = null;
1252 handler = GetHandler (context, context.Request.CurrentExecutionFilePath);
1253 context.Handler = handler;
1254 context.PushHandler (handler);
1255 } catch (FileNotFoundException fnf){
1257 Console.WriteLine ("$$$$$$$$$$:Sys.Web Pipeline");
1258 Console.WriteLine (fnf.ToString ());
1260 if (context.Request.IsLocal)
1261 ProcessError (HttpException.NewWithCode (404,
1262 String.Format ("File not found {0}", fnf.FileName),
1264 context.Request.FilePath,
1265 WebEventCodes.RuntimeErrorRequestAbort));
1267 ProcessError (HttpException.NewWithCode (404,
1268 "File not found: " + Path.GetFileName (fnf.FileName),
1269 context.Request.FilePath,
1270 WebEventCodes.RuntimeErrorRequestAbort));
1271 } catch (DirectoryNotFoundException dnf){
1272 if (!context.Request.IsLocal)
1273 dnf = null; // Do not "leak" real path information
1274 ProcessError (HttpException.NewWithCode (404, "Directory not found", dnf, WebEventCodes.RuntimeErrorRequestAbort));
1275 } catch (Exception e) {
1280 if (stop_processing)
1283 StartTimer ("PostMapRequestHandler");
1284 eventHandler = Events [PostMapRequestHandlerEvent];
1285 if (eventHandler != null)
1286 foreach (bool stop in RunHooks (eventHandler))
1290 StartTimer ("AcquireRequestState");
1291 eventHandler = Events [AcquireRequestStateEvent];
1292 if (eventHandler != null){
1293 foreach (bool stop in RunHooks (eventHandler))
1298 StartTimer ("PostAcquireRequestState");
1299 eventHandler = Events [PostAcquireRequestStateEvent];
1300 if (eventHandler != null){
1301 foreach (bool stop in RunHooks (eventHandler))
1307 // From this point on, we need to ensure that we call
1308 // ReleaseRequestState, so the code below jumps to
1309 // `release:' to guarantee it rather than yielding.
1311 StartTimer ("PreRequestHandlerExecute");
1312 eventHandler = Events [PreRequestHandlerExecuteEvent];
1313 if (eventHandler != null)
1314 foreach (bool stop in RunHooks (eventHandler))
1322 bool doProcessHandler = false;
1325 IHttpHandler ctxHandler = context.Handler;
1326 if (ctxHandler != null && handler != ctxHandler) {
1327 context.PopHandler ();
1328 handler = ctxHandler;
1329 context.PushHandler (handler);
1332 StartTimer ("ProcessRequest");
1334 context.BeginTimeoutPossible ();
1335 if (handler != null){
1336 IHttpAsyncHandler async_handler = handler as IHttpAsyncHandler;
1338 if (async_handler != null){
1341 async_handler.BeginProcessRequest (context, async_handler_complete_cb, handler);
1344 handler.ProcessRequest (context);
1346 IHttpExtendedHandler extHandler=handler as IHttpExtendedHandler;
1347 doProcessHandler = extHandler != null && !extHandler.IsCompleted;
1351 if (context.Error != null)
1352 throw new TargetInvocationException(context.Error);
1355 context.EndTimeoutPossible ();
1359 if (doProcessHandler) {
1361 goto processHandler;
1365 yield return stop_processing;
1366 else if (stop_processing)
1369 // These are executed after the application has returned
1371 StartTimer ("PostRequestHandlerExecute");
1372 eventHandler = Events [PostRequestHandlerExecuteEvent];
1373 if (eventHandler != null)
1374 foreach (bool stop in RunHooks (eventHandler))
1380 StartTimer ("ReleaseRequestState");
1381 eventHandler = Events [ReleaseRequestStateEvent];
1382 if (eventHandler != null){
1383 #pragma warning disable 219
1384 foreach (bool stop in RunHooks (eventHandler)) {
1386 // Ignore the stop signal while release the state
1390 #pragma warning restore 219
1394 if (stop_processing)
1397 StartTimer ("PostReleaseRequestState");
1398 eventHandler = Events [PostReleaseRequestStateEvent];
1399 if (eventHandler != null)
1400 foreach (bool stop in RunHooks (eventHandler))
1404 StartTimer ("Filter");
1405 if (context.Error == null)
1406 context.Response.DoFilter (true);
1409 StartTimer ("UpdateRequestCache");
1410 eventHandler = Events [UpdateRequestCacheEvent];
1411 if (eventHandler != null)
1412 foreach (bool stop in RunHooks (eventHandler))
1416 StartTimer ("PostUpdateRequestCache");
1417 eventHandler = Events [PostUpdateRequestCacheEvent];
1418 if (eventHandler != null)
1419 foreach (bool stop in RunHooks (eventHandler))
1423 StartTimer ("LogRequest");
1424 eventHandler = Events [LogRequestEvent];
1425 if (eventHandler != null)
1426 foreach (bool stop in RunHooks (eventHandler))
1430 StartTimer ("PostLogRequest");
1431 eventHandler = Events [PostLogRequestEvent];
1432 if (eventHandler != null)
1433 foreach (bool stop in RunHooks (eventHandler))
1437 StartTimer ("PipelineDone");
1443 internal CultureInfo GetThreadCulture (HttpRequest request, CultureInfo culture, bool isAuto)
1447 CultureInfo ret = null;
1448 string[] languages = request.UserLanguages;
1450 if (languages != null && languages.Length > 0)
1451 ret = CultureInfo.CreateSpecificCulture (languages[0]);
1464 GlobalizationSection cfg;
1465 cfg = (GlobalizationSection) WebConfigurationManager.GetSection ("system.web/globalization");
1466 app_culture = cfg.GetCulture ();
1467 autoCulture = cfg.IsAutoCulture;
1468 appui_culture = cfg.GetUICulture ();
1469 autoUICulture = cfg.IsAutoUICulture;
1471 context.StartTimeoutTimer ();
1473 Thread th = Thread.CurrentThread;
1474 if (app_culture != null) {
1475 prev_app_culture = th.CurrentCulture;
1476 CultureInfo new_app_culture = GetThreadCulture (Request, app_culture, autoCulture);
1477 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1478 th.CurrentCulture = new_app_culture;
1481 if (appui_culture != null) {
1482 prev_appui_culture = th.CurrentUICulture;
1483 CultureInfo new_app_culture = GetThreadCulture (Request, appui_culture, autoUICulture);
1484 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1485 th.CurrentUICulture = new_app_culture;
1489 prev_user = Thread.CurrentPrincipal;
1495 if (removeConfigurationFromCache) {
1496 WebConfigurationManager.RemoveConfigurationFromCache (context);
1497 removeConfigurationFromCache = false;
1500 Thread th = Thread.CurrentThread;
1502 if (Thread.CurrentPrincipal != prev_user)
1503 Thread.CurrentPrincipal = prev_user;
1505 if (prev_appui_culture != null && prev_appui_culture != th.CurrentUICulture)
1506 th.CurrentUICulture = prev_appui_culture;
1507 if (prev_app_culture != null && prev_app_culture != th.CurrentCulture)
1508 th.CurrentCulture = prev_app_culture;
1511 if (context == null)
1512 context = HttpContext.Current;
1513 context.StopTimeoutTimer ();
1515 context.Request.ReleaseResources ();
1516 context.Response.ReleaseResources ();
1519 HttpContext.Current = null;
1522 void Start (object x)
1524 var cultures = x as CultureInfo [];
1525 if (cultures != null && cultures.Length == 2) {
1526 Thread ct = Thread.CurrentThread;
1527 ct.CurrentCulture = cultures [0];
1528 ct.CurrentUICulture = cultures [1];
1533 } catch (Exception e) {
1534 initialization_exception = e;
1535 FinalErrorWrite (context.Response, HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort).GetHtmlErrorMessage ());
1540 HttpContext.Current = Context;
1542 pipeline = Pipeline ();
1546 const string HANDLER_CACHE = "@@HttpHandlerCache@@";
1548 internal static Hashtable GetHandlerCache ()
1550 Cache cache = HttpRuntime.InternalCache;
1551 Hashtable ret = cache [HANDLER_CACHE] as Hashtable;
1554 ret = new Hashtable ();
1555 cache.Insert (HANDLER_CACHE, ret);
1561 internal static void ClearHandlerCache ()
1563 Hashtable cache = GetHandlerCache ();
1567 object LocateHandler (HttpRequest req, string verb, string url)
1569 Hashtable cache = GetHandlerCache ();
1570 string id = String.Concat (verb, url);
1571 object ret = cache [id];
1577 HttpHandlersSection httpHandlersSection = WebConfigurationManager.GetSection ("system.web/httpHandlers", req.Path, req.Context) as HttpHandlersSection;
1578 ret = httpHandlersSection.LocateHandler (verb, url, out allowCache);
1580 IHttpHandler handler = ret as IHttpHandler;
1581 if (allowCache && handler != null && handler.IsReusable)
1587 internal IHttpHandler GetHandler (HttpContext context, string url)
1589 return GetHandler (context, url, false);
1592 // Used by HttpServerUtility.Execute
1593 internal IHttpHandler GetHandler (HttpContext context, string url, bool ignoreContextHandler)
1595 if (!ignoreContextHandler && context.Handler != null)
1596 return context.Handler;
1598 HttpRequest request = context.Request;
1599 string verb = request.RequestType;
1601 IHttpHandler handler = null;
1602 object o = LocateHandler (request, verb, url);
1604 factory = o as IHttpHandlerFactory;
1605 if (factory == null) {
1606 handler = (IHttpHandler) o;
1608 handler = factory.GetHandler (context, verb, url, request.MapPath (url));
1614 void IHttpHandler.ProcessRequest (HttpContext context)
1617 this.context = context;
1625 // This is used by FireOnAppStart, when we init the application
1626 // as the context is required to be set at that point (the user
1627 // might call methods that require it on that hook).
1629 internal void SetContext (HttpContext context)
1631 this.context = context;
1634 internal void SetSession (HttpSessionState session)
1636 this.session = session;
1639 IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
1641 this.context = context;
1644 begin_iar = new AsyncRequestState (done, cb, extraData);
1646 CultureInfo[] cultures = new CultureInfo [2];
1647 cultures [0] = Thread.CurrentThread.CurrentCulture;
1648 cultures [1] = Thread.CurrentThread.CurrentUICulture;
1653 if (Thread.CurrentThread.IsThreadPoolThread)
1657 ThreadPool.QueueUserWorkItem (x => {
1660 } catch (Exception e) {
1661 Console.Error.WriteLine (e);
1668 void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
1674 if (!result.IsCompleted)
1675 result.AsyncWaitHandle.WaitOne ();
1679 public virtual void Init ()
1683 bool IHttpHandler.IsReusable {
1690 internal void ClearError ()
1692 context.ClearError ();
1695 bool RedirectErrorPage (string error_page)
1697 if (context.Request.QueryString ["aspxerrorpath"] != null)
1700 Response.Redirect (error_page + "?aspxerrorpath=" + Request.Path, false);
1704 bool RedirectCustomError (ref HttpException httpEx)
1707 if (!context.IsCustomErrorEnabledUnsafe)
1710 CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");
1711 if (config == null) {
1712 if (context.ErrorPage != null)
1713 return RedirectErrorPage (context.ErrorPage);
1718 CustomError err = config.Errors [context.Response.StatusCode.ToString()];
1719 string redirect = err == null ? null : err.Redirect;
1720 if (redirect == null) {
1721 redirect = context.ErrorPage;
1722 if (redirect == null)
1723 redirect = config.DefaultRedirect;
1726 if (redirect == null)
1729 return RedirectErrorPage (redirect);
1731 catch (Exception ex) {
1732 httpEx = HttpException.NewWithCode (500, String.Empty, ex, WebEventCodes.WebErrorOtherError);
1737 internal static string BinDirectory
1740 if (binDirectory == null) {
1741 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
1742 string baseDir = setup.ApplicationBase;
1745 foreach (string dir in BinDirs) {
1746 bindir = Path.Combine (baseDir, dir);
1747 if (!Directory.Exists (bindir))
1749 binDirectory = bindir;
1754 return binDirectory;
1758 internal static string[] BinDirectoryAssemblies
1761 ArrayList binDlls = null;
1764 string bindir = BinDirectory;
1765 if (bindir != null) {
1766 binDlls = new ArrayList ();
1767 dlls = Directory.GetFiles (bindir, "*.dll");
1768 binDlls.AddRange (dlls);
1771 if (binDlls == null)
1772 return new string[] {};
1774 return (string[]) binDlls.ToArray (typeof (string));
1778 internal static Type LoadType (string typeName)
1780 return LoadType (typeName, false);
1783 internal static Type LoadType (string typeName, bool throwOnMissing)
1785 Type type = Type.GetType (typeName);
1790 Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
1791 foreach (Assembly ass in assemblies) {
1792 type = ass.GetType (typeName, false);
1797 IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
1798 if (tla != null && tla.Count > 0) {
1799 foreach (Assembly asm in tla) {
1802 type = asm.GetType (typeName, false);
1808 Exception loadException = null;
1811 type = LoadTypeFromBin (typeName);
1812 } catch (Exception ex) {
1820 throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName), loadException);
1825 internal static Type LoadType <TBaseType> (string typeName, bool throwOnMissing)
1827 Type ret = LoadType (typeName, throwOnMissing);
1829 if (typeof (TBaseType).IsAssignableFrom (ret))
1833 throw new TypeLoadException (String.Format ("Type '{0}' found but it doesn't derive from base type '{1}'.", typeName, typeof (TBaseType)));
1838 internal static Type LoadTypeFromBin (string typeName)
1842 foreach (string s in BinDirectoryAssemblies) {
1843 Assembly binA = null;
1846 binA = Assembly.LoadFrom (s);
1847 } catch (FileLoadException) {
1850 } catch (BadImageFormatException) {
1855 type = binA.GetType (typeName, false);
1867 // Based on Fritz' Onion's AsyncRequestState class for asynchronous IHttpAsyncHandlers
1869 class AsyncRequestState : IAsyncResult {
1873 ManualResetEvent complete_event = null;
1875 internal AsyncRequestState (ManualResetEvent complete_event, AsyncCallback cb, object cb_data)
1878 this.cb_data = cb_data;
1879 this.complete_event = complete_event;
1882 internal void Complete ()
1887 // TODO: if this throws an error, we have no way of reporting it
1888 // Not really too bad, since the only failure might be
1889 // `HttpRuntime.request_processed'.
1896 complete_event.Set ();
1899 public object AsyncState {
1905 public bool CompletedSynchronously {
1911 public bool IsCompleted {
1917 public WaitHandle AsyncWaitHandle {
1919 return complete_event;
1924 #region Helper classes
1927 // A wrapper to keep track of begin/end pairs
1929 class AsyncInvoker {
1930 public BeginEventHandler begin;
1931 public EndEventHandler end;
1934 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, object d)
1941 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh)
1947 public void Invoke (object sender, EventArgs e)
1949 throw new Exception ("This is just a dummy");