2 // System.Web.HttpApplication
5 // Patrik Torstensson (ptorsten@hotmail.com)
6 // Tim Coleman (tim@timcoleman.com)
7 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
10 using System.Collections;
11 using System.ComponentModel;
13 using System.Threading;
14 using System.Security.Principal;
15 using System.Runtime.Remoting.Messaging;
17 using System.Web.Configuration;
18 using System.Web.SessionState;
24 public class HttpApplication : IHttpAsyncHandler, IHttpHandler, IComponent, IDisposable
27 #region Event Handlers
29 // Async event holders
30 AsyncEvents _acquireRequestStateAsync;
31 AsyncEvents _authenticateRequestAsync;
32 AsyncEvents _endRequestAsync;
33 AsyncEvents _beginRequestAsync;
34 AsyncEvents _authorizeRequestAsync;
35 AsyncEvents _updateRequestCacheAsync;
36 AsyncEvents _resolveRequestCacheAsync;
37 AsyncEvents _releaseRequestStateAsync;
38 AsyncEvents _preRequestHandlerExecuteAsync;
39 AsyncEvents _postRequestHandlerExecuteAsync;
41 // ID objects used to indentify the event
42 static object AcquireRequestStateId = new Object ();
43 static object AuthenticateRequestId = new Object ();
44 static object DefaultAuthenticationId = new Object ();
45 static object EndRequestId = new Object ();
46 static object DisposedId = new Object ();
47 static object BeginRequestId = new Object ();
48 static object AuthorizeRequestId = new Object ();
49 static object UpdateRequestCacheId = new Object ();
50 static object ResolveRequestCacheId = new Object ();
51 static object ReleaseRequestStateId = new Object ();
52 static object PreSendRequestContentId = new Object ();
53 static object PreSendRequestHeadersId = new Object ();
54 static object PreRequestHandlerExecuteId = new Object ();
55 static object PostRequestHandlerExecuteId = new Object ();
56 static object ErrorId = new Object ();
59 private EventHandlerList _Events;
61 public event EventHandler AcquireRequestState {
62 add { Events.AddHandler (AcquireRequestStateId, value); }
63 remove { Events.RemoveHandler (AcquireRequestStateId, value); }
66 public event EventHandler AuthenticateRequest {
67 add { Events.AddHandler (AuthenticateRequestId, value); }
68 remove { Events.RemoveHandler (AuthenticateRequestId, value); }
71 public event EventHandler AuthorizeRequest {
72 add { Events.AddHandler (AuthorizeRequestId, value); }
73 remove { Events.RemoveHandler (AuthorizeRequestId, value); }
76 public event EventHandler BeginRequest {
77 add { Events.AddHandler (BeginRequestId, value); }
78 remove { Events.RemoveHandler (BeginRequestId, value); }
81 public event EventHandler Disposed {
82 add { Events.AddHandler (DisposedId, value); }
83 remove { Events.RemoveHandler (DisposedId, value); }
86 public event EventHandler EndRequest {
87 add { Events.AddHandler (EndRequestId, value); }
88 remove { Events.RemoveHandler (EndRequestId, value); }
91 public event EventHandler Error {
92 add { Events.AddHandler (ErrorId, value); }
93 remove { Events.RemoveHandler (ErrorId, value); }
96 public event EventHandler PostRequestHandlerExecute {
97 add { Events.AddHandler (PostRequestHandlerExecuteId, value); }
98 remove { Events.RemoveHandler (PostRequestHandlerExecuteId, value); }
101 public event EventHandler PreRequestHandlerExecute {
102 add { Events.AddHandler (PreRequestHandlerExecuteId, value); }
103 remove { Events.RemoveHandler (PreRequestHandlerExecuteId, value); }
106 public event EventHandler PreSendRequestContent {
107 add { Events.AddHandler (PreSendRequestContentId, value); }
108 remove { Events.RemoveHandler (PreSendRequestContentId, value); }
111 public event EventHandler ReleaseRequestState {
112 add { Events.AddHandler (ReleaseRequestStateId, value); }
113 remove { Events.RemoveHandler (ReleaseRequestStateId, value); }
116 public event EventHandler ResolveRequestCache
118 add { Events.AddHandler (ResolveRequestCacheId, value); }
119 remove { Events.RemoveHandler (ResolveRequestCacheId, value); }
122 public event EventHandler UpdateRequestCache {
123 add { Events.AddHandler (UpdateRequestCacheId, value); }
124 remove { Events.RemoveHandler (UpdateRequestCacheId, value); }
127 public event EventHandler PreSendRequestHeaders {
128 add { Events.AddHandler (PreSendRequestHeadersId, value); }
129 remove { Events.RemoveHandler (PreSendRequestHeadersId, value); }
132 internal event EventHandler DefaultAuthentication {
133 add { Events.AddHandler (DefaultAuthenticationId, value); }
134 remove { Events.RemoveHandler (DefaultAuthenticationId, value); }
137 public void AddOnAcquireRequestStateAsync (BeginEventHandler beg, EndEventHandler end)
139 if (null == _acquireRequestStateAsync)
140 _acquireRequestStateAsync = new AsyncEvents ();
142 _acquireRequestStateAsync.Add (beg, end);
145 public void AddOnAuthenticateRequestAsync(BeginEventHandler beg, EndEventHandler end)
147 if (null == _authenticateRequestAsync)
148 _authenticateRequestAsync = new AsyncEvents ();
150 _authenticateRequestAsync.Add (beg, end);
153 public void AddOnAuthorizeRequestAsync (BeginEventHandler beg, EndEventHandler end)
155 if (null == _authorizeRequestAsync)
156 _authorizeRequestAsync = new AsyncEvents ();
158 _authorizeRequestAsync.Add (beg, end);
161 public void AddOnBeginRequestAsync (BeginEventHandler beg, EndEventHandler end)
163 if (null == _beginRequestAsync)
164 _beginRequestAsync = new AsyncEvents ();
166 _beginRequestAsync.Add (beg, end);
169 public void AddOnEndRequestAsync (BeginEventHandler beg, EndEventHandler end)
171 if (null == _endRequestAsync)
172 _endRequestAsync = new AsyncEvents ();
174 _endRequestAsync.Add (beg, end);
177 public void AddOnPostRequestHandlerExecuteAsync (BeginEventHandler beg, EndEventHandler end)
179 if (null == _postRequestHandlerExecuteAsync)
180 _postRequestHandlerExecuteAsync = new AsyncEvents ();
182 _postRequestHandlerExecuteAsync.Add (beg, end);
185 public void AddOnPreRequestHandlerExecuteAsync (BeginEventHandler beg, EndEventHandler end)
187 if (null == _preRequestHandlerExecuteAsync)
188 _preRequestHandlerExecuteAsync = new AsyncEvents ();
190 _preRequestHandlerExecuteAsync.Add (beg, end);
193 public void AddOnReleaseRequestStateAsync (BeginEventHandler beg, EndEventHandler end)
195 if (null == _releaseRequestStateAsync)
196 _releaseRequestStateAsync = new AsyncEvents ();
198 _releaseRequestStateAsync.Add (beg, end);
201 public void AddOnResolveRequestCacheAsync (BeginEventHandler beg, EndEventHandler end)
203 if (null == _resolveRequestCacheAsync)
204 _resolveRequestCacheAsync = new AsyncEvents ();
206 _resolveRequestCacheAsync.Add (beg, end);
209 public void AddOnUpdateRequestCacheAsync (BeginEventHandler beg, EndEventHandler end)
211 if (null == _updateRequestCacheAsync)
212 _updateRequestCacheAsync = new AsyncEvents ();
214 _updateRequestCacheAsync.Add (beg, end);
219 #region State Machine
221 interface IStateHandler
224 bool CompletedSynchronously { get; }
225 bool PossibleToTimeout { get; }
228 class EventState : IStateHandler
230 HttpApplication _app;
233 public EventState (HttpApplication app, EventHandler evt)
239 public void Execute ()
242 _event (_app, EventArgs.Empty);
245 public bool CompletedSynchronously {
249 public bool PossibleToTimeout {
254 class AsyncEventState : IStateHandler
256 HttpApplication _app;
257 BeginEventHandler _begin;
258 EndEventHandler _end;
259 AsyncCallback _callback;
262 public AsyncEventState (HttpApplication app,
263 BeginEventHandler begin,
270 _callback = new AsyncCallback (OnAsyncReady);
273 public void Execute ()
276 IAsyncResult ar = _begin (_app, EventArgs.Empty, _callback, null);
277 if (ar.CompletedSynchronously) {
283 public bool CompletedSynchronously {
284 get { return !_async; }
287 public bool PossibleToTimeout {
289 // We can't cancel a async event
294 private void OnAsyncReady (IAsyncResult ar)
296 if (ar.CompletedSynchronously)
299 Exception error = null;
302 // Invoke end handler
304 } catch (Exception exc) {
305 // Flow this error to the next state (handle during state execution)
309 _app._state.ExecuteNextAsync (error);
317 public EventRecord(BeginEventHandler beg, EndEventHandler end)
323 public BeginEventHandler Begin;
324 public EndEventHandler End;
327 public AsyncEvents ()
329 _events = new ArrayList ();
332 public void Add (BeginEventHandler begin, EndEventHandler end)
334 _events.Add (new EventRecord (begin, end));
337 public void GetAsStates (HttpApplication app, ArrayList states)
339 foreach (object obj in _events)
340 states.Add (new AsyncEventState (app,
341 ((EventRecord) obj).Begin,
342 ((EventRecord) obj).End));
347 class ExecuteHandlerState : IStateHandler
349 HttpApplication _app;
350 AsyncCallback _callback;
351 IHttpAsyncHandler _handler;
354 public ExecuteHandlerState (HttpApplication app)
357 _callback = new AsyncCallback (OnAsyncReady);
360 private void OnAsyncReady (IAsyncResult ar)
362 if (ar.CompletedSynchronously)
365 Exception error = null;
368 // Invoke end handler
369 _handler.EndProcessRequest(ar);
370 } catch (Exception exc) {
371 // Flow this error to the next state (handle during state execution)
376 _app._state.ExecuteNextAsync (error);
379 public void Execute ()
381 IHttpHandler handler = _app.Context.Handler;
385 // Check if we can execute async
386 if (handler is IHttpAsyncHandler) {
388 _handler = (IHttpAsyncHandler) handler;
390 IAsyncResult ar = _handler.BeginProcessRequest (_app.Context,
394 if (ar.CompletedSynchronously) {
397 ((IHttpAsyncHandler) handler).EndProcessRequest (ar);
403 handler.ProcessRequest (_app.Context);
407 public bool CompletedSynchronously {
408 get { return !_async; }
411 public bool PossibleToTimeout {
413 if (_app.Context.Handler is IHttpAsyncHandler)
421 class CreateHandlerState : IStateHandler
423 HttpApplication _app;
425 public CreateHandlerState (HttpApplication app)
430 public void Execute ()
432 _app.Context.Handler = _app.CreateHttpHandler ( _app.Context,
433 _app.Request.RequestType,
434 _app.Request.FilePath,
435 _app.Request.PhysicalPath);
438 public bool CompletedSynchronously {
442 public bool PossibleToTimeout {
443 get { return false; }
447 class FilterHandlerState : IStateHandler
449 HttpApplication _app;
451 public FilterHandlerState (HttpApplication app)
456 public void Execute ()
458 _app.Context.Response.DoFilter (true);
461 public bool CompletedSynchronously {
465 public bool PossibleToTimeout {
472 HttpApplication _app;
473 WaitCallback _asynchandler;
475 IStateHandler [] _handlers;
476 int _currentStateIdx;
478 int _endRequestStateIdx;
482 // Helper to create the states for a normal event
483 private void GetAsStates (object Event, ArrayList states)
485 // Get list of clients for the sync events
486 Delegate evnt = _app.Events [Event];
490 System.Delegate [] clients = evnt.GetInvocationList();
491 foreach (Delegate client in clients)
492 states.Add (new EventState (_app, (EventHandler) client));
495 internal StateMachine (HttpApplication app)
500 internal void Init ()
502 _asynchandler = new WaitCallback (OnAsyncCallback);
504 // Create a arraylist of states to execute
505 ArrayList states = new ArrayList ();
508 if (null != _app._beginRequestAsync)
509 _app._beginRequestAsync.GetAsStates (_app, states);
510 GetAsStates (HttpApplication.BeginRequestId, states);
512 // AuthenticateRequest
513 if (null != _app._authenticateRequestAsync)
514 _app._authenticateRequestAsync.GetAsStates (_app, states);
515 GetAsStates (HttpApplication.AuthenticateRequestId, states);
517 // DefaultAuthentication
518 EventHandler defaultAuthHandler = (EventHandler) _app.Events [HttpApplication.DefaultAuthenticationId];
519 states.Add (new EventState (_app, defaultAuthHandler));
522 if (null != _app._authorizeRequestAsync)
523 _app._authorizeRequestAsync.GetAsStates (_app, states);
524 GetAsStates (HttpApplication.AuthorizeRequestId, states);
526 // ResolveRequestCache
527 if (null != _app._resolveRequestCacheAsync)
528 _app._resolveRequestCacheAsync.GetAsStates (_app, states);
529 GetAsStates (HttpApplication.ResolveRequestCacheId, states);
531 // [A handler (a page corresponding to the request URL) is created at this point.]
532 states.Add (new CreateHandlerState (_app));
534 // AcquireRequestState
535 if (null != _app._acquireRequestStateAsync)
536 _app._acquireRequestStateAsync.GetAsStates (_app, states);
537 GetAsStates (HttpApplication.AcquireRequestStateId, states);
539 // PreRequestHandlerExecute
540 if (null != _app._preRequestHandlerExecuteAsync)
541 _app._preRequestHandlerExecuteAsync.GetAsStates (_app, states);
542 GetAsStates (HttpApplication.PreRequestHandlerExecuteId, states);
544 // [The handler is executed.]
545 states.Add (new ExecuteHandlerState (_app));
547 // PostRequestHandlerExecute
548 if (null != _app._postRequestHandlerExecuteAsync)
549 _app._postRequestHandlerExecuteAsync.GetAsStates (_app, states);
550 GetAsStates (HttpApplication.PostRequestHandlerExecuteId, states);
552 // ReleaseRequestState
553 if (null != _app._releaseRequestStateAsync)
554 _app._releaseRequestStateAsync.GetAsStates (_app, states);
555 GetAsStates (HttpApplication.ReleaseRequestStateId, states);
557 // [Response filters, if any, filter the output.]
558 states.Add (new FilterHandlerState (_app));
560 // UpdateRequestCache
561 if (null != _app._updateRequestCacheAsync)
562 _app._updateRequestCacheAsync.GetAsStates (_app, states);
563 GetAsStates (HttpApplication.UpdateRequestCacheId, states);
566 _endRequestStateIdx = states.Count;
567 if (null != _app._endRequestAsync)
568 _app._endRequestAsync.GetAsStates (_app, states);
569 GetAsStates (HttpApplication.EndRequestId, states);
571 // Make list ready to execute
572 _handlers = new IStateHandler [states.Count];
573 states.CopyTo (_handlers);
577 internal void Reset ()
581 _currentStateIdx = -1;
582 _endStateIdx = _handlers.Length - 1;
585 internal void Start ()
588 ExecuteNextAsync (null);
591 internal void ExecuteNextAsync (Exception lasterror)
593 if (!Thread.CurrentThread.IsThreadPoolThread)
594 ThreadPool.QueueUserWorkItem (_asynchandler, lasterror);
596 ExecuteNext (lasterror);
599 internal void ExecuteNext (Exception lasterror)
601 bool ready_sync = false;
602 IStateHandler handler;
605 _app.OnStateExecuteEnter ();
608 if (null != lasterror) {
609 _app.HandleError (lasterror);
613 // Check if request flow is to be stopped
614 if ((_app.GetLastError () != null || _app._CompleteRequest) &&
615 _currentStateIdx < _endRequestStateIdx) {
616 _currentStateIdx = _endRequestStateIdx;
617 // MS does not filter on error
618 _app._Context.Response.DoFilter (false);
619 } else if (_currentStateIdx < _endStateIdx) {
620 // Get next state handler
624 handler = _handlers [_currentStateIdx];
626 lasterror = ExecuteState (handler, ref ready_sync);
629 } while (ready_sync && _currentStateIdx < _endStateIdx);
631 if (null != lasterror)
632 _app.HandleError (lasterror);
634 _app.OnStateExecuteLeave ();
639 // Finish the request off..
640 if (lasterror != null || _currentStateIdx == _endStateIdx) {
641 _app._asyncWebResult.Complete ((_countSyncSteps == _countSteps),
645 _app.Context.Handler = null;
646 _app.Context.ApplicationInstance = null;
647 _app.RecycleHandlers ();
648 _app._asyncWebResult = null;
650 HttpApplicationFactory.RecycleInstance (_app);
654 private void OnAsyncCallback (object obj)
656 ExecuteNext ((Exception) obj);
659 private Exception ExecuteState (IStateHandler state, ref bool readysync)
661 Exception lasterror = null;
663 if (state.PossibleToTimeout) {
664 _app.Context.BeginTimeoutPossible ();
670 if (state.PossibleToTimeout) {
671 _app.Context.EndTimeoutPossible ();
675 if (state.PossibleToTimeout) {
677 _app.Context.TryWaitForTimeout ();
680 readysync = state.CompletedSynchronously;
681 } catch (ThreadAbortException obj) {
682 object o = obj.ExceptionState;
683 Type type = (o != null) ? o.GetType () : null;
684 if (type == typeof (StepTimeout)) {
685 Thread.ResetAbort ();
686 lasterror = new HttpException ("The request timed out.");
687 _app.CompleteRequest ();
688 } else if (type == typeof (StepCompleteRequest)) {
689 Thread.ResetAbort ();
690 _app.CompleteRequest ();
692 } catch (Exception obj) {
706 bool _CompleteRequest;
707 HttpContext _Context;
708 Exception _lastError;
710 HttpContext _savedContext;
711 IPrincipal _savedUser;
712 HttpAsyncResult _asyncWebResult;
715 HttpModuleCollection _ModuleCollection;
716 HttpSessionState _Session;
717 HttpApplicationState _appState;
718 string assemblyLocation;
720 bool _InPreRequestResponseMode;
725 public HttpApplication ()
727 assemblyLocation = GetType ().Assembly.Location;
733 internal IHttpHandler CreateHttpHandler (HttpContext context,
738 HandlerFactoryConfiguration handler =
739 HttpContext.GetAppConfig ("system.web/httpHandlers")
740 as HandlerFactoryConfiguration;
743 throw new HttpException ("Cannot get system.web/httpHandlers handler.");
745 object result = handler.FindHandler (type, file).Create ();
746 if (result is IHttpHandler)
747 return (IHttpHandler) result;
749 if (result is IHttpHandlerFactory) {
750 IHttpHandlerFactory factory = (IHttpHandlerFactory) result;
752 return factory.GetHandler (context, type, file, path);
753 } catch (DirectoryNotFoundException) {
754 throw new HttpException (404, "Cannot find '" + file + "'.");
755 } catch (FileNotFoundException) {
756 throw new HttpException (404, "Cannot find '" + file + "'.");
760 throw new HttpException ("Handler not found");
764 internal void RecycleHandlers ()
766 // TODO: Recycle the created handlers (via factory?)
769 internal void InitModules ()
771 ModulesConfiguration modules;
773 modules = (ModulesConfiguration) HttpContext.GetAppConfig ("system.web/httpModules");
775 throw new HttpException (
776 HttpRuntime.FormatResourceString ("missing_modules_config"));
778 _ModuleCollection = modules.CreateCollection ();
779 if (_ModuleCollection == null)
784 count = _ModuleCollection.Count;
785 for (pos = 0; pos != count; pos++)
786 ((IHttpModule) _ModuleCollection.Get (pos)).Init (this);
789 internal void InitCulture ()
791 // TODO: Read culture info from globalization from config
794 internal void OnStateExecuteEnter ()
796 // TODO: Set correct culture for the thread
798 _savedContext = HttpContext.Context;
799 HttpContext.Context = _Context;
800 HttpRuntime.TimeoutManager.Add (_Context);
802 _savedUser = Thread.CurrentPrincipal;
803 Thread.CurrentPrincipal = Context.User;
806 internal void OnStateExecuteLeave ()
808 // TODO: Restore culture for the thread
810 HttpRuntime.TimeoutManager.Remove (_Context);
811 HttpContext.Context = _savedContext;
812 if (null != _savedUser) {
813 Thread.CurrentPrincipal = _savedUser;
818 internal void ClearError ()
823 internal Exception GetLastError ()
825 if (_Context == null)
828 return _Context.Error;
831 internal void HandleError (Exception obj)
833 EventHandler handler;
836 if (null != _Context) {
837 if (null != _Context.Error)
840 _Context.AddError (obj);
842 if (null != _lastError)
851 // Fire OnError event here
852 handler = (EventHandler) Events [HttpApplication.ErrorId];
853 if (null != handler) {
855 handler (this, EventArgs.Empty);
856 } catch (Exception excp) {
857 if (null != _Context)
858 _Context.AddError (excp);
863 internal void Startup (HttpContext context, HttpApplicationState state)
868 _state = new StateMachine (this);
870 // Initialize all IHttpModule(s)
872 HttpApplicationFactory.AttachEvents (this);
875 // Initialize custom application
876 _InPreRequestResponseMode = true;
879 } catch (Exception obj) {
883 _InPreRequestResponseMode = false;
888 internal void Cleanup ()
892 } catch (Exception obj) {
896 if (null != _ModuleCollection) {
898 int count = _ModuleCollection.Count;
900 for (pos = 0; pos != count; pos++)
901 ((IHttpModule) _ModuleCollection.Get (pos)).Dispose ();
903 _ModuleCollection = null;
909 public void CompleteRequest ()
911 _CompleteRequest = true;
914 public virtual void Dispose ()
917 EventHandler disposed = (EventHandler) Events [HttpApplication.DisposedId];
918 if (null != disposed)
919 disposed (this, EventArgs.Empty);
922 public virtual void Init ()
926 public virtual string GetVaryByCustomString (HttpContext context, string custom)
928 if (custom.ToLower () == "browser")
929 return context.Request.Browser.Type;
934 IAsyncResult IHttpAsyncHandler.BeginProcessRequest (HttpContext context,
939 _Context.ApplicationInstance = this;
940 _CompleteRequest = false;
942 _asyncWebResult = new HttpAsyncResult (cb, extraData);
946 return _asyncWebResult;
949 void IHttpAsyncHandler.EndProcessRequest (IAsyncResult result)
951 HttpAsyncResult ar = (HttpAsyncResult) result;
953 if (null != ar.Error)
957 void IHttpHandler.ProcessRequest (HttpContext context)
959 throw new NotSupportedException (HttpRuntime.FormatResourceString("sync_not_supported"));
962 bool IHttpHandler.IsReusable {
969 internal string AssemblyLocation {
970 get { return assemblyLocation; }
974 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
975 public HttpApplicationState Application {
976 get { return _appState; }
980 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
981 public HttpContext Context {
982 get { return _Context; }
985 protected EventHandlerList Events {
988 _Events = new EventHandlerList ();
995 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
996 public HttpModuleCollection Modules {
998 if (null == _ModuleCollection)
999 _ModuleCollection = new HttpModuleCollection ();
1001 return _ModuleCollection;
1006 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1007 public HttpRequest Request {
1009 if (null != _Context && (!_InPreRequestResponseMode))
1010 return _Context.Request;
1012 throw new HttpException ("Can't get request object");
1017 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1018 public HttpResponse Response {
1020 if (null != _Context && (!_InPreRequestResponseMode))
1021 return _Context.Response;
1023 throw new HttpException ("Can't get response object");
1028 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1029 public HttpServerUtility Server {
1031 if (null != _Context)
1032 return _Context.Server;
1034 return new HttpServerUtility (this);
1039 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1040 public HttpSessionState Session {
1042 if (null != _Session)
1045 if (null != _Context && null != _Context.Session) {
1046 _Session = _Context.Session;
1050 throw new HttpException ("Failed to get session object");
1055 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1056 public IPrincipal User {
1057 get { return _Context.User; }
1061 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
1063 get { return _Site; }
1064 set { _Site = value; }
1066 #endregion Properties
1069 // Used in HttpResponse.End ()
1070 class StepCompleteRequest