예제 #1
0
        protected internal virtual IAsyncResult BeginInvokeActionMethodWithFilters(ControllerContext controllerContext, IList <IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            Func <ActionExecutedContext> endContinuation = null;

            BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
            {
                AsyncInvocationWithFilters invocation = new AsyncInvocationWithFilters(this, controllerContext, actionDescriptor, filters, parameters, asyncCallback, asyncState);

                const int StartingFilterIndex = 0;
                endContinuation = invocation.InvokeActionMethodFilterAsynchronouslyRecursive(StartingFilterIndex);

                if (invocation.InnerAsyncResult != null)
                {
                    // we're just waiting for the inner result to complete
                    return(invocation.InnerAsyncResult);
                }
                else
                {
                    // something was short-circuited and the action was not called, so this was a synchronous operation
                    SimpleAsyncResult newAsyncResult = new SimpleAsyncResult(asyncState);
                    newAsyncResult.MarkCompleted(completedSynchronously: true, callback: asyncCallback);
                    return(newAsyncResult);
                }
            };

            EndInvokeDelegate <ActionExecutedContext> endDelegate = delegate(IAsyncResult asyncResult)
            {
                return(endContinuation());
            };

            return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _invokeActionMethodWithFiltersTag));
        }
        public override IAsyncResult BeginExecute(ControllerContext controllerContext, IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }

            AsyncManager asyncManager = GetAsyncManager(controllerContext.Controller);

            BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) {
                // call the XxxAsync() method
                ParameterInfo[] parameterInfos     = AsyncMethodInfo.GetParameters();
                var             rawParameterValues = from parameterInfo in parameterInfos
                                                     select ExtractParameterFromDictionary(parameterInfo, parameters, AsyncMethodInfo);

                object[] parametersArray = rawParameterValues.ToArray();

                TriggerListener   listener    = new TriggerListener();
                SimpleAsyncResult asyncResult = new SimpleAsyncResult(asyncState);

                // hook the Finished event to notify us upon completion
                Trigger finishTrigger = listener.CreateTrigger();
                asyncManager.Finished += delegate { finishTrigger.Fire(); };
                asyncManager.OutstandingOperations.Increment();

                // to simplify the logic, force the rest of the pipeline to execute in an asynchronous callback
                listener.SetContinuation(() => ThreadPool.QueueUserWorkItem(_ => asyncResult.MarkCompleted(false /* completedSynchronously */, asyncCallback)));

                // the inner operation might complete synchronously, so all setup work has to be done before this point
                ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(AsyncMethodInfo);
                dispatcher.Execute(controllerContext.Controller, parametersArray); // ignore return value from this method

                // now that the XxxAsync() method has completed, kick off any pending operations
                asyncManager.OutstandingOperations.Decrement();
                listener.Activate();
                return(asyncResult);
            };

            EndInvokeDelegate <object> endDelegate = delegate(IAsyncResult asyncResult) {
                // call the XxxCompleted() method
                ParameterInfo[] completionParametersInfos    = CompletedMethodInfo.GetParameters();
                var             rawCompletionParameterValues = from parameterInfo in completionParametersInfos
                                                               select ExtractParameterOrDefaultFromDictionary(parameterInfo, asyncManager.Parameters);

                object[] completionParametersArray = rawCompletionParameterValues.ToArray();

                ActionMethodDispatcher dispatcher = DispatcherCache.GetDispatcher(CompletedMethodInfo);
                object actionReturnValue          = dispatcher.Execute(controllerContext.Controller, completionParametersArray);
                return(actionReturnValue);
            };

            return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _executeTag, asyncManager.Timeout));
        }
예제 #3
0
        private static IAsyncResult BeginInvokeAction_ActionNotFound(AsyncCallback callback, object state)
        {
            BeginInvokeDelegate beginDelegate = BeginInvokeAction_MakeSynchronousAsyncResult;

            EndInvokeDelegate <bool> endDelegate = delegate(IAsyncResult asyncResult) {
                return(false);
            };

            return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _invokeActionTag));
        }
        public virtual IAsyncResult BeginInvokeAction(ControllerContext controllerContext, string actionName, AsyncCallback callback, object state)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }

            Contract.Assert(controllerContext.RouteData != null);
            if (String.IsNullOrEmpty(actionName) && !controllerContext.RouteData.HasDirectRouteMatch())
            {
                throw Error.ParameterCannotBeNullOrEmpty("actionName");
            }

            ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
            ActionDescriptor     actionDescriptor     = FindAction(controllerContext, controllerDescriptor, actionName);

            if (actionDescriptor != null)
            {
                BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
                {
                    var task = InvokeActionAsync(controllerContext, actionDescriptor);
                    var tcs  = new TaskCompletionSource <bool>(asyncState);
                    task.ContinueWith(t =>
                    {
                        if (t.IsFaulted)
                        {
                            tcs.TrySetException(t.Exception.InnerExceptions);
                        }
                        else if (t.IsCanceled)
                        {
                            tcs.TrySetCanceled();
                        }
                        else
                        {
                            tcs.TrySetResult(t.Result);
                        }
                        if (asyncCallback != null)
                        {
                            asyncCallback(tcs.Task);
                        }
                    }, TaskContinuationOptions.ExecuteSynchronously);
                    return(tcs.Task);
                };
                EndInvokeDelegate <bool> endDelegate = delegate(IAsyncResult asyncResult)
                {
                    return(((Task <bool>)asyncResult).GetAwaiter().GetResult());
                };
                return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _invokeActionTag));
            }
            else
            {
                // Notify the controller that no action was found.
                return(BeginInvokeAction_ActionNotFound(callback, state));
            }
        }
예제 #5
0
        private IAsyncResult BeginInvokeAsynchronousActionMethod(ControllerContext controllerContext, AsyncActionDescriptor actionDescriptor, IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) {
                return(actionDescriptor.BeginExecute(controllerContext, parameters, asyncCallback, asyncState));
            };

            EndInvokeDelegate <ActionResult> endDelegate = delegate(IAsyncResult asyncResult) {
                object       returnValue = actionDescriptor.EndExecute(asyncResult);
                ActionResult result      = CreateActionResult(controllerContext, actionDescriptor, returnValue);
                return(result);
            };

            return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _invokeActionMethodTag));
        }
        protected internal virtual IAsyncResult BeginInvokeActionMethodWithFilters(ControllerContext controllerContext, IList <IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary <string, object> parameters, AsyncCallback callback, object state)
        {
            Func <ActionExecutedContext> endContinuation = null;

            BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
            {
                ActionExecutingContext preContext       = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
                IAsyncResult           innerAsyncResult = null;

                Func <Func <ActionExecutedContext> > beginContinuation = () =>
                {
                    innerAsyncResult = BeginInvokeActionMethod(controllerContext, actionDescriptor, parameters, asyncCallback, asyncState);
                    return(() =>
                           new ActionExecutedContext(controllerContext, actionDescriptor, false /* canceled */, null /* exception */)
                    {
                        Result = EndInvokeActionMethod(innerAsyncResult)
                    });
                };

                // need to reverse the filter list because the continuations are built up backward
                Func <Func <ActionExecutedContext> > thunk = filters.Reverse().Aggregate(beginContinuation,
                                                                                         (next, filter) => () => InvokeActionMethodFilterAsynchronously(filter, preContext, next));
                endContinuation = thunk();

                if (innerAsyncResult != null)
                {
                    // we're just waiting for the inner result to complete
                    return(innerAsyncResult);
                }
                else
                {
                    // something was short-circuited and the action was not called, so this was a synchronous operation
                    SimpleAsyncResult newAsyncResult = new SimpleAsyncResult(asyncState);
                    newAsyncResult.MarkCompleted(true /* completedSynchronously */, asyncCallback);
                    return(newAsyncResult);
                }
            };

            EndInvokeDelegate <ActionExecutedContext> endDelegate = delegate(IAsyncResult asyncResult)
            {
                return(endContinuation());
            };

            return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _invokeActionMethodWithFiltersTag));
        }
예제 #7
0
        public virtual IAsyncResult BeginInvokeAction(ControllerContext controllerContext, string actionName, AsyncCallback callback, object state)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (String.IsNullOrEmpty(actionName))
            {
                throw Error.ParameterCannotBeNullOrEmpty("actionName");
            }

            ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
            ActionDescriptor     actionDescriptor     = controllerDescriptor.FindAction(controllerContext, actionName);

            if (actionDescriptor != null)
            {
                FilterInfo filterInfo   = GetFilters(controllerContext, actionDescriptor);
                Action     continuation = null;

                BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) {
                    try {
                        AuthorizationContext authContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
                        if (authContext.Result != null)
                        {
                            // the auth filter signaled that we should let it short-circuit the request
                            continuation = () => InvokeActionResult(controllerContext, authContext.Result);
                        }
                        else
                        {
                            if (controllerContext.Controller.ValidateRequest)
                            {
                                ValidateRequest(controllerContext);
                            }

                            IDictionary <string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
                            IAsyncResult asyncResult = BeginInvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters, asyncCallback, asyncState);
                            continuation = () => {
                                ActionExecutedContext postActionContext = EndInvokeActionMethodWithFilters(asyncResult);
                                InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters, postActionContext.Result);
                            };
                            return(asyncResult);
                        }
                    }
                    catch (ThreadAbortException) {
                        // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
                        // the filters don't see this as an error.
                        throw;
                    }
                    catch (Exception ex) {
                        // something blew up, so execute the exception filters
                        ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
                        if (!exceptionContext.ExceptionHandled)
                        {
                            throw;
                        }

                        continuation = () => InvokeActionResult(controllerContext, exceptionContext.Result);
                    }

                    return(BeginInvokeAction_MakeSynchronousAsyncResult(asyncCallback, asyncState));
                };

                EndInvokeDelegate <bool> endDelegate = delegate(IAsyncResult asyncResult) {
                    try {
                        continuation();
                    }
                    catch (ThreadAbortException) {
                        // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
                        // the filters don't see this as an error.
                        throw;
                    }
                    catch (Exception ex) {
                        // something blew up, so execute the exception filters
                        ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
                        if (!exceptionContext.ExceptionHandled)
                        {
                            throw;
                        }
                        InvokeActionResult(controllerContext, exceptionContext.Result);
                    }

                    return(true);
                };

                return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _invokeActionTag));
            }
            else
            {
                // Notify the controller that no action was found.
                return(BeginInvokeAction_ActionNotFound(callback, state));
            }
        }
예제 #8
0
        public virtual IAsyncResult BeginInvokeAction(ControllerContext controllerContext, string actionName, AsyncCallback callback, object state)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            if (String.IsNullOrEmpty(actionName))
            {
                throw Error.ParameterCannotBeNullOrEmpty("actionName");
            }

            ControllerDescriptor controllerDescriptor = GetControllerDescriptor(controllerContext);
            ActionDescriptor     actionDescriptor     = FindAction(controllerContext, controllerDescriptor, actionName);

            if (actionDescriptor != null)
            {
                FilterInfo filterInfo   = GetFilters(controllerContext, actionDescriptor);
                Action     continuation = null;

                BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState)
                {
                    try
                    {
                        AuthenticationContext authenticationContext = InvokeAuthenticationFilters(controllerContext,
                                                                                                  filterInfo.AuthenticationFilters, actionDescriptor);

                        if (authenticationContext.Result != null)
                        {
                            // An authentication filter signaled that we should short-circuit the request. Let all
                            // authentication filters contribute to an action result (to combine authentication
                            // challenges). Then, run this action result.
                            AuthenticationChallengeContext challengeContext =
                                InvokeAuthenticationFiltersChallenge(controllerContext,
                                                                     filterInfo.AuthenticationFilters, actionDescriptor, authenticationContext.Result);
                            continuation = () => InvokeActionResult(controllerContext,
                                                                    challengeContext.Result ?? authenticationContext.Result);
                        }
                        else
                        {
                            IPrincipal principal = authenticationContext.Principal;

                            if (principal != null)
                            {
                                Thread.CurrentPrincipal  = principal;
                                HttpContext.Current.User = principal;
                            }

                            AuthorizationContext authorizationContext = InvokeAuthorizationFilters(controllerContext, filterInfo.AuthorizationFilters, actionDescriptor);
                            if (authorizationContext.Result != null)
                            {
                                // An authorization filter signaled that we should short-circuit the request. Let all
                                // authentication filters contribute to an action result (to combine authentication
                                // challenges). Then, run this action result.
                                AuthenticationChallengeContext challengeContext =
                                    InvokeAuthenticationFiltersChallenge(controllerContext,
                                                                         filterInfo.AuthenticationFilters, actionDescriptor, authorizationContext.Result);
                                continuation = () => InvokeActionResult(controllerContext, challengeContext.Result ??
                                                                        authorizationContext.Result);
                            }
                            else
                            {
                                if (controllerContext.Controller.ValidateRequest)
                                {
                                    ValidateRequest(controllerContext);
                                }

                                IDictionary <string, object> parameters = GetParameterValues(controllerContext, actionDescriptor);
                                IAsyncResult asyncResult = BeginInvokeActionMethodWithFilters(controllerContext, filterInfo.ActionFilters, actionDescriptor, parameters, asyncCallback, asyncState);
                                continuation = () =>
                                {
                                    ActionExecutedContext postActionContext = EndInvokeActionMethodWithFilters(asyncResult);
                                    // The action succeeded. Let all authentication filters contribute to an action
                                    // result (to combine authentication challenges; some authentication filters need
                                    // to do negotiation even on a successful result). Then, run this action result.
                                    AuthenticationChallengeContext challengeContext =
                                        InvokeAuthenticationFiltersChallenge(controllerContext,
                                                                             filterInfo.AuthenticationFilters, actionDescriptor,
                                                                             postActionContext.Result);
                                    InvokeActionResultWithFilters(controllerContext, filterInfo.ResultFilters,
                                                                  challengeContext.Result ?? postActionContext.Result);
                                };
                                return(asyncResult);
                            }
                        }
                    }
                    catch (ThreadAbortException)
                    {
                        // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
                        // the filters don't see this as an error.
                        throw;
                    }
                    catch (Exception ex)
                    {
                        // something blew up, so execute the exception filters
                        ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
                        if (!exceptionContext.ExceptionHandled)
                        {
                            throw;
                        }

                        continuation = () => InvokeActionResult(controllerContext, exceptionContext.Result);
                    }

                    return(BeginInvokeAction_MakeSynchronousAsyncResult(asyncCallback, asyncState));
                };

                EndInvokeDelegate <bool> endDelegate = delegate(IAsyncResult asyncResult)
                {
                    try
                    {
                        continuation();
                    }
                    catch (ThreadAbortException)
                    {
                        // This type of exception occurs as a result of Response.Redirect(), but we special-case so that
                        // the filters don't see this as an error.
                        throw;
                    }
                    catch (Exception ex)
                    {
                        // something blew up, so execute the exception filters
                        ExceptionContext exceptionContext = InvokeExceptionFilters(controllerContext, filterInfo.ExceptionFilters, ex);
                        if (!exceptionContext.ExceptionHandled)
                        {
                            throw;
                        }
                        InvokeActionResult(controllerContext, exceptionContext.Result);
                    }

                    return(true);
                };

                return(AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _invokeActionTag));
            }
            else
            {
                // Notify the controller that no action was found.
                return(BeginInvokeAction_ActionNotFound(callback, state));
            }
        }