Beispiel #1
0
        // Disassociates this ThreadContext from the current thread. Any ambient values (e.g., culture)
        // associated with the current request are stored in the HttpContext object so that they
        // can be restored the next time a ThreadContext associated with this HttpContext is active.
        // Impersonation and other similar modifications to the current thread are undone.
        internal void DisassociateFromCurrentThread()
        {
            Debug.Trace("OnThread", GetTraceMessage("Leave1"));
            Debug.Assert(Current == this, "This ThreadContext isn't associated with current thread.");
            Debug.Assert(!HasBeenDisassociatedFromThread, "This ThreadContext has already been disassociated from a thread.");

            /*
             * !! IMPORTANT !!
             * Keep this logic in [....] with AssociateWithCurrentThread and EnterExecutionContext.
             */

            Current = _originalThreadContextCurrent;
            HasBeenDisassociatedFromThread = true;

            // remove thread if set
            if (_setCurrentThreadOnHttpContext)
            {
                HttpContext.CurrentThread = null;
            }

            // this thread should not be locking app state
            HttpApplicationFactory.ApplicationState.EnsureUnLock();

            // stop impersonation
            UndoImpersonationContext();

            // restore culture
            RestoreRequestLevelCulture();

            // restrore synchronization context
            AsyncOperationManager.SynchronizationContext = _originalSynchronizationContext;

            // restore thread principal
            HttpApplication.SetCurrentPrincipalWithAssert(_originalThreadPrincipal);

            // Remove SqlCacheDependency cookie from call context if necessary
            HttpContext.RemoveSqlDependencyCookie();

            // remove http context from the call context
            DisposableHttpContextWrapper.SwitchContext(_originalHttpContext);
            _originalHttpContext = null;

            Debug.Trace("OnThread", GetTraceMessage("Leave2"));
        }
Beispiel #2
0
        // Associates this ThreadContext with the current thread. This restores certain
        // ambient values associated with the current HttpContext, such as the current
        // user and cultures. It also sets HttpContext.Current.
        internal void AssociateWithCurrentThread(bool setImpersonationContext)
        {
            Debug.Assert(HttpContext != null); // only to be used when context is available
            Debug.Assert(Current != this, "This ThreadContext is already associated with this thread.");
            Debug.Assert(!HasBeenDisassociatedFromThread, "This ThreadContext has already been disassociated from a thread.");

            Debug.Trace("OnThread", GetTraceMessage("Enter1"));

            /*
             * !! IMPORTANT !!
             * Keep this logic in [....] with DisassociateFromCurrentThread and EnterExecutionContext.
             */

            // attach http context to the call context
            _originalHttpContext = DisposableHttpContextWrapper.SwitchContext(HttpContext);

            // set impersonation on the current thread
            if (setImpersonationContext)
            {
                SetImpersonationContext();
            }

            // set synchronization context for the current thread to support the async pattern
            _originalSynchronizationContext = AsyncOperationManager.SynchronizationContext;
            AspNetSynchronizationContextBase aspNetSynchronizationContext = HttpContext.SyncContext;

            AsyncOperationManager.SynchronizationContext = aspNetSynchronizationContext;

            // set ETW trace ID
            Guid g = HttpContext.WorkerRequest.RequestTraceIdentifier;

            if (g != Guid.Empty)
            {
                CallContext.LogicalSetData("E2ETrace.ActivityID", g);
            }

            // set SqlDependecyCookie
            HttpContext.ResetSqlDependencyCookie();

            // set principal on the current thread
            _originalThreadPrincipal = Thread.CurrentPrincipal;
            HttpApplication.SetCurrentPrincipalWithAssert(HttpContext.User);

            // only set culture on the current thread if it is not initialized
            SetRequestLevelCulture();

            // DevDivBugs 75042
            // set current thread in context if there is not there
            // the timeout manager  uses this to abort the correct thread
            if (HttpContext.CurrentThread == null)
            {
                _setCurrentThreadOnHttpContext = true;
                HttpContext.CurrentThread      = Thread.CurrentThread;
            }

            // Store a reference to the original ThreadContext.Current. It is possible that a parent
            // ThreadContext might already be associated with the current thread, e.g. if the current
            // stack contains a call to MgdIndicateCompletion (via
            // PipelineRuntime.ProcessRequestNotificationHelper). If this is the case, the child
            // ThreadContext will temporarily take over.
            _originalThreadContextCurrent = Current;
            Current = this;

            Debug.Trace("OnThread", GetTraceMessage("Enter2"));
        }
Beispiel #3
0
        // Called by AspNetHostExecutionContextManager to signal that ExecutionContext.Run
        // is being called on a thread currently associated with our ThreadContext. Since
        // ExecutionContext.Run destroys some of our ambient state (HttpContext.Current, etc.),
        // we need to restore it. This method returns an Action which should be called when
        // the call to ExecutionContext.Run is concluding.
        internal Action EnterExecutionContext()
        {
            Debug.Trace("OnThread", GetTraceMessage("EnterExecutionContext1"));
            Debug.Assert(Current == this, "This ThreadContext isn't associated with current thread.");
            Debug.Assert(!HasBeenDisassociatedFromThread, "This ThreadContext has already been disassociated from a thread.");

            /*
             * !! IMPORTANT !!
             * Keep this logic in [....] with AssociateWithCurrentThread and DisassociateFromCurrentThread.
             */

            // ExecutionContext.Run replaces the current impersonation token, so we need to impersonate
            // if AssociateWithCurrentThread also did so.

            ClientImpersonationContext executionContextClientImpersonationContext = null;

            if (_newImpersonationContext != null)
            {
                executionContextClientImpersonationContext = CreateNewClientImpersonationContext();
            }

            // ExecutionContext.Run resets the LogicalCallContext / IllogicalCallContext (which contains HttpContext.Current),
            // so we need to restore both of them.

            DisposableHttpContextWrapper.SwitchContext(HttpContext);

            Guid g = HttpContext.WorkerRequest.RequestTraceIdentifier;

            if (g != Guid.Empty)
            {
                CallContext.LogicalSetData("E2ETrace.ActivityID", g);
            }

            HttpContext.ResetSqlDependencyCookie();

            // ExecutionContext.Run resets the thread's CurrentPrincipal, so we need to restore it.

            HttpApplication.SetCurrentPrincipalWithAssert(HttpContext.User);

            // Other items like [ThreadStatic] fields, culture, etc. are untouched by ExecutionContext.Run,
            // so we don't need to worry about them.

            Debug.Trace("OnThread", GetTraceMessage("EnterExecutionContext2"));

            // This delegate is the cleanup routine.
            return(() => {
                Debug.Trace("OnThread", GetTraceMessage("LeaveExecutionContext1"));

                // Undo any impersonation that we performed.
                if (executionContextClientImpersonationContext != null)
                {
                    executionContextClientImpersonationContext.Undo();
                }

                // Other things, e.g. changes to the logical/illogical call contexts, changes
                // to CurrentPrincipal, etc., will automatically be reverted anyway when
                // the call to ExecutionContext.Run concludes, so we don't need to clean up
                // here.

                Debug.Trace("OnThread", GetTraceMessage("LeaveExecutionContext2"));
            });
        }