2 // System.Web.HttpApplication.cs
5 // Miguel de Icaza (miguel@novell.com)
6 // Gonzalo Paniagua (gonzalo@ximian.com)
7 // Matthias Bogad (bogad@cs.tum.edu)
10 // Copyright (C) 2005-2009 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 // The Application Processing Pipeline.
33 // The Http application pipeline implemented in this file is a
34 // beautiful thing. The application pipeline invokes a number of
35 // hooks at various stages of the processing of a request. These
36 // hooks can be either synchronous or can be asynchronous.
38 // The pipeline must ensure that every step is completed before
39 // moving to the next step. A trivial thing for synchronous
40 // hooks, but asynchronous hooks introduce an extra layer of
41 // complexity: when the hook is invoked, the thread must
42 // relinquish its control so that the thread can be reused in
43 // another operation while waiting.
45 // To implement this functionality we used C# iterators manually;
46 // we drive the pipeline by executing the various hooks from the
47 // `RunHooks' routine which is an enumerator that will yield the
48 // value `false' if execution must proceed or `true' if execution
51 // By yielding values we can suspend execution of RunHooks.
53 // Special attention must be given to `in_begin' and `must_yield'
54 // variables. These are used in the case that an async hook
55 // completes synchronously as its important to not yield in that
56 // case or we would hang.
58 // Many of Mono modules used to be declared async, but they would
59 // actually be completely synchronous, this might resurface in the
60 // future with other modules.
68 using System.Collections;
69 using System.Collections.Generic;
70 using System.ComponentModel;
71 using System.Configuration;
72 using System.Diagnostics;
73 using System.Globalization;
74 using System.Reflection;
75 using System.Security.Permissions;
76 using System.Security.Principal;
77 using System.Threading;
78 using System.Web.Caching;
79 using System.Web.Compilation;
80 using System.Web.Configuration;
81 using System.Web.Management;
82 using System.Web.SessionState;
84 using System.Web.Util;
90 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
91 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
94 public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
96 static readonly object disposedEvent = new object ();
97 static readonly object errorEvent = new object ();
99 // we do this static rather than per HttpApplication because
100 // mono's perfcounters use the counter instance parameter for
101 // the process to access shared memory.
102 internal static PerformanceCounter requests_total_counter = new PerformanceCounter ("ASP.NET", "Requests Total");
104 internal static readonly string [] BinDirs = {"Bin", "bin"};
105 object this_lock = new object();
108 HttpSessionState session;
111 // The source, and the exposed API (cache).
112 volatile HttpModuleCollection modcoll;
114 string assemblyLocation;
117 // The factory for the handler currently running.
119 IHttpHandlerFactory factory;
122 // Whether the thread culture is to be auto-set.
123 // Used only in the 2.0 profile, always false for 1.x
129 // Whether the pipeline should be stopped
131 bool stop_processing;
134 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
136 bool in_application_start;
141 IEnumerator pipeline;
143 // To flag when we are done processing a request from BeginProcessRequest.
144 ManualResetEvent done;
146 // The current IAsyncResult for the running async request handler in the pipeline
147 AsyncRequestState begin_iar;
149 // Tracks the current AsyncInvocation being dispatched
150 AsyncInvoker current_ai;
152 EventHandlerList events;
153 EventHandlerList nonApplicationEvents = new EventHandlerList ();
155 // Culture and IPrincipal
156 CultureInfo app_culture;
157 CultureInfo appui_culture;
158 CultureInfo prev_app_culture;
159 CultureInfo prev_appui_culture;
160 IPrincipal prev_user;
162 static string binDirectory;
164 static volatile Exception initialization_exception;
165 bool removeConfigurationFromCache;
166 bool fullInitComplete = false;
168 static DynamicModuleManager dynamicModuleManeger = new DynamicModuleManager ();
171 // These are used to detect the case where the EndXXX method is invoked
172 // from within the BeginXXXX delegate, so we detect whether we kick the
173 // pipeline from here, or from the the RunHook routine
178 public virtual event EventHandler Disposed {
179 add { nonApplicationEvents.AddHandler (disposedEvent, value); }
180 remove { nonApplicationEvents.RemoveHandler (disposedEvent, value); }
183 public virtual event EventHandler Error {
184 add { nonApplicationEvents.AddHandler (errorEvent, value); }
185 remove { nonApplicationEvents.RemoveHandler (errorEvent, value); }
188 public HttpApplication ()
190 done = new ManualResetEvent (false);
193 internal void InitOnce (bool full_init)
195 if (initialization_exception != null)
202 if (initialization_exception != null)
208 bool mustNullContext = context == null;
210 HttpModulesSection modules;
211 modules = (HttpModulesSection) WebConfigurationManager.GetWebApplicationSection ("system.web/httpModules");
212 HttpContext saved = HttpContext.Current;
213 HttpContext.Current = new HttpContext (new System.Web.Hosting.SimpleWorkerRequest (String.Empty, String.Empty, new StringWriter()));
215 context = HttpContext.Current;
216 HttpModuleCollection coll = modules.LoadModules (this);
218 HttpModuleCollection dynMods = CreateDynamicModules ();
220 for (int i = 0; i < dynMods.Count; i++) {
221 coll.AddModule (dynMods.GetKey (i), dynMods.Get (i));
224 Interlocked.CompareExchange (ref modcoll, coll, null);
225 HttpContext.Current = saved;
228 HttpApplicationFactory.AttachEvents (this);
230 fullInitComplete = true;
232 } catch (Exception e) {
233 initialization_exception = e;
234 Console.Error.WriteLine("Exception while initOnce: "+e.ToString());
235 // Once initialization_exception != null, we always respond with this exception
236 // You have to restart the HttpApplication to "unlock" it
237 Console.Error.WriteLine("Please restart your app to unlock it");
245 internal bool InApplicationStart {
246 get { return in_application_start; }
247 set { in_application_start = value; }
250 internal string AssemblyLocation {
252 if (assemblyLocation == null)
253 assemblyLocation = GetType ().Assembly.Location;
254 return assemblyLocation;
258 internal static Exception InitializationException {
259 get { return initialization_exception; }
263 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
264 public HttpApplicationState Application {
266 return HttpApplicationFactory.ApplicationState;
271 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
272 public HttpContext Context {
278 protected EventHandlerList Events {
281 events = new EventHandlerList ();
288 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
289 public HttpModuleCollection Modules {
290 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
293 modcoll = new HttpModuleCollection ();
300 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
301 public HttpRequest Request {
304 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
306 if (false == HttpApplicationFactory.ContextAvailable)
307 throw HttpException.NewWithCode (Locale.GetText ("Request is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
309 return context.Request;
314 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
315 public HttpResponse Response {
318 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
320 if (false == HttpApplicationFactory.ContextAvailable)
321 throw HttpException.NewWithCode (Locale.GetText ("Response is not available in this context."), WebEventCodes.RuntimeErrorRequestAbort);
323 return context.Response;
328 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
329 public HttpServerUtility Server {
332 return context.Server;
335 // This is so we can get the Server and call a few methods
336 // which are not context sensitive, see HttpServerUtilityTest
338 return new HttpServerUtility ((HttpContext) null);
343 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
344 public HttpSessionState Session {
346 // Only used for Session_End
351 throw HttpException.NewWithCode (Locale.GetText ("No context is available."), WebEventCodes.RuntimeErrorRequestAbort);
353 HttpSessionState ret = context.Session;
355 throw HttpException.NewWithCode (Locale.GetText ("Session state is not available in the context."), WebEventCodes.RuntimeErrorRequestAbort);
362 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
364 get { return isite; }
366 set { isite = value; }
370 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
371 public IPrincipal User {
374 throw new HttpException (Locale.GetText ("No context is available."));
375 if (context.User == null)
376 throw new HttpException (Locale.GetText ("No currently authenticated user."));
382 static object PreSendRequestHeadersEvent = new object ();
383 public event EventHandler PreSendRequestHeaders
385 add { AddEventHandler (PreSendRequestHeadersEvent, value); }
386 remove { RemoveEventHandler (PreSendRequestHeadersEvent, value); }
389 internal void TriggerPreSendRequestHeaders ()
391 EventHandler handler = Events [PreSendRequestHeadersEvent] as EventHandler;
393 handler (this, EventArgs.Empty);
396 static object PreSendRequestContentEvent = new object ();
397 public event EventHandler PreSendRequestContent
399 add { AddEventHandler (PreSendRequestContentEvent, value); }
400 remove { RemoveEventHandler (PreSendRequestContentEvent, value); }
403 internal void TriggerPreSendRequestContent ()
405 EventHandler handler = Events [PreSendRequestContentEvent] as EventHandler;
407 handler (this, EventArgs.Empty);
410 static object AcquireRequestStateEvent = new object ();
411 public event EventHandler AcquireRequestState
413 add { AddEventHandler (AcquireRequestStateEvent, value); }
414 remove { RemoveEventHandler (AcquireRequestStateEvent, value); }
417 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
419 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
420 AcquireRequestState += new EventHandler (invoker.Invoke);
423 static object AuthenticateRequestEvent = new object ();
424 public event EventHandler AuthenticateRequest
426 add { AddEventHandler (AuthenticateRequestEvent, value); }
427 remove { RemoveEventHandler (AuthenticateRequestEvent, value); }
430 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
432 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
433 AuthenticateRequest += new EventHandler (invoker.Invoke);
436 static object AuthorizeRequestEvent = new object ();
437 public event EventHandler AuthorizeRequest
439 add { AddEventHandler (AuthorizeRequestEvent, value); }
440 remove { RemoveEventHandler (AuthorizeRequestEvent, value); }
443 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
445 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
446 AuthorizeRequest += new EventHandler (invoker.Invoke);
449 static object BeginRequestEvent = new object ();
450 public event EventHandler BeginRequest
453 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
454 if (InApplicationStart)
456 AddEventHandler (BeginRequestEvent, value);
459 if (InApplicationStart)
461 RemoveEventHandler (BeginRequestEvent, value);
465 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
467 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
468 BeginRequest += new EventHandler (invoker.Invoke);
471 static object EndRequestEvent = new object ();
472 public event EventHandler EndRequest
475 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
476 if (InApplicationStart)
478 AddEventHandler (EndRequestEvent, value);
481 if (InApplicationStart)
483 RemoveEventHandler (EndRequestEvent, value);
487 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
489 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
490 EndRequest += new EventHandler (invoker.Invoke);
493 static object PostRequestHandlerExecuteEvent = new object ();
494 public event EventHandler PostRequestHandlerExecute
496 add { AddEventHandler (PostRequestHandlerExecuteEvent, value); }
497 remove { RemoveEventHandler (PostRequestHandlerExecuteEvent, value); }
500 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
502 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
503 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
506 static object PreRequestHandlerExecuteEvent = new object ();
507 public event EventHandler PreRequestHandlerExecute
509 add { AddEventHandler (PreRequestHandlerExecuteEvent, value); }
510 remove { RemoveEventHandler (PreRequestHandlerExecuteEvent, value); }
513 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
515 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
516 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
519 static object ReleaseRequestStateEvent = new object ();
520 public event EventHandler ReleaseRequestState
522 add { AddEventHandler (ReleaseRequestStateEvent, value); }
523 remove { RemoveEventHandler (ReleaseRequestStateEvent, value); }
526 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
528 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
529 ReleaseRequestState += new EventHandler (invoker.Invoke);
532 static object ResolveRequestCacheEvent = new object ();
533 public event EventHandler ResolveRequestCache
535 add { AddEventHandler (ResolveRequestCacheEvent, value); }
536 remove { RemoveEventHandler (ResolveRequestCacheEvent, value); }
539 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
541 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
542 ResolveRequestCache += new EventHandler (invoker.Invoke);
545 static object UpdateRequestCacheEvent = new object ();
546 public event EventHandler UpdateRequestCache
548 add { AddEventHandler (UpdateRequestCacheEvent, value); }
549 remove { RemoveEventHandler (UpdateRequestCacheEvent, value); }
552 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
554 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this);
555 UpdateRequestCache += new EventHandler (invoker.Invoke);
558 static object PostAuthenticateRequestEvent = new object ();
559 public event EventHandler PostAuthenticateRequest
561 add { AddEventHandler (PostAuthenticateRequestEvent, value); }
562 remove { RemoveEventHandler (PostAuthenticateRequestEvent, value); }
565 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
567 AddOnPostAuthenticateRequestAsync (bh, eh, null);
570 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
572 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
573 PostAuthenticateRequest += new EventHandler (invoker.Invoke);
576 static object PostAuthorizeRequestEvent = new object ();
577 public event EventHandler PostAuthorizeRequest
579 add { AddEventHandler (PostAuthorizeRequestEvent, value); }
580 remove { RemoveEventHandler (PostAuthorizeRequestEvent, value); }
583 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
585 AddOnPostAuthorizeRequestAsync (bh, eh, null);
588 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
590 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
591 PostAuthorizeRequest += new EventHandler (invoker.Invoke);
594 static object PostResolveRequestCacheEvent = new object ();
595 public event EventHandler PostResolveRequestCache
597 add { AddEventHandler (PostResolveRequestCacheEvent, value); }
598 remove { RemoveEventHandler (PostResolveRequestCacheEvent, value); }
601 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
603 AddOnPostResolveRequestCacheAsync (bh, eh, null);
606 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
608 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
609 PostResolveRequestCache += new EventHandler (invoker.Invoke);
612 static object PostMapRequestHandlerEvent = new object ();
613 public event EventHandler PostMapRequestHandler
615 add { AddEventHandler (PostMapRequestHandlerEvent, value); }
616 remove { RemoveEventHandler (PostMapRequestHandlerEvent, value); }
619 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
621 AddOnPostMapRequestHandlerAsync (bh, eh, null);
624 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh, object data)
626 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
627 PostMapRequestHandler += new EventHandler (invoker.Invoke);
630 static object PostAcquireRequestStateEvent = new object ();
631 public event EventHandler PostAcquireRequestState
633 add { AddEventHandler (PostAcquireRequestStateEvent, value); }
634 remove { RemoveEventHandler (PostAcquireRequestStateEvent, value); }
637 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
639 AddOnPostAcquireRequestStateAsync (bh, eh, null);
642 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
644 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
645 PostAcquireRequestState += new EventHandler (invoker.Invoke);
648 static object PostReleaseRequestStateEvent = new object ();
649 public event EventHandler PostReleaseRequestState
651 add { AddEventHandler (PostReleaseRequestStateEvent, value); }
652 remove { RemoveEventHandler (PostReleaseRequestStateEvent, value); }
655 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
657 AddOnPostReleaseRequestStateAsync (bh, eh, null);
660 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
662 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
663 PostReleaseRequestState += new EventHandler (invoker.Invoke);
666 static object PostUpdateRequestCacheEvent = new object ();
667 public event EventHandler PostUpdateRequestCache
669 add { AddEventHandler (PostUpdateRequestCacheEvent, value); }
670 remove { RemoveEventHandler (PostUpdateRequestCacheEvent, value); }
673 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
675 AddOnPostUpdateRequestCacheAsync (bh, eh, null);
678 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
680 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
681 PostUpdateRequestCache += new EventHandler (invoker.Invoke);
685 // The new overloads that take a data parameter
687 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
689 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
690 AcquireRequestState += new EventHandler (invoker.Invoke);
693 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
695 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
696 AuthenticateRequest += new EventHandler (invoker.Invoke);
699 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
701 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
702 AuthorizeRequest += new EventHandler (invoker.Invoke);
705 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
707 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
708 BeginRequest += new EventHandler (invoker.Invoke);
711 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
713 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
714 EndRequest += new EventHandler (invoker.Invoke);
717 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
719 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
720 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
723 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
725 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
726 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
729 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
731 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
732 ReleaseRequestState += new EventHandler (invoker.Invoke);
735 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
737 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
738 ResolveRequestCache += new EventHandler (invoker.Invoke);
741 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
743 AsyncInvoker invoker = new AsyncInvoker (bh, eh, this, data);
744 UpdateRequestCache += new EventHandler (invoker.Invoke);
748 // They are for use with the IIS7 integrated mode, but have been added for
750 static object LogRequestEvent = new object ();
751 public event EventHandler LogRequest
753 add { AddEventHandler (LogRequestEvent, value); }
754 remove { RemoveEventHandler (LogRequestEvent, value); }
757 public void AddOnLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
759 AddOnLogRequestAsync (bh, eh, null);
762 public void AddOnLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
764 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
765 LogRequest += new EventHandler (invoker.Invoke);
768 static object MapRequestHandlerEvent = new object ();
769 public event EventHandler MapRequestHandler
771 add { AddEventHandler (MapRequestHandlerEvent, value); }
772 remove { RemoveEventHandler (MapRequestHandlerEvent, value); }
775 public void AddOnMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
777 AddOnMapRequestHandlerAsync (bh, eh, null);
780 public void AddOnMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
782 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
783 MapRequestHandler += new EventHandler (invoker.Invoke);
786 static object PostLogRequestEvent = new object ();
787 public event EventHandler PostLogRequest
789 add { AddEventHandler (PostLogRequestEvent, value); }
790 remove { RemoveEventHandler (PostLogRequestEvent, value); }
793 public void AddOnPostLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
795 AddOnPostLogRequestAsync (bh, eh, null);
798 public void AddOnPostLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
800 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, this, state);
801 PostLogRequest += new EventHandler (invoker.Invoke);
804 internal event EventHandler DefaultAuthentication;
806 void AddEventHandler (object key, EventHandler handler)
808 if (fullInitComplete)
811 Events.AddHandler (key, handler);
814 void RemoveEventHandler (object key, EventHandler handler)
816 if (fullInitComplete)
819 Events.RemoveHandler (key, handler);
823 // Bypass all the event on the Http pipeline and go directly to EndRequest
825 public void CompleteRequest ()
827 stop_processing = true;
830 internal bool RequestCompleted {
831 set { stop_processing = value; }
834 internal void DisposeInternal ()
837 HttpModuleCollection coll = new HttpModuleCollection ();
838 Interlocked.Exchange (ref modcoll, coll);
840 for (int i = coll.Count - 1; i >= 0; i--) {
841 coll.Get (i).Dispose ();
846 EventHandler eh = nonApplicationEvents [disposedEvent] as EventHandler;
848 eh (this, EventArgs.Empty);
854 public virtual void Dispose ()
858 public virtual string GetOutputCacheProviderName (HttpContext context)
860 // LAMESPEC: doesn't throw ProviderException if context is null
861 return OutputCache.DefaultProviderName;
864 public virtual string GetVaryByCustomString (HttpContext context, string custom)
866 if (custom == null) // Sigh
867 throw new NullReferenceException ();
869 if (0 == String.Compare (custom, "browser", true, Helpers.InvariantCulture))
870 return context.Request.Browser.Type;
875 bool ShouldHandleException (Exception e)
877 if (e is ParseException)
884 // If we catch an error, queue this error
886 internal void ProcessError (Exception e)
888 bool first = context.Error == null;
889 context.AddError (e);
890 if (first && ShouldHandleException (e)) {
891 EventHandler eh = nonApplicationEvents [errorEvent] as EventHandler;
894 eh (this, EventArgs.Empty);
896 context.ClearError ();
897 } catch (ThreadAbortException taex){
898 context.ClearError ();
899 if (FlagEnd.Value == taex.ExceptionState || HttpRuntime.DomainUnloading)
900 // This happens on Redirect(), End() and
901 // when unloading the AppDomain
902 Thread.ResetAbort ();
904 // This happens on Thread.Abort()
905 context.AddError (taex);
906 } catch (Exception ee){
907 context.AddError (ee);
911 stop_processing = true;
913 // we want to remove configuration from the cache in case of
914 // invalid resource not exists to prevent DOS attack.
915 HttpException httpEx = e as HttpException;
916 if (httpEx != null && httpEx.GetHttpCode () == 404) {
917 removeConfigurationFromCache = true;
922 // Ticks the clock: next step on the pipeline.
924 internal void Tick ()
927 if (pipeline.MoveNext ()){
928 if ((bool)pipeline.Current)
931 } catch (ThreadAbortException taex) {
932 object obj = taex.ExceptionState;
933 Thread.ResetAbort ();
934 if (obj is StepTimeout)
935 ProcessError (HttpException.NewWithCode ("The request timed out.", WebEventCodes.RequestTransactionAbort));
937 context.ClearError ();
938 if (FlagEnd.Value != obj && !HttpRuntime.DomainUnloading)
939 context.AddError (taex);
942 stop_processing = true;
944 } catch (Exception e) {
945 ThreadAbortException inner = e.InnerException as ThreadAbortException;
946 if (inner != null && FlagEnd.Value == inner.ExceptionState && !HttpRuntime.DomainUnloading) {
947 context.ClearError ();
948 Thread.ResetAbort ();
952 stop_processing = true;
966 // Invoked when our async callback called from RunHooks completes,
967 // we restart the pipeline here.
969 void async_callback_completed_cb (IAsyncResult ar)
971 if (current_ai.end != null){
974 } catch (Exception e) {
982 void async_handler_complete_cb (IAsyncResult ar)
984 IHttpAsyncHandler async_handler = ar != null ? ar.AsyncState as IHttpAsyncHandler : null;
987 if (async_handler != null)
988 async_handler.EndProcessRequest (ar);
989 } catch (Exception e){
997 // This enumerator yields whether processing must be stopped:
998 // true: processing of the pipeline must be stopped
999 // false: processing of the pipeline must not be stopped
1001 IEnumerable RunHooks (Delegate list)
1003 Delegate [] delegates = list.GetInvocationList ();
1005 foreach (EventHandler d in delegates){
1006 if (d.Target != null && (d.Target is AsyncInvoker)){
1007 current_ai = (AsyncInvoker) d.Target;
1012 context.BeginTimeoutPossible ();
1013 current_ai.begin (this, EventArgs.Empty, async_callback_completed_cb, current_ai.data);
1016 context.EndTimeoutPossible ();
1020 // If things are still moving forward, yield this
1024 yield return stop_processing;
1025 else if (stop_processing)
1029 context.BeginTimeoutPossible ();
1030 d (this, EventArgs.Empty);
1032 context.EndTimeoutPossible ();
1034 if (stop_processing)
1040 static void FinalErrorWrite (HttpResponse response, string error)
1043 response.Write (error);
1044 response.Flush (true);
1052 if (context.Error == null){
1054 context.Response.Flush (true);
1055 } catch (Exception e){
1056 context.AddError (e);
1060 Exception error = context.Error;
1062 HttpResponse response = context.Response;
1064 if (!response.HeadersSent){
1065 response.ClearHeaders ();
1066 response.ClearContent ();
1068 if (error is HttpException){
1069 response.StatusCode = ((HttpException)error).GetHttpCode ();
1071 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1072 response.StatusCode = 500;
1074 HttpException httpEx = (HttpException) error;
1075 if (!RedirectCustomError (ref httpEx))
1076 FinalErrorWrite (response, httpEx.GetHtmlErrorMessage ());
1078 response.Flush (true);
1080 if (!(error is HttpException))
1081 error = HttpException.NewWithCode (String.Empty, error, WebEventCodes.WebErrorOtherError);
1082 FinalErrorWrite (response, ((HttpException) error).GetHtmlErrorMessage ());
1089 // Invoked at the end of the pipeline execution
1091 void PipelineDone ()
1094 EventHandler handler = Events [EndRequestEvent] as EventHandler;
1095 if (handler != null)
1096 handler (this, EventArgs.Empty);
1097 } catch (Exception e){
1103 } catch (ThreadAbortException taex) {
1104 ProcessError (taex);
1105 Thread.ResetAbort ();
1106 } catch (Exception e) {
1107 Console.WriteLine ("Internal error: OutputPage threw an exception " + e);
1109 context.WorkerRequest.EndOfRequest();
1110 if (factory != null && context.Handler != null){
1111 factory.ReleaseHandler (context.Handler);
1112 context.Handler = null;
1115 context.PopHandler ();
1117 // context = null; -> moved to PostDone
1123 if (begin_iar != null)
1124 begin_iar.Complete ();
1128 requests_total_counter.Increment ();
1138 public Tim (string name) {
1142 public string Name {
1143 get { return name; }
1144 set { name = value; }
1147 public void Start () {
1148 start = DateTime.UtcNow;
1151 public void Stop () {
1152 Console.WriteLine ("{0}: {1}ms", name, (DateTime.UtcNow - start).TotalMilliseconds);
1157 [Conditional ("PIPELINE_TIMER")]
1158 void StartTimer (string name)
1166 [Conditional ("PIPELINE_TIMER")]
1173 // Events fired as described in `Http Runtime Support, HttpModules,
1174 // Handling Public Events'
1176 IEnumerator Pipeline ()
1178 Delegate eventHandler;
1179 if (stop_processing)
1181 HttpRequest req = context.Request;
1184 context.MapRequestHandlerDone = false;
1185 StartTimer ("BeginRequest");
1186 eventHandler = Events [BeginRequestEvent];
1187 if (eventHandler != null) {
1188 foreach (bool stop in RunHooks (eventHandler))
1193 StartTimer ("AuthenticateRequest");
1194 eventHandler = Events [AuthenticateRequestEvent];
1195 if (eventHandler != null)
1196 foreach (bool stop in RunHooks (eventHandler))
1200 StartTimer ("DefaultAuthentication");
1201 if (DefaultAuthentication != null)
1202 foreach (bool stop in RunHooks (DefaultAuthentication))
1206 StartTimer ("PostAuthenticateRequest");
1207 eventHandler = Events [PostAuthenticateRequestEvent];
1208 if (eventHandler != null)
1209 foreach (bool stop in RunHooks (eventHandler))
1213 StartTimer ("AuthorizeRequest");
1214 eventHandler = Events [AuthorizeRequestEvent];
1215 if (eventHandler != null)
1216 foreach (bool stop in RunHooks (eventHandler))
1220 StartTimer ("PostAuthorizeRequest");
1221 eventHandler = Events [PostAuthorizeRequestEvent];
1222 if (eventHandler != null)
1223 foreach (bool stop in RunHooks (eventHandler))
1227 StartTimer ("ResolveRequestCache");
1228 eventHandler = Events [ResolveRequestCacheEvent];
1229 if (eventHandler != null)
1230 foreach (bool stop in RunHooks (eventHandler))
1234 StartTimer ("PostResolveRequestCache");
1235 eventHandler = Events [PostResolveRequestCacheEvent];
1236 if (eventHandler != null)
1237 foreach (bool stop in RunHooks (eventHandler))
1241 StartTimer ("MapRequestHandler");
1242 // As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
1243 eventHandler = Events [MapRequestHandlerEvent];
1244 if (eventHandler != null)
1245 foreach (bool stop in RunHooks (eventHandler))
1248 context.MapRequestHandlerDone = true;
1250 StartTimer ("GetHandler");
1251 // Obtain the handler for the request.
1252 IHttpHandler handler = null;
1254 handler = GetHandler (context, context.Request.CurrentExecutionFilePath);
1255 context.Handler = handler;
1256 context.PushHandler (handler);
1257 } catch (FileNotFoundException fnf){
1258 if (context.Request.IsLocal)
1259 ProcessError (HttpException.NewWithCode (404,
1260 String.Format ("File not found {0}", fnf.FileName),
1262 context.Request.FilePath,
1263 WebEventCodes.RuntimeErrorRequestAbort));
1265 ProcessError (HttpException.NewWithCode (404,
1266 "File not found: " + Path.GetFileName (fnf.FileName),
1267 context.Request.FilePath,
1268 WebEventCodes.RuntimeErrorRequestAbort));
1269 } catch (DirectoryNotFoundException dnf){
1270 if (!context.Request.IsLocal)
1271 dnf = null; // Do not "leak" real path information
1272 ProcessError (HttpException.NewWithCode (404, "Directory not found", dnf, WebEventCodes.RuntimeErrorRequestAbort));
1273 } catch (Exception e) {
1278 if (stop_processing)
1281 StartTimer ("PostMapRequestHandler");
1282 eventHandler = Events [PostMapRequestHandlerEvent];
1283 if (eventHandler != null)
1284 foreach (bool stop in RunHooks (eventHandler))
1288 StartTimer ("AcquireRequestState");
1289 eventHandler = Events [AcquireRequestStateEvent];
1290 if (eventHandler != null){
1291 foreach (bool stop in RunHooks (eventHandler))
1296 StartTimer ("PostAcquireRequestState");
1297 eventHandler = Events [PostAcquireRequestStateEvent];
1298 if (eventHandler != null){
1299 foreach (bool stop in RunHooks (eventHandler))
1305 // From this point on, we need to ensure that we call
1306 // ReleaseRequestState, so the code below jumps to
1307 // `release:' to guarantee it rather than yielding.
1309 StartTimer ("PreRequestHandlerExecute");
1310 eventHandler = Events [PreRequestHandlerExecuteEvent];
1311 if (eventHandler != null)
1312 foreach (bool stop in RunHooks (eventHandler))
1319 IHttpHandler ctxHandler = context.Handler;
1320 if (ctxHandler != null && handler != ctxHandler) {
1321 context.PopHandler ();
1322 handler = ctxHandler;
1323 context.PushHandler (handler);
1326 StartTimer ("ProcessRequest");
1328 context.BeginTimeoutPossible ();
1329 if (handler != null){
1330 IHttpAsyncHandler async_handler = handler as IHttpAsyncHandler;
1332 if (async_handler != null){
1335 async_handler.BeginProcessRequest (context, async_handler_complete_cb, handler);
1338 handler.ProcessRequest (context);
1341 throw new InvalidOperationException ("No handler for the current request.");
1342 if (context.Error != null)
1343 throw new TargetInvocationException(context.Error);
1346 context.EndTimeoutPossible ();
1350 yield return stop_processing;
1351 else if (stop_processing)
1354 // These are executed after the application has returned
1356 StartTimer ("PostRequestHandlerExecute");
1357 eventHandler = Events [PostRequestHandlerExecuteEvent];
1358 if (eventHandler != null)
1359 foreach (bool stop in RunHooks (eventHandler))
1365 StartTimer ("ReleaseRequestState");
1366 eventHandler = Events [ReleaseRequestStateEvent];
1367 if (eventHandler != null){
1368 #pragma warning disable 219
1369 foreach (bool stop in RunHooks (eventHandler)) {
1371 // Ignore the stop signal while release the state
1375 #pragma warning restore 219
1379 if (stop_processing)
1382 StartTimer ("PostReleaseRequestState");
1383 eventHandler = Events [PostReleaseRequestStateEvent];
1384 if (eventHandler != null)
1385 foreach (bool stop in RunHooks (eventHandler))
1389 StartTimer ("Filter");
1390 if (context.Error == null)
1391 context.Response.DoFilter (true);
1394 StartTimer ("UpdateRequestCache");
1395 eventHandler = Events [UpdateRequestCacheEvent];
1396 if (eventHandler != null)
1397 foreach (bool stop in RunHooks (eventHandler))
1401 StartTimer ("PostUpdateRequestCache");
1402 eventHandler = Events [PostUpdateRequestCacheEvent];
1403 if (eventHandler != null)
1404 foreach (bool stop in RunHooks (eventHandler))
1408 StartTimer ("LogRequest");
1409 eventHandler = Events [LogRequestEvent];
1410 if (eventHandler != null)
1411 foreach (bool stop in RunHooks (eventHandler))
1415 StartTimer ("PostLogRequest");
1416 eventHandler = Events [PostLogRequestEvent];
1417 if (eventHandler != null)
1418 foreach (bool stop in RunHooks (eventHandler))
1422 StartTimer ("PipelineDone");
1428 internal CultureInfo GetThreadCulture (HttpRequest request, CultureInfo culture, bool isAuto)
1432 CultureInfo ret = null;
1433 string[] languages = request.UserLanguages;
1435 if (languages != null && languages.Length > 0)
1436 ret = CultureInfo.CreateSpecificCulture (languages[0]);
1449 GlobalizationSection cfg;
1450 cfg = (GlobalizationSection) WebConfigurationManager.GetSection ("system.web/globalization");
1451 app_culture = cfg.GetCulture ();
1452 autoCulture = cfg.IsAutoCulture;
1453 appui_culture = cfg.GetUICulture ();
1454 autoUICulture = cfg.IsAutoUICulture;
1455 context.StartTimeoutTimer ();
1456 Thread th = Thread.CurrentThread;
1457 if (app_culture != null) {
1458 prev_app_culture = th.CurrentCulture;
1459 CultureInfo new_app_culture = GetThreadCulture (Request, app_culture, autoCulture);
1460 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1461 th.CurrentCulture = new_app_culture;
1464 if (appui_culture != null) {
1465 prev_appui_culture = th.CurrentUICulture;
1466 CultureInfo new_app_culture = GetThreadCulture (Request, appui_culture, autoUICulture);
1467 if (!new_app_culture.Equals (Helpers.InvariantCulture))
1468 th.CurrentUICulture = new_app_culture;
1471 prev_user = Thread.CurrentPrincipal;
1476 if (removeConfigurationFromCache) {
1477 WebConfigurationManager.RemoveConfigurationFromCache (context);
1478 removeConfigurationFromCache = false;
1481 Thread th = Thread.CurrentThread;
1482 if (Thread.CurrentPrincipal != prev_user)
1483 Thread.CurrentPrincipal = prev_user;
1484 if (prev_appui_culture != null && prev_appui_culture != th.CurrentUICulture)
1485 th.CurrentUICulture = prev_appui_culture;
1486 if (prev_app_culture != null && prev_app_culture != th.CurrentCulture)
1487 th.CurrentCulture = prev_app_culture;
1489 if (context == null)
1490 context = HttpContext.Current;
1491 context.StopTimeoutTimer ();
1492 context.Request.ReleaseResources ();
1493 context.Response.ReleaseResources ();
1496 HttpContext.Current = null;
1499 void Start (object x)
1501 var cultures = x as CultureInfo [];
1502 if (cultures != null && cultures.Length == 2) {
1503 Thread ct = Thread.CurrentThread;
1504 ct.CurrentCulture = cultures [0];
1505 ct.CurrentUICulture = cultures [1];
1509 if (initialization_exception != null) {
1510 Exception e = initialization_exception;
1511 HttpException exc = HttpException.NewWithCode (String.Empty, e, WebEventCodes.RuntimeErrorRequestAbort);
1512 context.Response.StatusCode = 500;
1513 FinalErrorWrite (context.Response, exc.GetHtmlErrorMessage ());
1518 HttpContext.Current = Context;
1520 pipeline = Pipeline ();
1524 const string HANDLER_CACHE = "@@HttpHandlerCache@@";
1526 internal static Hashtable GetHandlerCache ()
1528 Cache cache = HttpRuntime.InternalCache;
1529 Hashtable ret = cache [HANDLER_CACHE] as Hashtable;
1532 ret = new Hashtable ();
1533 cache.Insert (HANDLER_CACHE, ret);
1539 internal static void ClearHandlerCache ()
1541 Hashtable cache = GetHandlerCache ();
1545 object LocateHandler (HttpRequest req, string verb, string url)
1547 Hashtable cache = GetHandlerCache ();
1548 string id = String.Concat (verb, url);
1549 object ret = cache [id];
1555 HttpHandlersSection httpHandlersSection = WebConfigurationManager.GetSection ("system.web/httpHandlers", req.Path, req.Context) as HttpHandlersSection;
1556 ret = httpHandlersSection.LocateHandler (verb, url, out allowCache);
1558 IHttpHandler handler = ret as IHttpHandler;
1559 if (allowCache && handler != null && handler.IsReusable)
1565 internal IHttpHandler GetHandler (HttpContext context, string url)
1567 return GetHandler (context, url, false);
1570 // Used by HttpServerUtility.Execute
1571 internal IHttpHandler GetHandler (HttpContext context, string url, bool ignoreContextHandler)
1573 if (!ignoreContextHandler && context.Handler != null)
1574 return context.Handler;
1576 HttpRequest request = context.Request;
1577 string verb = request.RequestType;
1579 IHttpHandler handler = null;
1580 object o = LocateHandler (request, verb, url);
1582 factory = o as IHttpHandlerFactory;
1583 if (factory == null) {
1584 handler = (IHttpHandler) o;
1586 handler = factory.GetHandler (context, verb, url, request.MapPath (url));
1592 void IHttpHandler.ProcessRequest (HttpContext context)
1595 this.context = context;
1603 // This is used by FireOnAppStart, when we init the application
1604 // as the context is required to be set at that point (the user
1605 // might call methods that require it on that hook).
1607 internal void SetContext (HttpContext context)
1609 this.context = context;
1612 internal void SetSession (HttpSessionState session)
1614 this.session = session;
1617 IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
1619 this.context = context;
1622 begin_iar = new AsyncRequestState (done, cb, extraData);
1624 CultureInfo[] cultures = new CultureInfo [2];
1625 cultures [0] = Thread.CurrentThread.CurrentCulture;
1626 cultures [1] = Thread.CurrentThread.CurrentUICulture;
1628 if (Thread.CurrentThread.IsThreadPoolThread)
1631 ThreadPool.QueueUserWorkItem (x => {
1634 } catch (Exception e) {
1635 Console.Error.WriteLine (e);
1642 void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
1644 if (!result.IsCompleted)
1645 result.AsyncWaitHandle.WaitOne ();
1649 public virtual void Init ()
1653 bool IHttpHandler.IsReusable {
1659 public static void RegisterModule (Type moduleType)
1661 HttpRuntimeSection config = (HttpRuntimeSection)WebConfigurationManager.GetSection ("system.web/httpRuntime");
1663 if (!config.AllowDynamicModuleRegistration)
1664 throw new InvalidOperationException ("The Application has requested to register a dynamic Module, but dynamic module registration is disabled in web.config.");
1666 dynamicModuleManeger.Add (moduleType);
1670 HttpModuleCollection CreateDynamicModules ()
1672 HttpModuleCollection modules = new HttpModuleCollection ();
1674 foreach (var module in dynamicModuleManeger.LockAndGetModules ()) {
1675 IHttpModule httpModule = CreateModuleInstance (module.Type);
1676 httpModule.Init (this);
1677 modules.AddModule (module.Name, httpModule);
1682 IHttpModule CreateModuleInstance (Type type)
1684 return (IHttpModule) Activator.CreateInstance (type,
1685 BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.CreateInstance,
1692 internal void ClearError ()
1694 context.ClearError ();
1697 bool RedirectErrorPage (string error_page)
1699 if (context.Request.QueryString ["aspxerrorpath"] != null)
1702 Response.Redirect (error_page + "?aspxerrorpath=" + Request.Path, false);
1706 bool RedirectCustomError (ref HttpException httpEx)
1709 if (!context.IsCustomErrorEnabledUnsafe)
1712 CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");
1713 if (config == null) {
1714 if (context.ErrorPage != null)
1715 return RedirectErrorPage (context.ErrorPage);
1720 CustomError err = config.Errors [context.Response.StatusCode.ToString()];
1721 string redirect = err == null ? null : err.Redirect;
1722 if (redirect == null) {
1723 redirect = context.ErrorPage;
1724 if (redirect == null)
1725 redirect = config.DefaultRedirect;
1728 if (redirect == null)
1731 if (config.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite) {
1732 context.Server.Execute (redirect);
1736 return RedirectErrorPage (redirect);
1738 catch (Exception ex) {
1739 httpEx = HttpException.NewWithCode (500, String.Empty, ex, WebEventCodes.WebErrorOtherError);
1744 internal static string BinDirectory
1747 if (binDirectory == null) {
1748 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
1749 string baseDir = setup.ApplicationBase;
1752 foreach (string dir in BinDirs) {
1753 bindir = Path.Combine (baseDir, dir);
1754 if (!Directory.Exists (bindir))
1756 binDirectory = bindir;
1761 return binDirectory;
1765 internal static string[] BinDirectoryAssemblies
1768 ArrayList binDlls = null;
1771 string bindir = BinDirectory;
1772 if (bindir != null) {
1773 binDlls = new ArrayList ();
1774 dlls = Directory.GetFiles (bindir, "*.dll");
1775 binDlls.AddRange (dlls);
1778 if (binDlls == null)
1779 return new string[] {};
1781 return (string[]) binDlls.ToArray (typeof (string));
1785 internal static Type LoadType (string typeName)
1787 return LoadType (typeName, false);
1790 internal static Type LoadType (string typeName, bool throwOnMissing)
1792 Type type = Type.GetType (typeName);
1796 Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
1797 foreach (Assembly ass in assemblies) {
1798 type = ass.GetType (typeName, false);
1803 IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
1804 if (tla != null && tla.Count > 0) {
1805 foreach (Assembly asm in tla) {
1808 type = asm.GetType (typeName, false);
1814 Exception loadException = null;
1817 type = LoadTypeFromBin (typeName);
1818 } catch (Exception ex) {
1825 throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName), loadException);
1830 internal static Type LoadType <TBaseType> (string typeName, bool throwOnMissing)
1832 Type ret = LoadType (typeName, throwOnMissing);
1834 if (typeof (TBaseType).IsAssignableFrom (ret))
1838 throw new TypeLoadException (String.Format ("Type '{0}' found but it doesn't derive from base type '{1}'.", typeName, typeof (TBaseType)));
1843 internal static Type LoadTypeFromBin (string typeName)
1847 foreach (string s in BinDirectoryAssemblies) {
1848 Assembly binA = null;
1851 binA = Assembly.LoadFrom (s);
1852 } catch (FileLoadException) {
1855 } catch (BadImageFormatException) {
1860 type = binA.GetType (typeName, false);
1872 // Based on Fritz' Onion's AsyncRequestState class for asynchronous IHttpAsyncHandlers
1874 class AsyncRequestState : IAsyncResult {
1878 ManualResetEvent complete_event = null;
1880 internal AsyncRequestState (ManualResetEvent complete_event, AsyncCallback cb, object cb_data)
1883 this.cb_data = cb_data;
1884 this.complete_event = complete_event;
1887 internal void Complete ()
1892 // TODO: if this throws an error, we have no way of reporting it
1893 // Not really too bad, since the only failure might be
1894 // `HttpRuntime.request_processed'.
1901 complete_event.Set ();
1904 public object AsyncState {
1910 public bool CompletedSynchronously {
1916 public bool IsCompleted {
1922 public WaitHandle AsyncWaitHandle {
1924 return complete_event;
1929 #region Helper classes
1932 // A wrapper to keep track of begin/end pairs
1934 class AsyncInvoker {
1935 public BeginEventHandler begin;
1936 public EndEventHandler end;
1938 HttpApplication app;
1939 AsyncCallback callback;
1941 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, HttpApplication a, object d)
1947 callback = new AsyncCallback (doAsyncCallback);
1950 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, HttpApplication app) : this(bh, eh, app, null) { }
1952 public void Invoke (object sender, EventArgs e)
1955 res = begin (app, e, callback, data);
1958 void doAsyncCallback (IAsyncResult res)
1960 ThreadPool.QueueUserWorkItem ((object ores) => {
1961 IAsyncResult tres = (IAsyncResult) ores;
1964 } catch (Exception ee) {
1965 // I tried using ProcessError(), but we only come here frome an Invokation in PipelineDone().
1966 // Using ProcessError, I still get a blank screen, this way, we at least log the error to console...
1967 Console.Error.WriteLine (ee.ToString ());