2 // System.Web.HttpApplication.cs
5 // Miguel de Icaza (miguel@novell.com)
6 // Gonzalo Paniagua (gonzalo@ximian.com)
9 // Copyright (C) 2005 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.Configuration;
77 using System.Web.SessionState;
84 namespace System.Web {
87 [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
88 [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
91 public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
93 static readonly object disposedEvent = new object ();
94 static readonly object errorEvent = new object ();
96 // we do this static rather than per HttpApplication because
97 // mono's perfcounters use the counter instance parameter for
98 // the process to access shared memory.
99 internal static PerformanceCounter requests_total_counter = new PerformanceCounter ("ASP.NET", "Requests Total");
101 internal static readonly string [] BinDirs = {"Bin", "bin"};
102 object this_lock = new object();
105 HttpSessionState session;
108 // The source, and the exposed API (cache).
109 HttpModuleCollection modcoll;
111 string assemblyLocation;
114 // The factory for the handler currently running.
116 IHttpHandlerFactory factory;
119 // Whether the thread culture is to be auto-set.
120 // Used only in the 2.0 profile, always false for 1.x
126 // Whether the pipeline should be stopped
128 bool stop_processing;
131 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
133 bool in_application_start;
138 IEnumerator pipeline;
140 // To flag when we are done processing a request from BeginProcessRequest.
141 ManualResetEvent done;
143 // The current IAsyncResult for the running async request handler in the pipeline
144 AsyncRequestState begin_iar;
146 // Tracks the current AsyncInvocation being dispatched
147 AsyncInvoker current_ai;
149 EventHandlerList events;
150 EventHandlerList nonApplicationEvents = new EventHandlerList ();
152 // Culture and IPrincipal
153 CultureInfo app_culture;
154 CultureInfo appui_culture;
155 CultureInfo prev_app_culture;
156 CultureInfo prev_appui_culture;
157 IPrincipal prev_user;
159 static string binDirectory;
163 const string initialization_exception_key = "System.Web.HttpApplication.initialization_exception";
164 static Exception initialization_exception {
165 get { return (Exception) AppDomain.CurrentDomain.GetData (initialization_exception_key); }
166 set { AppDomain.CurrentDomain.SetData (initialization_exception_key, value); }
169 static Exception initialization_exception;
171 bool removeConfigurationFromCache;
173 bool fullInitComplete = false;
176 // These are used to detect the case where the EndXXX method is invoked
177 // from within the BeginXXXX delegate, so we detect whether we kick the
178 // pipeline from here, or from the the RunHook routine
183 public virtual event EventHandler Disposed {
184 add { nonApplicationEvents.AddHandler (disposedEvent, value); }
185 remove { nonApplicationEvents.RemoveHandler (disposedEvent, value); }
188 public virtual event EventHandler Error {
189 add { nonApplicationEvents.AddHandler (errorEvent, value); }
190 remove { nonApplicationEvents.RemoveHandler (errorEvent, value); }
193 public HttpApplication ()
195 done = new ManualResetEvent (false);
198 internal void InitOnce (bool full_init)
205 HttpModulesSection modules;
206 modules = (HttpModulesSection) WebConfigurationManager.GetWebApplicationSection ("system.web/httpModules");
208 ModulesConfiguration modules;
210 modules = (ModulesConfiguration) HttpContext.GetAppConfig ("system.web/httpModules");
213 HttpContext saved = HttpContext.Current;
214 HttpContext.Current = new HttpContext (new System.Web.Hosting.SimpleWorkerRequest ("", "", new StringWriter()));
215 modcoll = modules.LoadModules (this);
216 HttpContext.Current = saved;
219 HttpApplicationFactory.AttachEvents (this);
221 fullInitComplete = true;
226 internal bool InApplicationStart {
227 get { return in_application_start; }
228 set { in_application_start = value; }
231 internal string AssemblyLocation {
233 if (assemblyLocation == null)
234 assemblyLocation = GetType ().Assembly.Location;
235 return assemblyLocation;
240 internal static Exception InitializationException {
241 get { return initialization_exception; }
246 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
247 public HttpApplicationState Application {
249 return HttpApplicationFactory.ApplicationState;
254 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
255 public HttpContext Context {
261 protected EventHandlerList Events {
264 events = new EventHandlerList ();
271 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
272 public HttpModuleCollection Modules {
273 [AspNetHostingPermission (SecurityAction.Demand, Level = AspNetHostingPermissionLevel.High)]
277 modcoll = new HttpModuleCollection ();
285 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
286 public HttpRequest Request {
289 throw new HttpException (Locale.GetText ("No context is available."));
291 if (false == HttpApplicationFactory.ContextAvailable)
292 throw new HttpException (Locale.GetText ("Request is not available in this context."));
294 return context.Request;
299 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
300 public HttpResponse Response {
303 throw new HttpException (Locale.GetText ("No context is available."));
305 if (false == HttpApplicationFactory.ContextAvailable)
306 throw new HttpException (Locale.GetText ("Response is not available in this context."));
308 return context.Response;
313 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
314 public HttpServerUtility Server {
317 return context.Server;
320 // This is so we can get the Server and call a few methods
321 // which are not context sensitive, see HttpServerUtilityTest
323 return new HttpServerUtility ((HttpContext) null);
328 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
329 public HttpSessionState Session {
331 // Only used for Session_End
336 throw new HttpException (Locale.GetText ("No context is available."));
338 HttpSessionState ret = context.Session;
340 throw new HttpException (Locale.GetText ("Session state is not available in the context."));
347 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
351 public virtual ISite Site {
363 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
364 public IPrincipal User {
367 throw new HttpException (Locale.GetText ("No context is available."));
368 if (context.User == null)
369 throw new HttpException (Locale.GetText ("No currently authenticated user."));
375 static object PreSendRequestHeadersEvent = new object ();
376 public event EventHandler PreSendRequestHeaders
378 add { AddEventHandler (PreSendRequestHeadersEvent, value); }
379 remove { RemoveEventHandler (PreSendRequestHeadersEvent, value); }
382 internal void TriggerPreSendRequestHeaders ()
384 EventHandler handler = Events [PreSendRequestHeadersEvent] as EventHandler;
386 handler (this, EventArgs.Empty);
389 static object PreSendRequestContentEvent = new object ();
390 public event EventHandler PreSendRequestContent
392 add { AddEventHandler (PreSendRequestContentEvent, value); }
393 remove { RemoveEventHandler (PreSendRequestContentEvent, value); }
396 internal void TriggerPreSendRequestContent ()
398 EventHandler handler = Events [PreSendRequestContentEvent] as EventHandler;
400 handler (this, EventArgs.Empty);
403 static object AcquireRequestStateEvent = new object ();
404 public event EventHandler AcquireRequestState
406 add { AddEventHandler (AcquireRequestStateEvent, value); }
407 remove { RemoveEventHandler (AcquireRequestStateEvent, value); }
410 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
412 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
413 AcquireRequestState += new EventHandler (invoker.Invoke);
416 static object AuthenticateRequestEvent = new object ();
417 public event EventHandler AuthenticateRequest
419 add { AddEventHandler (AuthenticateRequestEvent, value); }
420 remove { RemoveEventHandler (AuthenticateRequestEvent, value); }
423 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
425 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
426 AuthenticateRequest += new EventHandler (invoker.Invoke);
429 static object AuthorizeRequestEvent = new object ();
430 public event EventHandler AuthorizeRequest
432 add { AddEventHandler (AuthorizeRequestEvent, value); }
433 remove { RemoveEventHandler (AuthorizeRequestEvent, value); }
436 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
438 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
439 AuthorizeRequest += new EventHandler (invoker.Invoke);
442 static object BeginRequestEvent = new object ();
443 public event EventHandler BeginRequest
446 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
447 if (InApplicationStart)
449 AddEventHandler (BeginRequestEvent, value);
452 if (InApplicationStart)
454 RemoveEventHandler (BeginRequestEvent, value);
458 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh)
460 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
461 BeginRequest += new EventHandler (invoker.Invoke);
464 static object EndRequestEvent = new object ();
465 public event EventHandler EndRequest
468 // See https://bugzilla.novell.com/show_bug.cgi?id=381971
469 if (InApplicationStart)
471 AddEventHandler (EndRequestEvent, value);
474 if (InApplicationStart)
476 RemoveEventHandler (EndRequestEvent, value);
480 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh)
482 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
483 EndRequest += new EventHandler (invoker.Invoke);
486 static object PostRequestHandlerExecuteEvent = new object ();
487 public event EventHandler PostRequestHandlerExecute
489 add { AddEventHandler (PostRequestHandlerExecuteEvent, value); }
490 remove { RemoveEventHandler (PostRequestHandlerExecuteEvent, value); }
493 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
495 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
496 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
499 static object PreRequestHandlerExecuteEvent = new object ();
500 public event EventHandler PreRequestHandlerExecute
502 add { AddEventHandler (PreRequestHandlerExecuteEvent, value); }
503 remove { RemoveEventHandler (PreRequestHandlerExecuteEvent, value); }
506 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh)
508 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
509 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
512 static object ReleaseRequestStateEvent = new object ();
513 public event EventHandler ReleaseRequestState
515 add { AddEventHandler (ReleaseRequestStateEvent, value); }
516 remove { RemoveEventHandler (ReleaseRequestStateEvent, value); }
519 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
521 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
522 ReleaseRequestState += new EventHandler (invoker.Invoke);
525 static object ResolveRequestCacheEvent = new object ();
526 public event EventHandler ResolveRequestCache
528 add { AddEventHandler (ResolveRequestCacheEvent, value); }
529 remove { RemoveEventHandler (ResolveRequestCacheEvent, value); }
532 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
534 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
535 ResolveRequestCache += new EventHandler (invoker.Invoke);
538 static object UpdateRequestCacheEvent = new object ();
539 public event EventHandler UpdateRequestCache
541 add { AddEventHandler (UpdateRequestCacheEvent, value); }
542 remove { RemoveEventHandler (UpdateRequestCacheEvent, value); }
545 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
547 AsyncInvoker invoker = new AsyncInvoker (bh, eh);
548 UpdateRequestCache += new EventHandler (invoker.Invoke);
552 static object PostAuthenticateRequestEvent = new object ();
553 public event EventHandler PostAuthenticateRequest
555 add { AddEventHandler (PostAuthenticateRequestEvent, value); }
556 remove { RemoveEventHandler (PostAuthenticateRequestEvent, value); }
559 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh)
561 AddOnPostAuthenticateRequestAsync (bh, eh, null);
564 public void AddOnPostAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
566 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
567 PostAuthenticateRequest += new EventHandler (invoker.Invoke);
570 static object PostAuthorizeRequestEvent = new object ();
571 public event EventHandler PostAuthorizeRequest
573 add { AddEventHandler (PostAuthorizeRequestEvent, value); }
574 remove { RemoveEventHandler (PostAuthorizeRequestEvent, value); }
577 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh)
579 AddOnPostAuthorizeRequestAsync (bh, eh, null);
582 public void AddOnPostAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
584 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
585 PostAuthorizeRequest += new EventHandler (invoker.Invoke);
588 static object PostResolveRequestCacheEvent = new object ();
589 public event EventHandler PostResolveRequestCache
591 add { AddEventHandler (PostResolveRequestCacheEvent, value); }
592 remove { RemoveEventHandler (PostResolveRequestCacheEvent, value); }
595 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
597 AddOnPostResolveRequestCacheAsync (bh, eh, null);
600 public void AddOnPostResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
602 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
603 PostResolveRequestCache += new EventHandler (invoker.Invoke);
606 static object PostMapRequestHandlerEvent = new object ();
607 public event EventHandler PostMapRequestHandler
609 add { AddEventHandler (PostMapRequestHandlerEvent, value); }
610 remove { RemoveEventHandler (PostMapRequestHandlerEvent, value); }
613 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
615 AddOnPostMapRequestHandlerAsync (bh, eh, null);
618 public void AddOnPostMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh, object data)
620 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
621 PostMapRequestHandler += new EventHandler (invoker.Invoke);
624 static object PostAcquireRequestStateEvent = new object ();
625 public event EventHandler PostAcquireRequestState
627 add { AddEventHandler (PostAcquireRequestStateEvent, value); }
628 remove { RemoveEventHandler (PostAcquireRequestStateEvent, value); }
631 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
633 AddOnPostAcquireRequestStateAsync (bh, eh, null);
636 public void AddOnPostAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
638 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
639 PostAcquireRequestState += new EventHandler (invoker.Invoke);
642 static object PostReleaseRequestStateEvent = new object ();
643 public event EventHandler PostReleaseRequestState
645 add { AddEventHandler (PostReleaseRequestStateEvent, value); }
646 remove { RemoveEventHandler (PostReleaseRequestStateEvent, value); }
649 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh)
651 AddOnPostReleaseRequestStateAsync (bh, eh, null);
654 public void AddOnPostReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
656 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
657 PostReleaseRequestState += new EventHandler (invoker.Invoke);
660 static object PostUpdateRequestCacheEvent = new object ();
661 public event EventHandler PostUpdateRequestCache
663 add { AddEventHandler (PostUpdateRequestCacheEvent, value); }
664 remove { RemoveEventHandler (PostUpdateRequestCacheEvent, value); }
667 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh)
669 AddOnPostUpdateRequestCacheAsync (bh, eh, null);
672 public void AddOnPostUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
674 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
675 PostUpdateRequestCache += new EventHandler (invoker.Invoke);
679 // The new overloads that take a data parameter
681 public void AddOnAcquireRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
683 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
684 AcquireRequestState += new EventHandler (invoker.Invoke);
687 public void AddOnAuthenticateRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
689 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
690 AuthenticateRequest += new EventHandler (invoker.Invoke);
693 public void AddOnAuthorizeRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
695 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
696 AuthorizeRequest += new EventHandler (invoker.Invoke);
699 public void AddOnBeginRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
701 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
702 BeginRequest += new EventHandler (invoker.Invoke);
705 public void AddOnEndRequestAsync (BeginEventHandler bh, EndEventHandler eh, object data)
707 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
708 EndRequest += new EventHandler (invoker.Invoke);
711 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
713 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
714 PostRequestHandlerExecute += new EventHandler (invoker.Invoke);
717 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler bh, EndEventHandler eh, object data)
719 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
720 PreRequestHandlerExecute += new EventHandler (invoker.Invoke);
723 public void AddOnReleaseRequestStateAsync (BeginEventHandler bh, EndEventHandler eh, object data)
725 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
726 ReleaseRequestState += new EventHandler (invoker.Invoke);
729 public void AddOnResolveRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
731 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
732 ResolveRequestCache += new EventHandler (invoker.Invoke);
735 public void AddOnUpdateRequestCacheAsync (BeginEventHandler bh, EndEventHandler eh, object data)
737 AsyncInvoker invoker = new AsyncInvoker (bh, eh, data);
738 UpdateRequestCache += new EventHandler (invoker.Invoke);
742 // They are for use with the IIS7 integrated mode, but have been added for
744 static object LogRequestEvent = new object ();
745 public event EventHandler LogRequest
747 add { AddEventHandler (LogRequestEvent, value); }
748 remove { RemoveEventHandler (LogRequestEvent, value); }
751 public void AddOnLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
753 AddOnLogRequestAsync (bh, eh, null);
756 public void AddOnLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
758 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
759 LogRequest += new EventHandler (invoker.Invoke);
762 static object MapRequestHandlerEvent = new object ();
763 public event EventHandler MapRequestHandler
765 add { AddEventHandler (MapRequestHandlerEvent, value); }
766 remove { RemoveEventHandler (MapRequestHandlerEvent, value); }
769 public void AddOnMapRequestHandlerAsync (BeginEventHandler bh, EndEventHandler eh)
771 AddOnMapRequestHandlerAsync (bh, eh, null);
774 public void AddOnMapRequestHandlerAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
776 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
777 MapRequestHandler += new EventHandler (invoker.Invoke);
780 static object PostLogRequestEvent = new object ();
781 public event EventHandler PostLogRequest
783 add { AddEventHandler (PostLogRequestEvent, value); }
784 remove { RemoveEventHandler (PostLogRequestEvent, value); }
787 public void AddOnPostLogRequestAsync (BeginEventHandler bh, EndEventHandler eh)
789 AddOnPostLogRequestAsync (bh, eh, null);
792 public void AddOnPostLogRequestAsync (BeginEventHandler beginHandler, EndEventHandler endHandler, object state)
794 AsyncInvoker invoker = new AsyncInvoker (beginHandler, endHandler, state);
795 PostLogRequest += new EventHandler (invoker.Invoke);
800 internal event EventHandler DefaultAuthentication;
802 void AddEventHandler (object key, EventHandler handler)
804 if (fullInitComplete)
807 Events.AddHandler (key, handler);
810 void RemoveEventHandler (object key, EventHandler handler)
812 if (fullInitComplete)
815 Events.RemoveHandler (key, handler);
819 // Bypass all the event on the Http pipeline and go directly to EndRequest
821 public void CompleteRequest ()
823 stop_processing = true;
826 internal bool RequestCompleted {
827 set { stop_processing = value; }
830 internal void DisposeInternal ()
834 if (modcoll != null) {
835 for (int i = modcoll.Count - 1; i >= 0; i--) {
836 modcoll.Get (i).Dispose ();
842 EventHandler eh = nonApplicationEvents [disposedEvent] as EventHandler;
844 eh (this, EventArgs.Empty);
850 public virtual void Dispose ()
854 public virtual string GetVaryByCustomString (HttpContext context, string custom)
856 if (custom == null) // Sigh
857 throw new NullReferenceException ();
859 if (0 == String.Compare (custom, "browser", true, CultureInfo.InvariantCulture))
860 return context.Request.Browser.Type;
866 // If we catch an error, queue this error
868 void ProcessError (Exception e)
870 bool first = context.Error == null;
871 context.AddError (e);
873 EventHandler eh = nonApplicationEvents [errorEvent] as EventHandler;
876 eh (this, EventArgs.Empty);
877 } catch (ThreadAbortException taex){
878 context.ClearError ();
879 if (FlagEnd.Value == taex.ExceptionState)
880 // This happens on Redirect() or End()
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;
902 // Ticks the clock: next step on the pipeline.
904 internal void Tick ()
908 if (context.Error is UnifyRequestException) {
909 Exception ex = context.Error.InnerException;
910 context.ClearError ();
911 vmw.common.TypeUtils.Throw (ex);
915 if (pipeline.MoveNext ()){
916 if ((bool)pipeline.Current)
921 catch (Exception ex) {
922 if (ex is ThreadAbortException &&
923 ((ThreadAbortException) ex).ExceptionState == FlagEnd.Value)
925 if (context.WorkerRequest is IHttpUnifyWorkerRequest) {
926 context.ClearError ();
927 context.AddError (new UnifyRequestException (ex));
934 } catch (ThreadAbortException taex) {
935 object obj = taex.ExceptionState;
936 Thread.ResetAbort ();
937 stop_processing = true;
938 if (obj is StepTimeout)
939 ProcessError (new HttpException ("The request timed out."));
941 context.ClearError ();
942 if (FlagEnd.Value != obj)
943 context.AddError (taex);
947 } catch (Exception e) {
948 stop_processing = true;
963 // Invoked when our async callback called from RunHooks completes,
964 // we restart the pipeline here.
966 void async_callback_completed_cb (IAsyncResult ar)
968 if (current_ai.end != null){
971 } catch (Exception e) {
979 void async_handler_complete_cb (IAsyncResult ar)
981 IHttpAsyncHandler async_handler = ar != null ? ar.AsyncState as IHttpAsyncHandler : null;
984 if (async_handler != null)
985 async_handler.EndProcessRequest (ar);
986 } catch (Exception e){
994 // This enumerator yields whether processing must be stopped:
995 // true: processing of the pipeline must be stopped
996 // false: processing of the pipeline must not be stopped
998 IEnumerable RunHooks (Delegate list)
1000 Delegate [] delegates = list.GetInvocationList ();
1002 foreach (EventHandler d in delegates){
1003 if (d.Target != null && (d.Target is AsyncInvoker)){
1004 current_ai = (AsyncInvoker) d.Target;
1009 context.BeginTimeoutPossible ();
1010 current_ai.begin (this, EventArgs.Empty, async_callback_completed_cb, current_ai.data);
1013 context.EndTimeoutPossible ();
1017 // If things are still moving forward, yield this
1021 yield return stop_processing;
1022 else if (stop_processing)
1026 context.BeginTimeoutPossible ();
1027 d (this, EventArgs.Empty);
1029 context.EndTimeoutPossible ();
1031 if (stop_processing)
1037 static void FinalErrorWrite (HttpResponse response, string error)
1040 response.Write (error);
1041 response.Flush (true);
1049 if (context.Error == null){
1051 context.Response.Flush (true);
1052 } catch (Exception e){
1053 context.AddError (e);
1057 Exception error = context.Error;
1059 HttpResponse response = context.Response;
1061 if (!response.HeadersSent){
1062 response.ClearHeaders ();
1063 response.ClearContent ();
1065 if (error is HttpException){
1066 response.StatusCode = ((HttpException)error).GetHttpCode ();
1068 error = new HttpException ("", error);
1069 response.StatusCode = 500;
1071 HttpException httpEx = (HttpException) error;
1072 if (!RedirectCustomError (ref httpEx))
1073 FinalErrorWrite (response, httpEx.GetHtmlErrorMessage ());
1075 response.Flush (true);
1077 if (!(error is HttpException))
1078 error = new HttpException ("", error);
1079 FinalErrorWrite (response, ((HttpException) error).GetHtmlErrorMessage ());
1086 // Invoked at the end of the pipeline execution
1088 void PipelineDone ()
1091 EventHandler handler = Events [EndRequestEvent] as EventHandler;
1092 if (handler != null)
1093 handler (this, EventArgs.Empty);
1094 } catch (Exception e){
1100 } catch (ThreadAbortException taex) {
1101 ProcessError (taex);
1102 Thread.ResetAbort ();
1103 } catch (Exception e) {
1104 Console.WriteLine ("Internal error: OutputPage threw an exception " + e);
1106 context.WorkerRequest.EndOfRequest();
1107 if (factory != null && context.Handler != null){
1108 factory.ReleaseHandler (context.Handler);
1109 context.Handler = null;
1113 context.PopHandler ();
1115 // context = null; -> moved to PostDone
1121 if (begin_iar != null)
1122 begin_iar.Complete ();
1126 requests_total_counter.Increment ();
1136 public Tim (string name) {
1140 public string Name {
1141 get { return name; }
1142 set { name = value; }
1145 public void Start () {
1146 start = DateTime.UtcNow;
1149 public void Stop () {
1150 Console.WriteLine ("{0}: {1}ms", name, (DateTime.UtcNow - start).TotalMilliseconds);
1155 [Conditional ("PIPELINE_TIMER")]
1156 void StartTimer (string name)
1164 [Conditional ("PIPELINE_TIMER")]
1171 // Events fired as described in `Http Runtime Support, HttpModules,
1172 // Handling Public Events'
1174 IEnumerator Pipeline ()
1176 Delegate eventHandler;
1177 if (stop_processing)
1181 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))
1205 StartTimer ("PostAuthenticateRequest");
1206 eventHandler = Events [PostAuthenticateRequestEvent];
1207 if (eventHandler != null)
1208 foreach (bool stop in RunHooks (eventHandler))
1212 StartTimer ("AuthorizeRequest");
1213 eventHandler = Events [AuthorizeRequestEvent];
1214 if (eventHandler != null)
1215 foreach (bool stop in RunHooks (eventHandler))
1219 StartTimer ("PostAuthorizeRequest");
1220 eventHandler = Events [PostAuthorizeRequestEvent];
1221 if (eventHandler != null)
1222 foreach (bool stop in RunHooks (eventHandler))
1227 StartTimer ("ResolveRequestCache");
1228 eventHandler = Events [ResolveRequestCacheEvent];
1229 if (eventHandler != null)
1230 foreach (bool stop in RunHooks (eventHandler))
1235 StartTimer ("PostResolveRequestCache");
1236 eventHandler = Events [PostResolveRequestCacheEvent];
1237 if (eventHandler != null)
1238 foreach (bool stop in RunHooks (eventHandler))
1242 StartTimer ("MapRequestHandler");
1243 // As per http://msdn2.microsoft.com/en-us/library/bb470252(VS.90).aspx
1244 eventHandler = Events [MapRequestHandlerEvent];
1245 if (eventHandler != null)
1246 foreach (bool stop in RunHooks (eventHandler))
1249 context.MapRequestHandlerDone = true;
1252 StartTimer ("GetHandler");
1253 // Obtain the handler for the request.
1254 IHttpHandler handler = null;
1256 handler = GetHandler (context, context.Request.CurrentExecutionFilePath);
1257 context.Handler = handler;
1259 context.PushHandler (handler);
1261 } catch (FileNotFoundException fnf){
1263 Console.WriteLine ("$$$$$$$$$$:Sys.Web Pipeline");
1264 Console.WriteLine (fnf.ToString ());
1266 if (context.Request.IsLocal)
1267 ProcessError (new HttpException (404, String.Format ("File not found {0}", fnf.FileName), fnf, context.Request.FilePath));
1269 ProcessError (new HttpException (404, "File not found: " + Path.GetFileName (fnf.FileName), context.Request.FilePath));
1270 } catch (DirectoryNotFoundException dnf){
1271 if (!context.Request.IsLocal)
1272 dnf = null; // Do not "leak" real path information
1273 ProcessError (new HttpException (404, "Directory not found", dnf));
1274 } catch (Exception e) {
1279 if (stop_processing)
1283 StartTimer ("PostMapRequestHandler");
1284 eventHandler = Events [PostMapRequestHandlerEvent];
1285 if (eventHandler != null)
1286 foreach (bool stop in RunHooks (eventHandler))
1291 StartTimer ("AcquireRequestState");
1292 eventHandler = Events [AcquireRequestStateEvent];
1293 if (eventHandler != null){
1294 foreach (bool stop in RunHooks (eventHandler))
1300 StartTimer ("PostAcquireRequestState");
1301 eventHandler = Events [PostAcquireRequestStateEvent];
1302 if (eventHandler != null){
1303 foreach (bool stop in RunHooks (eventHandler))
1310 // From this point on, we need to ensure that we call
1311 // ReleaseRequestState, so the code below jumps to
1312 // `release:' to guarantee it rather than yielding.
1314 StartTimer ("PreRequestHandlerExecute");
1315 eventHandler = Events [PreRequestHandlerExecuteEvent];
1316 if (eventHandler != null)
1317 foreach (bool stop in RunHooks (eventHandler))
1325 bool doProcessHandler = false;
1329 IHttpHandler ctxHandler = context.Handler;
1330 if (ctxHandler != null && handler != ctxHandler) {
1331 context.PopHandler ();
1332 handler = ctxHandler;
1333 context.PushHandler (handler);
1337 StartTimer ("ProcessRequest");
1339 context.BeginTimeoutPossible ();
1340 if (handler != null){
1341 IHttpAsyncHandler async_handler = handler as IHttpAsyncHandler;
1343 if (async_handler != null){
1346 async_handler.BeginProcessRequest (context, async_handler_complete_cb, handler);
1349 handler.ProcessRequest (context);
1351 IHttpExtendedHandler extHandler=handler as IHttpExtendedHandler;
1352 doProcessHandler = extHandler != null && !extHandler.IsCompleted;
1356 if (context.Error != null)
1357 throw new TargetInvocationException(context.Error);
1360 context.EndTimeoutPossible ();
1364 if (doProcessHandler) {
1366 goto processHandler;
1370 yield return stop_processing;
1371 else if (stop_processing)
1374 // These are executed after the application has returned
1376 StartTimer ("PostRequestHandlerExecute");
1377 eventHandler = Events [PostRequestHandlerExecuteEvent];
1378 if (eventHandler != null)
1379 foreach (bool stop in RunHooks (eventHandler))
1385 StartTimer ("ReleaseRequestState");
1386 eventHandler = Events [ReleaseRequestStateEvent];
1387 if (eventHandler != null){
1388 #pragma warning disable 219
1389 foreach (bool stop in RunHooks (eventHandler)) {
1391 // Ignore the stop signal while release the state
1395 #pragma warning restore 219
1399 if (stop_processing)
1403 StartTimer ("PostReleaseRequestState");
1404 eventHandler = Events [PostReleaseRequestStateEvent];
1405 if (eventHandler != null)
1406 foreach (bool stop in RunHooks (eventHandler))
1411 StartTimer ("Filter");
1412 if (context.Error == null)
1413 context.Response.DoFilter (true);
1416 StartTimer ("UpdateRequestCache");
1417 eventHandler = Events [UpdateRequestCacheEvent];
1418 if (eventHandler != null)
1419 foreach (bool stop in RunHooks (eventHandler))
1424 StartTimer ("PostUpdateRequestCache");
1425 eventHandler = Events [PostUpdateRequestCacheEvent];
1426 if (eventHandler != null)
1427 foreach (bool stop in RunHooks (eventHandler))
1431 StartTimer ("LogRequest");
1432 eventHandler = Events [LogRequestEvent];
1433 if (eventHandler != null)
1434 foreach (bool stop in RunHooks (eventHandler))
1438 StartTimer ("PostLogRequest");
1439 eventHandler = Events [PostLogRequestEvent];
1440 if (eventHandler != null)
1441 foreach (bool stop in RunHooks (eventHandler))
1445 StartTimer ("PipelineDone");
1451 internal CultureInfo GetThreadCulture (HttpRequest request, CultureInfo culture, bool isAuto)
1456 CultureInfo ret = null;
1457 string[] languages = request.UserLanguages;
1459 if (languages != null && languages.Length > 0)
1460 ret = CultureInfo.CreateSpecificCulture (languages[0]);
1477 GlobalizationSection cfg;
1478 cfg = (GlobalizationSection) WebConfigurationManager.GetSection ("system.web/globalization");
1479 app_culture = cfg.GetCulture ();
1480 autoCulture = cfg.IsAutoCulture;
1481 appui_culture = cfg.GetUICulture ();
1482 autoUICulture = cfg.IsAutoUICulture;
1484 GlobalizationConfiguration cfg;
1485 cfg = GlobalizationConfiguration.GetInstance (null);
1487 app_culture = cfg.Culture;
1488 appui_culture = cfg.UICulture;
1493 context.StartTimeoutTimer ();
1495 Thread th = Thread.CurrentThread;
1496 if (app_culture != null) {
1497 prev_app_culture = th.CurrentCulture;
1498 CultureInfo new_app_culture = GetThreadCulture (Request, app_culture, autoCulture);
1499 if (!new_app_culture.Equals (CultureInfo.InvariantCulture))
1500 th.CurrentCulture = new_app_culture;
1503 if (appui_culture != null) {
1504 prev_appui_culture = th.CurrentUICulture;
1505 CultureInfo new_app_culture = GetThreadCulture (Request, appui_culture, autoUICulture);
1506 if (!new_app_culture.Equals (CultureInfo.InvariantCulture))
1507 th.CurrentUICulture = new_app_culture;
1511 prev_user = Thread.CurrentPrincipal;
1518 if (removeConfigurationFromCache) {
1519 WebConfigurationManager.RemoveConfigurationFromCache (context);
1520 removeConfigurationFromCache = false;
1523 Thread th = Thread.CurrentThread;
1525 if (Thread.CurrentPrincipal != prev_user)
1526 Thread.CurrentPrincipal = prev_user;
1528 if (prev_appui_culture != null && prev_appui_culture != th.CurrentUICulture)
1529 th.CurrentUICulture = prev_appui_culture;
1530 if (prev_app_culture != null && prev_app_culture != th.CurrentCulture)
1531 th.CurrentCulture = prev_app_culture;
1534 if (context == null)
1535 context = HttpContext.Current;
1536 context.StopTimeoutTimer ();
1538 context.Request.ReleaseResources ();
1539 context.Response.ReleaseResources ();
1542 HttpContext.Current = null;
1545 void Start (object x)
1547 CultureInfo[] cultures = x as CultureInfo[];
1548 if (cultures != null && cultures.Length == 2) {
1549 Thread ct = Thread.CurrentThread;
1550 ct.CurrentCulture = cultures [0];
1551 ct.CurrentUICulture = cultures [1];
1556 } catch (Exception e) {
1558 initialization_exception = e;
1560 FinalErrorWrite (context.Response, new HttpException ("", e).GetHtmlErrorMessage ());
1565 HttpContext.Current = Context;
1567 pipeline = Pipeline ();
1571 const string HANDLER_CACHE = "@@HttpHandlerCache@@";
1573 internal static Hashtable GetHandlerCache ()
1575 Cache cache = HttpRuntime.InternalCache;
1576 Hashtable ret = cache [HANDLER_CACHE] as Hashtable;
1579 ret = new Hashtable ();
1580 cache.Insert (HANDLER_CACHE, ret);
1586 internal static void ClearHandlerCache ()
1588 Hashtable cache = GetHandlerCache ();
1592 object LocateHandler (string verb, string url)
1594 Hashtable cache = GetHandlerCache ();
1595 string id = String.Concat (verb, url);
1596 object ret = cache [id];
1602 HttpHandlersSection httpHandlersSection = (HttpHandlersSection) WebConfigurationManager.GetWebApplicationSection ("system.web/httpHandlers");
1603 ret = httpHandlersSection.LocateHandler (verb, url);
1605 HandlerFactoryConfiguration factory_config = (HandlerFactoryConfiguration) HttpContext.GetAppConfig ("system.web/httpHandlers");
1606 ret = factory_config.LocateHandler (verb, url);
1609 IHttpHandler handler = ret as IHttpHandler;
1610 if (handler != null && handler.IsReusable)
1616 internal IHttpHandler GetHandler (HttpContext context, string url)
1618 return GetHandler (context, url, false);
1621 // Used by HttpServerUtility.Execute
1622 internal IHttpHandler GetHandler (HttpContext context, string url, bool ignoreContextHandler)
1624 if (!ignoreContextHandler && context.Handler != null)
1625 return context.Handler;
1627 HttpRequest request = context.Request;
1628 string verb = request.RequestType;
1630 IHttpHandler handler = null;
1631 object o = LocateHandler (verb, url);
1633 factory = o as IHttpHandlerFactory;
1635 if (factory == null) {
1636 handler = (IHttpHandler) o;
1638 handler = factory.GetHandler (context, verb, url, request.MapPath (url));
1644 void IHttpHandler.ProcessRequest (HttpContext context)
1647 this.context = context;
1655 // This is used by FireOnAppStart, when we init the application
1656 // as the context is required to be set at that point (the user
1657 // might call methods that require it on that hook).
1659 internal void SetContext (HttpContext context)
1661 this.context = context;
1664 internal void SetSession (HttpSessionState session)
1666 this.session = session;
1669 IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData)
1671 this.context = context;
1674 begin_iar = new AsyncRequestState (done, cb, extraData);
1676 CultureInfo[] cultures = new CultureInfo [2];
1677 cultures [0] = Thread.CurrentThread.CurrentCulture;
1678 cultures [1] = Thread.CurrentThread.CurrentUICulture;
1683 if (Thread.CurrentThread.IsThreadPoolThread)
1687 ThreadPool.QueueUserWorkItem (new WaitCallback (Start), cultures);
1692 void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
1698 if (!result.IsCompleted)
1699 result.AsyncWaitHandle.WaitOne ();
1703 public virtual void Init ()
1707 bool IHttpHandler.IsReusable {
1714 internal void ClearError ()
1716 context.ClearError ();
1719 bool RedirectErrorPage (string error_page)
1721 if (context.Request.QueryString ["aspxerrorpath"] != null)
1724 Response.Redirect (error_page + "?aspxerrorpath=" + Request.Path, false);
1728 bool RedirectCustomError (ref HttpException httpEx)
1731 if (!context.IsCustomErrorEnabledUnsafe)
1735 CustomErrorsSection config = (CustomErrorsSection)WebConfigurationManager.GetSection ("system.web/customErrors");
1737 CustomErrorsConfig config = null;
1739 config = (CustomErrorsConfig) context.GetConfig ("system.web/customErrors");
1743 if (config == null) {
1744 if (context.ErrorPage != null)
1745 return RedirectErrorPage (context.ErrorPage);
1751 CustomError err = config.Errors [context.Response.StatusCode.ToString()];
1752 string redirect = err == null ? null : err.Redirect;
1754 string redirect = config [context.Response.StatusCode];
1756 if (redirect == null) {
1757 redirect = context.ErrorPage;
1758 if (redirect == null)
1759 redirect = config.DefaultRedirect;
1762 if (redirect == null)
1765 return RedirectErrorPage (redirect);
1767 catch (Exception ex) {
1768 httpEx = new HttpException (500, "", ex);
1773 internal static string BinDirectory
1776 if (binDirectory == null) {
1777 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
1778 string baseDir = setup.ApplicationBase;
1781 foreach (string dir in BinDirs) {
1782 bindir = Path.Combine (baseDir, dir);
1783 if (!Directory.Exists (bindir))
1785 binDirectory = bindir;
1790 return binDirectory;
1794 internal static string[] BinDirectoryAssemblies
1797 ArrayList binDlls = null;
1800 string bindir = BinDirectory;
1801 if (bindir != null) {
1802 binDlls = new ArrayList ();
1803 dlls = Directory.GetFiles (bindir, "*.dll");
1804 binDlls.AddRange (dlls);
1807 if (binDlls == null)
1808 return new string[] {};
1810 return (string[]) binDlls.ToArray (typeof (string));
1814 internal static Type LoadType (string typeName)
1816 return LoadType (typeName, false);
1819 internal static Type LoadType (string typeName, bool throwOnMissing)
1821 Type type = Type.GetType (typeName);
1826 Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
1827 foreach (Assembly ass in assemblies) {
1828 type = ass.GetType (typeName, false);
1834 IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
1835 if (tla != null && tla.Count > 0) {
1836 foreach (Assembly asm in tla) {
1839 type = asm.GetType (typeName, false);
1846 type = LoadTypeFromBin (typeName);
1851 throw new TypeLoadException (String.Format ("Type '{0}' cannot be found", typeName));
1856 internal static Type LoadTypeFromBin (string typeName)
1860 foreach (string s in BinDirectoryAssemblies) {
1861 Assembly binA = Assembly.LoadFrom (s);
1862 type = binA.GetType (typeName, false);
1874 // Based on Fritz' Onion's AsyncRequestState class for asynchronous IHttpAsyncHandlers
1876 class AsyncRequestState : IAsyncResult {
1880 ManualResetEvent complete_event = null;
1882 internal AsyncRequestState (ManualResetEvent complete_event, AsyncCallback cb, object cb_data)
1885 this.cb_data = cb_data;
1886 this.complete_event = complete_event;
1889 internal void Complete ()
1894 // TODO: if this throws an error, we have no way of reporting it
1895 // Not really too bad, since the only failure might be
1896 // `HttpRuntime.request_processed'.
1903 complete_event.Set ();
1906 public object AsyncState {
1912 public bool CompletedSynchronously {
1918 public bool IsCompleted {
1924 public WaitHandle AsyncWaitHandle {
1926 return complete_event;
1931 #region Helper classes
1934 // A wrapper to keep track of begin/end pairs
1936 class AsyncInvoker {
1937 public BeginEventHandler begin;
1938 public EndEventHandler end;
1941 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh, object d)
1948 public AsyncInvoker (BeginEventHandler bh, EndEventHandler eh)
1954 public void Invoke (object sender, EventArgs e)
1956 throw new Exception ("This is just a dummy");