Example #1
0
        public void InvokeAction_ThrowsOnActionExecutingException_Handled()
        {
            var actionLog    = new List <string>();
            var actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext =>
                {
                    actionLog.Add("OnActionExecuting");
                },
                OnActionExecutedImpl = filterContext =>
                {
                    actionLog.Add("OnActionExecuted");
                    Assert.Equal("Some exception text.", filterContext.Exception.Message);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result           = new LoggingActionResult("Handled Exception");
                }
            };

            GlobalFilters.Filters.Add(actionFilter);
            var controllerContext = GetControllerContext();

            var retVal = InvokeAction(controllerContext, nameof(TestController.ActionThrowsExceptionAndIsNotHandled), null, null);

            Assert.True(retVal);
            Assert.Equal(new[] {
                "OnActionExecuting",
                "OnActionExecuted"
            }, actionLog.ToArray());
            Assert.Equal("Handled Exception", ((TestController)controllerContext.Controller).Log);
        }
Example #2
0
        public void InvokeAction_ThrowsOnActionExecutingException_NotHandled()
        {
            var actionLog    = new List <string>();
            var actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext =>
                {
                    actionLog.Add("OnActionExecuting1");
                },
                OnActionExecutedImpl = filterContext =>
                {
                    actionLog.Add("OnActionExecuted1");
                }
            };

            GlobalFilters.Filters.Add(actionFilter);
            var controllerContext = GetControllerContext();

            AssertEx.Throws <Exception>(() =>
            {
                var retVal = InvokeAction(controllerContext, nameof(TestController.ActionThrowsExceptionAndIsNotHandled), null, null);
            }, "Some exception text.");

            Assert.Equal(new[] {
                "OnActionExecuting1",
                "OnActionExecuted1"
            }, actionLog.ToArray());
        }
Example #3
0
        public void BeginInvokeActionMethodWithFilters_EndExecuteThrowsOnActionExecutedException_ThreadAbort()
        {
            // Arrange
            bool             onActionExecutedWasCalled = false;
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutedImpl = filterContext =>
                {
                    onActionExecutedWasCalled = true;
                    Thread.ResetAbort();
                }
            };
            Func <ActionResult> action = delegate
            {
                Thread.CurrentThread.Abort();
                return(null);
            };

            // Act & assert
            Assert.Throws <ThreadAbortException>(
                delegate { BeingInvokeActionMethodWithFiltersEndTester(action, actionFilter); });

            // Assert
            Assert.True(onActionExecutedWasCalled);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutedException_Handled()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled      = false;
            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext   = GetActionExecutingContext();
            ActionFilterImpl       actionFilter = new ActionFilterImpl()
            {
                OnActionExecutedImpl = filterContext => {
                    onActionExecutedWasCalled = true;
                    Assert.IsNotNull(filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result           = expectedResult;
                }
            };

            // Act & assert pre-execution
            Func <ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                                                                                                                            () => () => {
                nextInChainWasCalled = true;
                throw new Exception("Some exception text.");
            });

            Assert.IsFalse(onActionExecutedWasCalled, "OnActionExecuted() shouldn't have been called yet.");

            // Act & assert post-execution
            ActionExecutedContext postContext = continuation();

            Assert.IsTrue(nextInChainWasCalled, "Next in chain should've been called.");
            Assert.IsTrue(onActionExecutedWasCalled, "OnActionExecuted() should've been called.");
            Assert.AreEqual(expectedResult, postContext.Result);
        }
Example #5
0
        public void BeginInvokeActionMethodWithFilters_EndExecuteThrowsOnActionExecutedException_Handled()
        {
            // Arrange
            ViewResult       expectedResult         = new ViewResult();
            Exception        exepctedException      = new Exception("Some exception message.");
            bool             actionCalled           = false;
            bool             onActionExecutedCalled = false;
            ActionFilterImpl actionFilter           = new ActionFilterImpl()
            {
                OnActionExecutedImpl = (filterContext) =>
                {
                    onActionExecutedCalled = true;
                    Assert.Same(exepctedException, filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result           = expectedResult;
                }
            };
            Func <ActionResult> action = () =>
            {
                actionCalled = true;
                throw exepctedException;
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersEndTester(action, actionFilter);

            // Assert
            Assert.True(actionCalled);
            Assert.True(onActionExecutedCalled);
            Assert.Equal(expectedResult, result);
        }
Example #6
0
        public void BeginInvokeActionMethodWithFilters_BeginExecuteThrowsOnActionExecutingException_NotHandled()
        {
            // Arrange
            string           expectedExceptionText      = "Some exception text.";
            Exception        expectedException          = new Exception(expectedExceptionText);
            bool             onActionExecutingWasCalled = false;
            bool             onActionExecutedWasCalled  = false;
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl  = filterContext => { onActionExecutedWasCalled = true; }
            };
            Func <IAsyncResult> beginExecute = delegate
            {
                throw expectedException;
            };

            // Act & assert
            Assert.Throws <Exception>(
                delegate
            {
                BeingInvokeActionMethodWithFiltersBeginTester(beginExecute, actionFilter);
            },
                expectedExceptionText);

            // Assert
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
        }
Example #7
0
        public void BeginInvokeActionMethodWithFilters_EndExecuteThrowsOnActionExecutedException_HandledByLater()
        {
            // Arrange
            List <string>       actionLog      = new List <string>();
            Exception           exception      = new Exception("Some exception message.");
            ActionResult        expectedResult = new ViewResult();
            Func <ActionResult> action         = delegate
            {
                actionLog.Add("EndExecute");
                throw exception;
            };
            ActionFilterImpl filter1 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting1"); },
                OnActionExecutedImpl  = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted1"); }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting2"); },
                OnActionExecutedImpl  = delegate(ActionExecutedContext filterContext)
                {
                    actionLog.Add("OnActionExecuted2");
                    Assert.Same(exception, filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result           = expectedResult;
                }
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersEndTester(action, filter1, filter2);

            // Assert
            Assert.Equal(new[] { "OnActionExecuting1", "OnActionExecuting2", "EndExecute", "OnActionExecuted2", "OnActionExecuted1" }, actionLog.ToArray());
            Assert.Equal(expectedResult, result);
        }
Example #8
0
        public void BeginInvokeActionMethodWithFilters_BeginExecuteThrowsOnActionExecutingException_Handled()
        {
            // Arrange
            ActionResult     expectedResult             = new ViewResult();
            Exception        expectedException          = new Exception("Some exception text.");
            bool             onActionExecutingWasCalled = false;
            bool             onActionExecutedWasCalled  = false;
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl  = filterContext =>
                {
                    onActionExecutedWasCalled = true;
                    Assert.Same(expectedException, filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result           = expectedResult;
                }
            };
            Func <IAsyncResult> beginExecute = delegate
            {
                throw expectedException;
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersBeginTester(beginExecute, actionFilter);

            // Assert
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
            Assert.Equal(expectedResult, result);
        }
Example #9
0
        public void BeginInvokeActionMethodWithFilters_OnActionExecutingSetsResult()
        {
            // Arrange
            ActionResult     expectedResult             = new ViewResult();
            ActionResult     overriddenResult           = new ViewResult();
            bool             onActionExecutingWasCalled = false;
            bool             onActionExecutedWasCalled  = false;
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext =>
                {
                    onActionExecutingWasCalled = true;
                    filterContext.Result       = expectedResult;
                },
                OnActionExecutedImpl = _ => { onActionExecutedWasCalled = true; }
            };
            Func <ActionResult> endExecute = delegate
            {
                return(overriddenResult);
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersTester(() => new MockAsyncResult(), endExecute, checkBegin: false, checkEnd: false, filters: new IActionFilter[] { actionFilter });

            // Assert
            Assert.True(onActionExecutingWasCalled);
            Assert.False(onActionExecutedWasCalled);
            Assert.Equal(expectedResult, result);
        }
        public void InvokeActionMethodFilterAsynchronously_NormalExecutionNotCanceled()
        {
            // Arrange
            bool nextInChainWasCalled       = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled  = false;

            ActionExecutingContext preContext   = GetActionExecutingContext();
            ActionFilterImpl       actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = _ => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl  = _ => { onActionExecutedWasCalled = true; }
            };

            // Act
            Func <ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                                                                                                                            () => {
                nextInChainWasCalled = true;
                return(() => new ActionExecutedContext());
            });

            // Assert
            Assert.IsTrue(nextInChainWasCalled);
            Assert.IsTrue(onActionExecutingWasCalled, "OnActionExecuting() should've been called by the first invocation.");
            Assert.IsFalse(onActionExecutedWasCalled, "OnActionExecuted() shouldn't have been called by the first invocation.");

            continuation();
            Assert.IsTrue(onActionExecutedWasCalled, "OnActionExecuted() should've been called by the second invocation.");
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutingException_NotHandled()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled       = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled  = false;

            ActionExecutingContext preContext   = GetActionExecutingContext();
            ActionFilterImpl       actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl  = filterContext => { onActionExecutedWasCalled = true; }
            };

            // Act & assert
            Assert.Throws <Exception>(
                delegate
            {
                AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(
                    actionFilter, preContext,
                    () =>
                {
                    nextInChainWasCalled = true;
                    throw new Exception("Some exception text.");
                });
            },
                @"Some exception text.");

            // Assert
            Assert.True(nextInChainWasCalled);
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
        }
Example #12
0
        public void BeginInvokeActionMethodWithFilters_ShortCircuited()
        {
            // Arrange
            List <string>    actionLog          = new List <string>();
            ActionResult     shortCircuitResult = new ViewResult();
            ActionResult     executeResult      = new ViewResult();
            ActionFilterImpl filter1            = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting1"); },
                OnActionExecutedImpl  = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted1"); }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext)
                {
                    actionLog.Add("OnActionExecuting2");
                    filterContext.Result = shortCircuitResult;
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted2"); }
            };
            Func <ActionResult> endExecute = () =>
            {
                actionLog.Add("ExecuteCalled");
                return(executeResult);
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersTester(() => new MockAsyncResult(), endExecute, checkBegin: false, checkEnd: false, filters: new IActionFilter[] { filter1, filter2 });

            // Assert
            Assert.Equal(new[] { "OnActionExecuting1", "OnActionExecuting2", "OnActionExecuted1" }, actionLog.ToArray());
            Assert.Equal(shortCircuitResult, result);
        }
Example #13
0
        public void BeginInvokeActionMethodWithFilters_FiltersOrderedCorrectly()
        {
            // Arrange
            List <string>       actionLog    = new List <string>();
            ActionResult        actionResult = new ViewResult();
            Func <ActionResult> continuation = delegate
            {
                actionLog.Add("Continuation");
                return(actionResult);
            };
            ActionFilterImpl filter1 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting1"); },
                OnActionExecutedImpl  = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted1"); }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting2"); },
                OnActionExecutedImpl  = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted2"); }
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersEndTester(continuation, filter1, filter2);

            // Assert
            Assert.Equal(new[] { "OnActionExecuting1", "OnActionExecuting2", "Continuation", "OnActionExecuted2", "OnActionExecuted1" }, actionLog.ToArray());
            Assert.Equal(actionResult, result);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutedException_ThreadAbort()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext   = GetActionExecutingContext();
            ActionFilterImpl       actionFilter = new ActionFilterImpl()
            {
                OnActionExecutedImpl = filterContext => {
                    onActionExecutedWasCalled = true;
                    Thread.ResetAbort();
                }
            };

            // Act & assert
            Func <ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                                                                                                                            () => () => {
                Thread.CurrentThread.Abort();
                return(null);
            });

            ExceptionHelper.ExpectException <ThreadAbortException>(
                delegate {
                continuation();
            });

            // Assert
            Assert.IsTrue(onActionExecutedWasCalled, "OnActionExecuted() should've been called.");
        }
        public void InvokeActionMethodWithFilters_ShortCircuited()
        {
            // Arrange
            List <string>               actionLog         = new List <string>();
            ControllerContext           controllerContext = new ControllerContext();
            Dictionary <string, object> parameters        = new Dictionary <string, object>();
            ActionResult actionResult = new ViewResult();

            ActionFilterImpl filter1 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    actionLog.Add("OnActionExecuting1");
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    actionLog.Add("OnActionExecuted1");
                }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    actionLog.Add("OnActionExecuting2");
                    filterContext.Result = actionResult;
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    actionLog.Add("OnActionExecuted2");
                }
            };

            Mock <AsyncActionDescriptor> mockActionDescriptor = new Mock <AsyncActionDescriptor>();

            mockActionDescriptor.Expect(d => d.BeginExecute(controllerContext, parameters, It.IsAny <AsyncCallback>(), It.IsAny <object>())).Throws(new Exception("I shouldn't have been called."));
            mockActionDescriptor.Expect(d => d.EndExecute(It.IsAny <IAsyncResult>())).Throws(new Exception("I shouldn't have been called."));

            AsyncControllerActionInvoker invoker = new AsyncControllerActionInvoker();

            IActionFilter[] filters = new IActionFilter[] { filter1, filter2 };

            // Act
            IAsyncResult          outerAsyncResult = invoker.BeginInvokeActionMethodWithFilters(controllerContext, filters, mockActionDescriptor.Object, parameters, null, null);
            ActionExecutedContext postContext      = invoker.EndInvokeActionMethodWithFilters(outerAsyncResult);

            // Assert
            CollectionAssert.AreEqual(
                new string[] { "OnActionExecuting1", "OnActionExecuting2", "OnActionExecuted1" },
                actionLog);
            Assert.AreEqual(actionResult, postContext.Result);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutingException_Handled()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled       = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled  = false;

            ActionExecutingContext preContext   = GetActionExecutingContext();
            ActionFilterImpl       actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl  = filterContext =>
                {
                    onActionExecutedWasCalled = true;
                    Assert.NotNull(filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result           = expectedResult;
                }
            };

            // Act
            Func <ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(
                actionFilter, preContext,
                () =>
            {
                nextInChainWasCalled = true;
                throw new Exception("Some exception text.");
            });

            // Assert
            Assert.True(nextInChainWasCalled);
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);

            ActionExecutedContext postContext = continuation();

            Assert.Equal(expectedResult, postContext.Result);
        }
        public void InvokeActionMethodFilterAsynchronously_OnActionExecutingSetsResult()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled       = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled  = false;

            ActionExecutingContext preContext   = GetActionExecutingContext();
            ActionFilterImpl       actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext =>
                {
                    onActionExecutingWasCalled = true;
                    filterContext.Result       = expectedResult;
                },
                OnActionExecutedImpl = _ => { onActionExecutedWasCalled = true; }
            };

            // Act
            Func <ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(
                actionFilter, preContext,
                () =>
            {
                nextInChainWasCalled = true;
                return(() => new ActionExecutedContext());
            });

            // Assert
            Assert.False(nextInChainWasCalled);
            Assert.True(onActionExecutingWasCalled);
            Assert.False(onActionExecutedWasCalled);

            ActionExecutedContext postContext = continuation();

            Assert.False(onActionExecutedWasCalled);
            Assert.Equal(expectedResult, postContext.Result);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutingException_ThreadAbort()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled       = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled  = false;

            ActionExecutingContext preContext   = GetActionExecutingContext();
            ActionFilterImpl       actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl  = filterContext =>
                {
                    onActionExecutedWasCalled = true;
                    Thread.ResetAbort();
                }
            };

            // Act & assert
            Assert.Throws <ThreadAbortException>(
                delegate
            {
                AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(
                    actionFilter, preContext,
                    () =>
                {
                    nextInChainWasCalled = true;
                    Thread.CurrentThread.Abort();
                    return(null);
                });
            });

            // Assert
            Assert.True(nextInChainWasCalled);
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
        }
Example #19
0
        public void BeginInvokeActionMethodWithFilters_EndExecuteThrowsOnActionExecutedException_NotHandled()
        {
            // Arrange
            bool             onActionExecutedWasCalled = false;
            string           expectedExceptionText     = "Some exception text.";
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutedImpl = filterContext => { onActionExecutedWasCalled = true; }
            };
            Func <ActionResult> action = delegate
            {
                throw new Exception(expectedExceptionText);
            };

            // Act & assert
            Assert.Throws <Exception>(
                () => { BeingInvokeActionMethodWithFiltersEndTester(action, actionFilter); },
                expectedExceptionText);

            // Assert
            Assert.True(onActionExecutedWasCalled);
        }
Example #20
0
        public void BeginInvokeActionMethodWithFilters_NormalExecutionNotCanceled()
        {
            // Arrange
            bool             onActionExecutingWasCalled = false;
            bool             onActionExecutedWasCalled  = false;
            MockAsyncResult  innerAsyncResult           = new MockAsyncResult();
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = _ => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl  = _ => { onActionExecutedWasCalled = true; }
            };
            Func <IAsyncResult> beginExecute = delegate
            {
                return(innerAsyncResult);
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersBeginTester(beginExecute, actionFilter);

            // Assert
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
        }
        public void InvokeActionMethodWithFilters()
        {
            // Arrange
            List <string>               actionLog         = new List <string>();
            ControllerContext           controllerContext = new ControllerContext();
            Dictionary <string, object> parameters        = new Dictionary <string, object>();
            MockAsyncResult             innerAsyncResult  = new MockAsyncResult();
            ActionResult actionResult = new ViewResult();

            ActionFilterImpl filter1 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting1"); },
                OnActionExecutedImpl  = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted1"); }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting2"); },
                OnActionExecutedImpl  = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted2"); }
            };

            Mock <AsyncActionDescriptor> mockActionDescriptor = new Mock <AsyncActionDescriptor>();

            mockActionDescriptor.Setup(d => d.BeginExecute(controllerContext, parameters, It.IsAny <AsyncCallback>(), It.IsAny <object>())).Returns(innerAsyncResult);
            mockActionDescriptor.Setup(d => d.EndExecute(innerAsyncResult)).Returns(actionResult);

            AsyncControllerActionInvoker invoker = new AsyncControllerActionInvoker();

            IActionFilter[] filters = new IActionFilter[] { filter1, filter2 };

            // Act
            IAsyncResult          outerAsyncResult = invoker.BeginInvokeActionMethodWithFilters(controllerContext, filters, mockActionDescriptor.Object, parameters, null, null);
            ActionExecutedContext postContext      = invoker.EndInvokeActionMethodWithFilters(outerAsyncResult);

            // Assert
            Assert.Equal(new[] { "OnActionExecuting1", "OnActionExecuting2", "OnActionExecuted2", "OnActionExecuted1" }, actionLog.ToArray());
            Assert.Equal(actionResult, postContext.Result);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutingException_ThreadAbort()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled       = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled  = false;

            ActionExecutingContext preContext   = GetActionExecutingContext();
            ActionFilterImpl       actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => {
                    onActionExecutingWasCalled = true;
                },
                OnActionExecutedImpl = filterContext => {
                    onActionExecutedWasCalled = true;
                    Thread.ResetAbort();
                }
            };

            // Act & assert
            ExceptionHelper.ExpectException <ThreadAbortException>(
                delegate {
                AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                                                                                    () => {
                    nextInChainWasCalled = true;
                    Thread.CurrentThread.Abort();
                    return(null);
                });
            });

            // Assert
            Assert.IsTrue(nextInChainWasCalled, "Next in chain should've been called.");
            Assert.IsTrue(onActionExecutingWasCalled, "OnActionExecuting() should've been called by the first invocation.");
            Assert.IsTrue(onActionExecutedWasCalled, "OnActionExecuted() should've been called due to exception handling.");
        }
        public void InvokeActionMethodFilterAsynchronously_OnActionExecutingSetsResult()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled       = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled  = false;

            ActionExecutingContext preContext   = GetActionExecutingContext();
            ActionFilterImpl       actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => {
                    onActionExecutingWasCalled = true;
                    filterContext.Result       = expectedResult;
                },
                OnActionExecutedImpl = _ => { onActionExecutedWasCalled = true; }
            };

            // Act
            Func <ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                                                                                                                            () => {
                nextInChainWasCalled = true;
                return(() => new ActionExecutedContext());
            });

            // Assert
            Assert.IsFalse(nextInChainWasCalled, "Next in chain shouldn't have been called due to short circuiting.");
            Assert.IsTrue(onActionExecutingWasCalled, "OnActionExecuting() should've been called by the first invocation.");
            Assert.IsFalse(onActionExecutedWasCalled, "OnActionExecuted() shouldn't have been called by the first invocation.");

            ActionExecutedContext postContext = continuation();

            Assert.IsFalse(onActionExecutedWasCalled, "OnActionExecuted() shouldn't have been called by the second invocation.");
            Assert.AreEqual(expectedResult, postContext.Result);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutingException_ThreadAbort() {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext = GetActionExecutingContext();
            ActionFilterImpl actionFilter = new ActionFilterImpl() {
                OnActionExecutingImpl = filterContext => {
                    onActionExecutingWasCalled = true;
                },
                OnActionExecutedImpl = filterContext => {
                    onActionExecutedWasCalled = true;
                    Thread.ResetAbort();
                }
            };

            // Act & assert
            ExceptionHelper.ExpectException<ThreadAbortException>(
                delegate {
                    AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                        () => {
                            nextInChainWasCalled = true;
                            Thread.CurrentThread.Abort();
                            return null;
                        });
                });

            // Assert
            Assert.IsTrue(nextInChainWasCalled, "Next in chain should've been called.");
            Assert.IsTrue(onActionExecutingWasCalled, "OnActionExecuting() should've been called by the first invocation.");
            Assert.IsTrue(onActionExecutedWasCalled, "OnActionExecuted() should've been called due to exception handling.");
        }
        public void InvokeActionMethodFilterAsynchronously_NormalExecutionNotCanceled() {
            // Arrange
            bool nextInChainWasCalled = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext = GetActionExecutingContext();
            ActionFilterImpl actionFilter = new ActionFilterImpl() {
                OnActionExecutingImpl = _ => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl = _ => { onActionExecutedWasCalled = true; }
            };

            // Act
            Func<ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                () => {
                    nextInChainWasCalled = true;
                    return () => new ActionExecutedContext();
                });

            // Assert
            Assert.IsTrue(nextInChainWasCalled);
            Assert.IsTrue(onActionExecutingWasCalled, "OnActionExecuting() should've been called by the first invocation.");
            Assert.IsFalse(onActionExecutedWasCalled, "OnActionExecuted() shouldn't have been called by the first invocation.");

            continuation();
            Assert.IsTrue(onActionExecutedWasCalled, "OnActionExecuted() should've been called by the second invocation.");
        }
        public void BeginInvokeActionMethodWithFilters_NormalExecutionNotCanceled()
        {
            // Arrange
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;
            MockAsyncResult innerAsyncResult = new MockAsyncResult();
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = _ => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl = _ => { onActionExecutedWasCalled = true; }
            };
            Func<IAsyncResult> beginExecute = delegate
            {
                return innerAsyncResult;
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersBeginTester(beginExecute, actionFilter);

            // Assert
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
        }
        public void BeginInvokeActionMethodWithFilters_FiltersOrderedCorrectly()
        {
            // Arrange
            List<string> actionLog = new List<string>();
            ActionResult actionResult = new ViewResult();
            Func<ActionResult> continuation = delegate
            {
                actionLog.Add("Continuation");
                return actionResult;

            };
            ActionFilterImpl filter1 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting1"); },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted1"); }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting2"); },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted2"); }
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersEndTester(continuation, filter1, filter2);

            // Assert
            Assert.Equal(new[] { "OnActionExecuting1", "OnActionExecuting2", "Continuation", "OnActionExecuted2", "OnActionExecuted1" }, actionLog.ToArray());
            Assert.Equal(actionResult, result);
        }
        public void BeginInvokeActionMethodWithFilters_EndExecuteThrowsOnActionExecutedException_Handled()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();
            Exception exepctedException = new Exception("Some exception message.");
            bool actionCalled = false;
            bool onActionExecutedCalled = false;
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutedImpl = (filterContext) =>
                {
                    onActionExecutedCalled = true;
                    Assert.Same(exepctedException, filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result = expectedResult;
                }
            };
            Func<ActionResult> action = () =>
            {
                actionCalled = true;
                throw exepctedException;
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersEndTester(action, actionFilter);

            // Assert
            Assert.True(actionCalled);
            Assert.True(onActionExecutedCalled);
            Assert.Equal(expectedResult, result);
        }
        public void BeginInvokeActionMethodWithFilters_EndExecuteThrowsOnActionExecutedException_NotHandled()
        {
            // Arrange
            bool onActionExecutedWasCalled = false;
            string expectedExceptionText = "Some exception text.";
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutedImpl = filterContext => { onActionExecutedWasCalled = true; }
            };
            Func<ActionResult> action = delegate
            {
                throw new Exception(expectedExceptionText);
            };

            // Act & assert
            Assert.Throws<Exception>(
                () => { BeingInvokeActionMethodWithFiltersEndTester(action, actionFilter); },
                expectedExceptionText);

            // Assert
            Assert.True(onActionExecutedWasCalled);
        }
        public void InvokeActionMethodFilterAsynchronously_OnActionExecutingSetsResult()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext = GetActionExecutingContext();
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext =>
                {
                    onActionExecutingWasCalled = true;
                    filterContext.Result = expectedResult;
                },
                OnActionExecutedImpl = _ => { onActionExecutedWasCalled = true; }
            };

            // Act
            Func<ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(
                actionFilter, preContext,
                () =>
                {
                    nextInChainWasCalled = true;
                    return () => new ActionExecutedContext();
                });

            // Assert
            Assert.False(nextInChainWasCalled);
            Assert.True(onActionExecutingWasCalled);
            Assert.False(onActionExecutedWasCalled);

            ActionExecutedContext postContext = continuation();
            Assert.False(onActionExecutedWasCalled);
            Assert.Equal(expectedResult, postContext.Result);
        }
        public void BeginInvokeActionMethodWithFilters_BeginExecuteThrowsOnActionExecutingException_Handled()
        {
            // Arrange
            ActionResult expectedResult = new ViewResult();
            Exception expectedException = new Exception("Some exception text.");
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl = filterContext =>
                {
                    onActionExecutedWasCalled = true;
                    Assert.Same(expectedException, filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result = expectedResult;
                }
            };
            Func<IAsyncResult> beginExecute = delegate
            {
                throw expectedException;
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersBeginTester(beginExecute, actionFilter);

            // Assert
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
            Assert.Equal(expectedResult, result);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutingException_NotHandled()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext = GetActionExecutingContext();
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl = filterContext => { onActionExecutedWasCalled = true; }
            };

            // Act & assert
            Assert.Throws<Exception>(
                delegate
                {
                    AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(
                        actionFilter, preContext,
                        () =>
                        {
                            nextInChainWasCalled = true;
                            throw new Exception("Some exception text.");
                        });
                },
                @"Some exception text.");

            // Assert
            Assert.True(nextInChainWasCalled);
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutingException_ThreadAbort()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext = GetActionExecutingContext();
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl = filterContext =>
                {
                    onActionExecutedWasCalled = true;
                    Thread.ResetAbort();
                }
            };

            // Act & assert
            Assert.Throws<ThreadAbortException>(
                delegate
                {
                    AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(
                        actionFilter, preContext,
                        () =>
                        {
                            nextInChainWasCalled = true;
                            Thread.CurrentThread.Abort();
                            return null;
                        });
                });

            // Assert
            Assert.True(nextInChainWasCalled);
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutedException_Handled()
        {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled = false;
            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext = GetActionExecutingContext();
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutedImpl = filterContext =>
                {
                    onActionExecutedWasCalled = true;
                    Assert.NotNull(filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result = expectedResult;
                }
            };

            // Act & assert pre-execution
            Func<ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(
                actionFilter, preContext,
                () => () =>
                {
                    nextInChainWasCalled = true;
                    throw new Exception("Some exception text.");
                });

            Assert.False(onActionExecutedWasCalled);

            // Act & assert post-execution
            ActionExecutedContext postContext = continuation();

            Assert.True(nextInChainWasCalled);
            Assert.True(onActionExecutedWasCalled);
            Assert.Equal(expectedResult, postContext.Result);
        }
        public void InvokeActionMethodFilterWithNormalControlFlow() {
            // Arrange
            List<string> actions = new List<string>();
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            ActionDescriptor action = new Mock<ActionDescriptor>().Object;
            MockAsyncResult asyncResult = new MockAsyncResult();
            object state = new object();

            ActionExecutingContext preContext = new Mock<ActionExecutingContext>().Object;
            ActionExecutedContext postContext = new Mock<ActionExecutedContext>().Object;

            ActionFilterImpl filter = new ActionFilterImpl() {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    Assert.AreEqual(preContext, filterContext);
                    Assert.IsNull(filterContext.Result);
                    actions.Add("OnActionExecuting");
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    Assert.AreEqual(postContext, filterContext);
                    actions.Add("OnActionExecuted");
                }
            };

            BeginInvokeCallback beginContinuation = (innerCallback, innerState) => {
                actions.Add("BeginContinuation");
                return asyncResult;
            };

            AsyncCallback<ActionExecutedContext> endContinuation = ar => {
                Assert.AreEqual(asyncResult, ar);
                actions.Add("EndContinuation");
                return postContext;
            };

            // Act
            IAsyncResult returnedAsyncResult = AsyncControllerActionInvoker.BeginInvokeActionMethodFilter(filter, preContext, beginContinuation, endContinuation, null, state);
            ActionExecutedContext returnedPostContext = AsyncControllerActionInvoker.EndInvokeActionMethodFilter(returnedAsyncResult);

            // Assert
            Assert.AreEqual(4, actions.Count);
            Assert.AreEqual("OnActionExecuting", actions[0]);
            Assert.AreEqual("BeginContinuation", actions[1]);
            Assert.AreEqual("EndContinuation", actions[2]);
            Assert.AreEqual("OnActionExecuted", actions[3]);

            Assert.AreEqual(state, returnedAsyncResult.AsyncState);
            Assert.AreEqual(postContext, returnedPostContext);
        }
        public void InvokeActionMethodFilterWhereEndContinuationThrowsExceptionAndIsNotHandled() {
            // Arrange
            List<string> actions = new List<string>();
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            Exception exception = new Exception();
            ActionExecutingContext preContext = GetEmptyActionExecutingContext();
            MockAsyncResult asyncResult = new MockAsyncResult();

            ActionFilterImpl filter = new ActionFilterImpl() {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    actions.Add("OnActionExecuting");
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    actions.Add("OnActionExecuted");
                    Assert.AreEqual(exception, filterContext.Exception, "Exception did not match.");
                    Assert.AreEqual(preContext.ActionDescriptor, filterContext.ActionDescriptor, "Descriptor did not match.");
                    Assert.IsFalse(filterContext.ExceptionHandled);
                }
            };

            BeginInvokeCallback beginContinuation = (innerCallback, innerState) => {
                actions.Add("BeginContinuation");
                return asyncResult;
            };

            AsyncCallback<ActionExecutedContext> endContinuation = ar => {
                Assert.AreEqual(asyncResult, ar);
                actions.Add("EndContinuation");
                throw exception;
            };

            // Act
            IAsyncResult returnedResult = AsyncControllerActionInvoker.BeginInvokeActionMethodFilter(filter, preContext, beginContinuation, endContinuation, null, null);
            Exception thrownException = ExceptionHelper.ExpectException<Exception>(
                delegate {
                    AsyncControllerActionInvoker.EndInvokeActionMethodFilter(returnedResult);
                });

            // Assert
            Assert.AreEqual(4, actions.Count);
            Assert.AreEqual("OnActionExecuting", actions[0]);
            Assert.AreEqual("BeginContinuation", actions[1]);
            Assert.AreEqual("EndContinuation", actions[2]);
            Assert.AreEqual("OnActionExecuted", actions[3]);

            Assert.AreEqual(exception, thrownException);
        }
        public void InvokeActionMethodFilterAsynchronously_OnActionExecutingSetsResult() {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext = GetActionExecutingContext();
            ActionFilterImpl actionFilter = new ActionFilterImpl() {
                OnActionExecutingImpl = filterContext => {
                    onActionExecutingWasCalled = true;
                    filterContext.Result = expectedResult;
                },
                OnActionExecutedImpl = _ => { onActionExecutedWasCalled = true; }
            };

            // Act
            Func<ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                () => {
                    nextInChainWasCalled = true;
                    return () => new ActionExecutedContext();
                });

            // Assert
            Assert.IsFalse(nextInChainWasCalled, "Next in chain shouldn't have been called due to short circuiting.");
            Assert.IsTrue(onActionExecutingWasCalled, "OnActionExecuting() should've been called by the first invocation.");
            Assert.IsFalse(onActionExecutedWasCalled, "OnActionExecuted() shouldn't have been called by the first invocation.");

            ActionExecutedContext postContext = continuation();
            Assert.IsFalse(onActionExecutedWasCalled, "OnActionExecuted() shouldn't have been called by the second invocation.");
            Assert.AreEqual(expectedResult, postContext.Result);
        }
        public void InvokeActionMethodWithFilters()
        {
            // Arrange
            List<string> actionLog = new List<string>();
            ControllerContext controllerContext = new ControllerContext();
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            MockAsyncResult innerAsyncResult = new MockAsyncResult();
            ActionResult actionResult = new ViewResult();

            ActionFilterImpl filter1 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting1"); },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted1"); }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting2"); },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted2"); }
            };

            Mock<AsyncActionDescriptor> mockActionDescriptor = new Mock<AsyncActionDescriptor>();
            mockActionDescriptor.Setup(d => d.BeginExecute(controllerContext, parameters, It.IsAny<AsyncCallback>(), It.IsAny<object>())).Returns(innerAsyncResult);
            mockActionDescriptor.Setup(d => d.EndExecute(innerAsyncResult)).Returns(actionResult);

            AsyncControllerActionInvoker invoker = new AsyncControllerActionInvoker();
            IActionFilter[] filters = new IActionFilter[] { filter1, filter2 };

            // Act
            IAsyncResult outerAsyncResult = invoker.BeginInvokeActionMethodWithFilters(controllerContext, filters, mockActionDescriptor.Object, parameters, null, null);
            ActionExecutedContext postContext = invoker.EndInvokeActionMethodWithFilters(outerAsyncResult);

            // Assert
            Assert.Equal(new[] { "OnActionExecuting1", "OnActionExecuting2", "OnActionExecuted2", "OnActionExecuted1" }, actionLog.ToArray());
            Assert.Equal(actionResult, postContext.Result);
        }
        public void InvokeActionMethodWithFilters_ShortCircuited() {
            // Arrange
            List<string> actionLog = new List<string>();
            ControllerContext controllerContext = new ControllerContext();
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            ActionResult actionResult = new ViewResult();

            ActionFilterImpl filter1 = new ActionFilterImpl() {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    actionLog.Add("OnActionExecuting1");
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    actionLog.Add("OnActionExecuted1");
                }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl() {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    actionLog.Add("OnActionExecuting2");
                    filterContext.Result = actionResult;
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    actionLog.Add("OnActionExecuted2");
                }
            };

            Mock<AsyncActionDescriptor> mockActionDescriptor = new Mock<AsyncActionDescriptor>();
            mockActionDescriptor.Expect(d => d.BeginExecute(controllerContext, parameters, It.IsAny<AsyncCallback>(), It.IsAny<object>())).Throws(new Exception("I shouldn't have been called."));
            mockActionDescriptor.Expect(d => d.EndExecute(It.IsAny<IAsyncResult>())).Throws(new Exception("I shouldn't have been called."));

            AsyncControllerActionInvoker invoker = new AsyncControllerActionInvoker();
            IActionFilter[] filters = new IActionFilter[] { filter1, filter2 };

            // Act
            IAsyncResult outerAsyncResult = invoker.BeginInvokeActionMethodWithFilters(controllerContext, filters, mockActionDescriptor.Object, parameters, null, null);
            ActionExecutedContext postContext = invoker.EndInvokeActionMethodWithFilters(outerAsyncResult);

            // Assert
            CollectionAssert.AreEqual(
                new string[] { "OnActionExecuting1", "OnActionExecuting2", "OnActionExecuted1" },
                actionLog);
            Assert.AreEqual(actionResult, postContext.Result);
        }
        public void InvokeActionMethodFilterWhereOnActionExecutingCancels() {
            // Arrange
            bool wasCalled = false;
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            ActionResult actionResult = new EmptyResult();

            ActionExecutingContext preContext = GetEmptyActionExecutingContext();

            ActionFilterImpl filter = new ActionFilterImpl() {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    Assert.IsFalse(wasCalled);
                    wasCalled = true;
                    filterContext.Result = actionResult;
                },
            };

            BeginInvokeCallback beginContinuation = (innerCallback, innerState) => {
                Assert.Fail("The continuation should not be called.");
                return null;
            };

            AsyncCallback<ActionExecutedContext> endContinuation = ar => {
                Assert.Fail("The continuation should not be called.");
                return null;
            };

            // Act
            IAsyncResult asyncResult = AsyncControllerActionInvoker.BeginInvokeActionMethodFilter(filter, preContext, beginContinuation, endContinuation, null, null);
            ActionExecutedContext postContext = AsyncControllerActionInvoker.EndInvokeActionMethodFilter(asyncResult);

            // Assert
            Assert.IsTrue(wasCalled);
            Assert.IsNull(postContext.Exception);
            Assert.IsTrue(postContext.Canceled);
            Assert.AreEqual(actionResult, postContext.Result, "Result was incorrect.");
            Assert.AreEqual(preContext.ActionDescriptor, postContext.ActionDescriptor, "Descriptor was incorrect.");
        }
        public void BeginInvokeActionMethodWithFilters_BeginExecuteThrowsOnActionExecutingException_NotHandled()
        {
            // Arrange
            string expectedExceptionText = "Some exception text.";
            Exception expectedException = new Exception(expectedExceptionText);
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext => { onActionExecutingWasCalled = true; },
                OnActionExecutedImpl = filterContext => { onActionExecutedWasCalled = true; }
            };
            Func<IAsyncResult> beginExecute = delegate
            {
                throw expectedException;
            };

            // Act & assert
            Assert.Throws<Exception>(
                delegate
                {
                    BeingInvokeActionMethodWithFiltersBeginTester(beginExecute, actionFilter);
                },
                expectedExceptionText);

            // Assert
            Assert.True(onActionExecutingWasCalled);
            Assert.True(onActionExecutedWasCalled);
        }
        public void InvokeActionMethodFilterWhereEndContinuationThrowsThreadAbortException() {
            // Arrange
            List<string> actions = new List<string>();
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            ActionExecutingContext preContext = GetEmptyActionExecutingContext();
            MockAsyncResult asyncResult = new MockAsyncResult();

            ActionFilterImpl filter = new ActionFilterImpl() {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    actions.Add("OnActionExecuting");
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    actions.Add("OnActionExecuted");
                    Thread.ResetAbort();
                    Assert.IsNull(filterContext.Exception, "Exception should not have shown up.");
                    Assert.AreEqual(preContext.ActionDescriptor, filterContext.ActionDescriptor, "Descriptor did not match.");
                    filterContext.ExceptionHandled = true;
                }
            };

            BeginInvokeCallback beginContinuation = (innerCallback, innerState) => {
                actions.Add("BeginContinuation");
                return asyncResult;
            };

            AsyncCallback<ActionExecutedContext> endContinuation = ar => {
                Assert.AreEqual(asyncResult, ar);
                actions.Add("EndContinuation");
                Thread.CurrentThread.Abort();
                return null;
            };

            // Act
            // Act
            IAsyncResult returnedResult = AsyncControllerActionInvoker.BeginInvokeActionMethodFilter(filter, preContext, beginContinuation, endContinuation, null, null);
            ExceptionHelper.ExpectException<ThreadAbortException>(
                delegate {
                    AsyncControllerActionInvoker.EndInvokeActionMethodFilter(returnedResult);
                },
                "Thread was being aborted.");

            // Assert
            Assert.AreEqual(4, actions.Count);
            Assert.AreEqual("OnActionExecuting", actions[0]);
            Assert.AreEqual("BeginContinuation", actions[1]);
            Assert.AreEqual("EndContinuation", actions[2]);
            Assert.AreEqual("OnActionExecuted", actions[3]);
        }
        public void BeginInvokeActionMethodWithFilters_EndExecuteThrowsOnActionExecutedException_HandledByLater()
        {
            // Arrange
            List<string> actionLog = new List<string>();
            Exception exception = new Exception("Some exception message.");
            ActionResult expectedResult = new ViewResult();
            Func<ActionResult> action = delegate
            {
                actionLog.Add("EndExecute");
                throw exception;

            };
            ActionFilterImpl filter1 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting1"); },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted1"); }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting2"); },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext)
                {
                    actionLog.Add("OnActionExecuted2");
                    Assert.Same(exception, filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result = expectedResult;
                }
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersEndTester(action, filter1, filter2);

            // Assert
            Assert.Equal(new[] { "OnActionExecuting1", "OnActionExecuting2", "EndExecute", "OnActionExecuted2", "OnActionExecuted1" }, actionLog.ToArray());
            Assert.Equal(expectedResult, result);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutedException_ThreadAbort() {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext = GetActionExecutingContext();
            ActionFilterImpl actionFilter = new ActionFilterImpl() {
                OnActionExecutedImpl = filterContext => {
                    onActionExecutedWasCalled = true;
                    Thread.ResetAbort();
                }
            };

            // Act & assert
            Func<ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                () => () => {
                    Thread.CurrentThread.Abort();
                    return null;
                });

            ExceptionHelper.ExpectException<ThreadAbortException>(
                delegate {
                    continuation();
                });

            // Assert
            Assert.IsTrue(onActionExecutedWasCalled, "OnActionExecuted() should've been called.");
        }
        public void BeginInvokeActionMethodWithFilters_EndExecuteThrowsOnActionExecutedException_ThreadAbort()
        {
            // Arrange
            bool onActionExecutedWasCalled = false;
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutedImpl = filterContext =>
                {
                    onActionExecutedWasCalled = true;
                    Thread.ResetAbort();
                }
            };
            Func<ActionResult> action = delegate
            {
                Thread.CurrentThread.Abort();
                return null;
            };

            // Act & assert
            Assert.Throws<ThreadAbortException>(
                delegate { BeingInvokeActionMethodWithFiltersEndTester(action, actionFilter); });

            // Assert
            Assert.True(onActionExecutedWasCalled);
        }
        public void InvokeActionMethodFilterAsynchronously_NextInChainThrowsOnActionExecutingException_Handled() {
            // Arrange
            ViewResult expectedResult = new ViewResult();

            bool nextInChainWasCalled = false;
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;

            ActionExecutingContext preContext = GetActionExecutingContext();
            ActionFilterImpl actionFilter = new ActionFilterImpl() {
                OnActionExecutingImpl = filterContext => {
                    onActionExecutingWasCalled = true;
                },
                OnActionExecutedImpl = filterContext => {
                    onActionExecutedWasCalled = true;
                    Assert.IsNotNull(filterContext.Exception);
                    filterContext.ExceptionHandled = true;
                    filterContext.Result = expectedResult;
                }
            };

            // Act
            Func<ActionExecutedContext> continuation = AsyncControllerActionInvoker.InvokeActionMethodFilterAsynchronously(actionFilter, preContext,
                () => {
                    nextInChainWasCalled = true;
                    throw new Exception("Some exception text.");
                });

            // Assert
            Assert.IsTrue(nextInChainWasCalled, "Next in chain should've been called.");
            Assert.IsTrue(onActionExecutingWasCalled, "OnActionExecuting() should've been called by the first invocation.");
            Assert.IsTrue(onActionExecutedWasCalled, "OnActionExecuted() should've been called due to exception handling.");

            ActionExecutedContext postContext = continuation();
            Assert.AreEqual(expectedResult, postContext.Result);
        }
        public void BeginInvokeActionMethodWithFilters_OnActionExecutingSetsResult()
        {
            // Arrange
            ActionResult expectedResult = new ViewResult();
            ActionResult overriddenResult = new ViewResult();
            bool onActionExecutingWasCalled = false;
            bool onActionExecutedWasCalled = false;
            ActionFilterImpl actionFilter = new ActionFilterImpl()
            {
                OnActionExecutingImpl = filterContext =>
                {
                    onActionExecutingWasCalled = true;
                    filterContext.Result = expectedResult;
                },
                OnActionExecutedImpl = _ => { onActionExecutedWasCalled = true; }
            };
            Func<ActionResult> endExecute = delegate
            {
                return overriddenResult;
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersTester(() => new MockAsyncResult(), endExecute, checkBegin: false, checkEnd: false, filters: new IActionFilter[] { actionFilter } );

            // Assert
            Assert.True(onActionExecutingWasCalled);
            Assert.False(onActionExecutedWasCalled);
            Assert.Equal(expectedResult, result);
        }
        public void InvokeActionMethodWithFiltersOrdersFiltersCorrectly() {
            // Arrange
            List<string> actions = new List<string>();
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            MockAsyncResult asyncResult = new MockAsyncResult();
            ActionResult actionResult = new ViewResult();

            ActionFilterImpl filter1 = new ActionFilterImpl() {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    actions.Add("OnActionExecuting1");
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    actions.Add("OnActionExecuted1");
                }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl() {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    actions.Add("OnActionExecuting2");
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    actions.Add("OnActionExecuted2");
                }
            };

            ControllerContext controllerContext = new ControllerContext() { Controller = new Mock<Controller>().Object };
            ActionDescriptor ad = new Mock<ActionDescriptor>().Object;

            Mock<AsyncControllerActionInvoker> mockInvoker = new Mock<AsyncControllerActionInvoker>() { CallBase = true };
            mockInvoker.Expect(i => i.BeginInvokeActionMethod(controllerContext, ad, parameters, It.IsAny<AsyncCallback>(), It.IsAny<object>())).Returns(asyncResult);
            mockInvoker.Expect(i => i.EndInvokeActionMethod(asyncResult)).Returns(actionResult);

            AsyncControllerActionInvoker invoker = mockInvoker.Object;
            List<IActionFilter> filters = new List<IActionFilter>() { filter1, filter2 };

            // Act
            IAsyncResult returnedAsyncResult = invoker.BeginInvokeActionMethodWithFilters(controllerContext, filters, ad, parameters, null, null);
            ActionExecutedContext returnedPostContext = invoker.EndInvokeActionMethodWithFilters(returnedAsyncResult);

            // Assert
            Assert.AreEqual(4, actions.Count);
            Assert.AreEqual("OnActionExecuting1", actions[0]);
            Assert.AreEqual("OnActionExecuting2", actions[1]);
            Assert.AreEqual("OnActionExecuted2", actions[2]);
            Assert.AreEqual("OnActionExecuted1", actions[3]);

            Assert.AreEqual(actionResult, returnedPostContext.Result);
            Assert.IsNull(returnedPostContext.Exception);
        }
        public void BeginInvokeActionMethodWithFilters_ShortCircuited()
        {
            // Arrange
            List<string> actionLog = new List<string>();
            ActionResult shortCircuitResult = new ViewResult();
            ActionResult executeResult = new ViewResult();
            ActionFilterImpl filter1 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actionLog.Add("OnActionExecuting1"); },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted1"); }
            };
            ActionFilterImpl filter2 = new ActionFilterImpl()
            {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext)
                {
                    actionLog.Add("OnActionExecuting2");
                    filterContext.Result = shortCircuitResult;
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) { actionLog.Add("OnActionExecuted2"); }
            };
            Func<ActionResult> endExecute = () =>
            {
                actionLog.Add("ExecuteCalled");
                return executeResult;
            };

            // Act
            ActionResult result = BeingInvokeActionMethodWithFiltersTester(() => new MockAsyncResult(), endExecute, checkBegin: false, checkEnd: false, filters: new IActionFilter[] { filter1, filter2 });

            // Assert
            Assert.Equal(new[] { "OnActionExecuting1", "OnActionExecuting2", "OnActionExecuted1" }, actionLog.ToArray());
            Assert.Equal(shortCircuitResult, result);
        }
        public void InvokeActionMethodFilterWhereBeginContinuationThrowsExceptionAndIsHandled() {
            // Arrange
            List<string> actions = new List<string>();
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            Exception exception = new Exception();
            ActionExecutingContext preContext = GetEmptyActionExecutingContext();

            ActionFilterImpl filter = new ActionFilterImpl() {
                OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) {
                    actions.Add("OnActionExecuting");
                },
                OnActionExecutedImpl = delegate(ActionExecutedContext filterContext) {
                    actions.Add("OnActionExecuted");
                    Assert.AreEqual(exception, filterContext.Exception, "Exception did not match.");
                    Assert.AreEqual(preContext.ActionDescriptor, filterContext.ActionDescriptor, "Descriptor did not match.");
                    Assert.IsFalse(filterContext.ExceptionHandled);
                    filterContext.ExceptionHandled = true;
                }
            };

            BeginInvokeCallback beginContinuation = (innerCallback, innerState) => {
                actions.Add("BeginContinuation");
                throw exception;
            };

            AsyncCallback<ActionExecutedContext> endContinuation = ar => {
                Assert.Fail("Continuation should not be called.");
                return null;
            };

            // Act
            IAsyncResult asyncResult = AsyncControllerActionInvoker.BeginInvokeActionMethodFilter(filter, preContext, beginContinuation, endContinuation, null, null);
            ActionExecutedContext postContext = AsyncControllerActionInvoker.EndInvokeActionMethodFilter(asyncResult);

            // Assert
            Assert.AreEqual(3, actions.Count);
            Assert.AreEqual("OnActionExecuting", actions[0]);
            Assert.AreEqual("BeginContinuation", actions[1]);
            Assert.AreEqual("OnActionExecuted", actions[2]);
            Assert.AreEqual(exception, postContext.Exception, "Exception did not match.");
            Assert.AreEqual(preContext.ActionDescriptor, postContext.ActionDescriptor, "Descriptor did not match.");
            Assert.IsTrue(postContext.ExceptionHandled);
        }