/test/System.Web.Mvc.Test/Test/ControllerActionInvokerTest.cs
C# | 1084 lines | 739 code | 200 blank | 145 comment | 1 complexity | 6f04a89a462aa58d962227ec5d187fa2 MD5 | raw file
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Globalization;
- using System.Linq;
- using System.Reflection;
- using System.Threading;
- using Microsoft.Web.UnitTestUtil;
- using Moq;
- using Xunit;
- using Assert = Microsoft.TestCommon.AssertEx;
- namespace System.Web.Mvc.Test
- {
- [CLSCompliant(false)]
- public class ControllerActionInvokerTest
- {
- [Fact]
- public void CreateActionResultWithActionResultParameterReturnsParameterUnchanged()
- {
- // Arrange
- ControllerActionInvokerHelper invoker = new ControllerActionInvokerHelper();
- ActionResult originalResult = new JsonResult();
- // Act
- ActionResult returnedActionResult = invoker.PublicCreateActionResult(null, null, originalResult);
- // Assert
- Assert.Same(originalResult, returnedActionResult);
- }
- [Fact]
- public void CreateActionResultWithNullParameterReturnsEmptyResult()
- {
- // Arrange
- ControllerActionInvokerHelper invoker = new ControllerActionInvokerHelper();
- // Act
- ActionResult returnedActionResult = invoker.PublicCreateActionResult(null, null, null);
- // Assert
- Assert.IsType<EmptyResult>(returnedActionResult);
- }
- [Fact]
- public void CreateActionResultWithObjectParameterReturnsContentResult()
- {
- // Arrange
- ControllerActionInvokerHelper invoker = new ControllerActionInvokerHelper();
- object originalReturnValue = new CultureReflector();
- // Act
- ActionResult returnedActionResult = invoker.PublicCreateActionResult(null, null, originalReturnValue);
- // Assert
- ContentResult contentResult = Assert.IsType<ContentResult>(returnedActionResult);
- Assert.Equal("ivl", contentResult.Content);
- }
- [Fact]
- public void FindAction()
- {
- // Arrange
- EmptyController controller = new EmptyController();
- ControllerContext controllerContext = GetControllerContext(controller);
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ActionDescriptor expectedAd = new Mock<ActionDescriptor>().Object;
- Mock<ControllerDescriptor> mockCd = new Mock<ControllerDescriptor>();
- mockCd.Setup(cd => cd.FindAction(controllerContext, "someAction")).Returns(expectedAd);
- // Act
- ActionDescriptor returnedAd = helper.PublicFindAction(controllerContext, mockCd.Object, "someAction");
- // Assert
- Assert.Equal(expectedAd, returnedAd);
- }
- [Fact]
- public void FindActionDoesNotMatchConstructor()
- {
- // FindActionMethod() shouldn't match special-named methods like type constructors.
- // Arrange
- Controller controller = new FindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(FindMethodController));
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, ".ctor");
- ActionDescriptor ad2 = helper.PublicFindAction(context, cd, "FindMethodController");
- // Assert
- Assert.Null(ad);
- Assert.Null(ad2);
- }
- [Fact]
- public void FindActionDoesNotMatchEvent()
- {
- // FindActionMethod() should skip methods that aren't publicly visible.
- // Arrange
- Controller controller = new FindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(FindMethodController));
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "add_Event");
- // Assert
- Assert.Null(ad);
- }
- [Fact]
- public void FindActionDoesNotMatchInternalMethod()
- {
- // FindActionMethod() should skip methods that aren't publicly visible.
- // Arrange
- Controller controller = new FindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(FindMethodController));
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "InternalMethod");
- // Assert
- Assert.Null(ad);
- }
- [Fact]
- public void FindActionDoesNotMatchMethodsDefinedOnControllerType()
- {
- // FindActionMethod() shouldn't match methods originally defined on the Controller type, e.g. Dispose().
- // Arrange
- Controller controller = new BlankController();
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(BlankController));
- ControllerContext context = GetControllerContext(controller);
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- var methods = typeof(Controller).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
- // Act & Assert
- foreach (var method in methods)
- {
- bool wasFound = true;
- try
- {
- ActionDescriptor ad = helper.PublicFindAction(context, cd, method.Name);
- wasFound = (ad != null);
- }
- finally
- {
- Assert.False(wasFound, "FindAction() should return false for methods defined on the Controller class: " + method);
- }
- }
- }
- [Fact]
- public void FindActionDoesNotMatchMethodsDefinedOnObjectType()
- {
- // FindActionMethod() shouldn't match methods originally defined on the Object type, e.g. ToString().
- // Arrange
- Controller controller = new FindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(FindMethodController));
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "ToString");
- // Assert
- Assert.Null(ad);
- }
- [Fact]
- public void FindActionDoesNotMatchNonActionMethod()
- {
- // FindActionMethod() should respect the [NonAction] attribute.
- // Arrange
- Controller controller = new FindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(FindMethodController));
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "NonActionMethod");
- // Assert
- Assert.Null(ad);
- }
- [Fact]
- public void FindActionDoesNotMatchOverriddenNonActionMethod()
- {
- // FindActionMethod() should trace the method's inheritance chain looking for the [NonAction] attribute.
- // Arrange
- Controller controller = new DerivedFindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(DerivedFindMethodController));
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "InternalMethod");
- // Assert
- Assert.Null(ad);
- }
- [Fact]
- public void FindActionDoesNotMatchPrivateMethod()
- {
- // FindActionMethod() should skip methods that aren't publicly visible.
- // Arrange
- Controller controller = new FindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(FindMethodController));
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "PrivateMethod");
- // Assert
- Assert.Null(ad);
- }
- [Fact]
- public void FindActionDoesNotMatchProperty()
- {
- // FindActionMethod() shouldn't match special-named methods like property getters.
- // Arrange
- Controller controller = new FindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(FindMethodController));
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "get_Property");
- // Assert
- Assert.Null(ad);
- }
- [Fact]
- public void FindActionDoesNotMatchProtectedMethod()
- {
- // FindActionMethod() should skip methods that aren't publicly visible.
- // Arrange
- Controller controller = new FindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(FindMethodController));
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "ProtectedMethod");
- // Assert
- Assert.Null(ad);
- }
- [Fact]
- public void FindActionIsCaseInsensitive()
- {
- // Arrange
- Controller controller = new FindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(FindMethodController));
- MethodInfo expectedMethodInfo = typeof(FindMethodController).GetMethod("ValidActionMethod");
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad1 = helper.PublicFindAction(context, cd, "validactionmethod");
- ActionDescriptor ad2 = helper.PublicFindAction(context, cd, "VALIDACTIONMETHOD");
- // Assert
- ReflectedActionDescriptor rad1 = Assert.IsType<ReflectedActionDescriptor>(ad1);
- Assert.Same(expectedMethodInfo, rad1.MethodInfo);
- ReflectedActionDescriptor rad2 = Assert.IsType<ReflectedActionDescriptor>(ad2);
- Assert.Same(expectedMethodInfo, rad2.MethodInfo);
- }
- [Fact]
- public void FindActionMatchesActionMethodWithClosedGenerics()
- {
- // FindActionMethod() should work with generic methods as long as there are no open types.
- // Arrange
- Controller controller = new GenericFindMethodController<int>();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(GenericFindMethodController<int>));
- MethodInfo expectedMethodInfo = typeof(GenericFindMethodController<int>).GetMethod("ClosedGenericMethod");
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "ClosedGenericMethod");
- // Assert
- ReflectedActionDescriptor rad = Assert.IsType<ReflectedActionDescriptor>(ad);
- Assert.Same(expectedMethodInfo, rad.MethodInfo);
- }
- [Fact]
- public void FindActionMatchesNewActionMethodsHidingNonActionMethods()
- {
- // FindActionMethod() should stop looking for [NonAction] in the method's inheritance chain when it sees
- // that a method in a derived class hides the a method in the base class.
- // Arrange
- Controller controller = new DerivedFindMethodController();
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new ReflectedControllerDescriptor(typeof(DerivedFindMethodController));
- MethodInfo expectedMethodInfo = typeof(DerivedFindMethodController).GetMethod("DerivedIsActionMethod");
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ActionDescriptor ad = helper.PublicFindAction(context, cd, "DerivedIsActionMethod");
- // Assert
- ReflectedActionDescriptor rad = Assert.IsType<ReflectedActionDescriptor>(ad);
- Assert.Same(expectedMethodInfo, rad.MethodInfo);
- }
- [Fact]
- public void GetControllerDescriptor()
- {
- // Arrange
- EmptyController controller = new EmptyController();
- ControllerContext controllerContext = GetControllerContext(controller);
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- // Act
- ControllerDescriptor cd = helper.PublicGetControllerDescriptor(controllerContext);
- // Assert
- Assert.IsType<ReflectedControllerDescriptor>(cd);
- Assert.Equal(typeof(EmptyController), cd.ControllerType);
- }
- [Fact]
- public void GetFiltersSplitsFilterObjectsIntoFilterInfo()
- {
- // Arrange
- IActionFilter actionFilter = new Mock<IActionFilter>().Object;
- IResultFilter resultFilter = new Mock<IResultFilter>().Object;
- IAuthorizationFilter authFilter = new Mock<IAuthorizationFilter>().Object;
- IExceptionFilter exFilter = new Mock<IExceptionFilter>().Object;
- object noneOfTheAbove = new object();
- ControllerActionInvokerHelper invoker = new ControllerActionInvokerHelper(actionFilter, authFilter, exFilter, resultFilter, noneOfTheAbove);
- ControllerContext context = new ControllerContext();
- ActionDescriptor descriptor = new Mock<ActionDescriptor>().Object;
- // Act
- FilterInfo result = invoker.PublicGetFilters(context, descriptor);
- // Assert
- Assert.Same(actionFilter, result.ActionFilters.Single());
- Assert.Same(authFilter, result.AuthorizationFilters.Single());
- Assert.Same(exFilter, result.ExceptionFilters.Single());
- Assert.Same(resultFilter, result.ResultFilters.Single());
- }
- [Fact]
- public void GetParameterValueAllowsAllSubpropertiesIfBindAttributeNotSpecified()
- {
- // Arrange
- CustomConverterController controller = new CustomConverterController();
- ControllerContext controllerContext = GetControllerContext(controller);
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ParameterInfo paramWithoutBindAttribute = typeof(CustomConverterController).GetMethod("ParameterWithoutBindAttribute").GetParameters()[0];
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(paramWithoutBindAttribute, new Mock<ActionDescriptor>().Object);
- // Act
- object valueWithoutBindAttribute = helper.PublicGetParameterValue(controllerContext, pd);
- // Assert
- Assert.Equal("foo=True&bar=True", valueWithoutBindAttribute);
- }
- [Fact]
- public void GetParameterValueResolvesConvertersInCorrectOrderOfPrecedence()
- {
- // Order of precedence:
- // 1. Attributes on the parameter itself
- // 2. Query the global converter provider
- // Arrange
- CustomConverterController controller = new CustomConverterController();
- Dictionary<string, object> values = new Dictionary<string, object> { { "foo", "fooValue" } };
- ControllerContext controllerContext = GetControllerContext(controller, values);
- controller.ControllerContext = controllerContext;
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ParameterInfo paramWithOneConverter = typeof(CustomConverterController).GetMethod("ParameterHasOneConverter").GetParameters()[0];
- ReflectedParameterDescriptor pdOneConverter = new ReflectedParameterDescriptor(paramWithOneConverter, new Mock<ActionDescriptor>().Object);
- ParameterInfo paramWithNoConverters = typeof(CustomConverterController).GetMethod("ParameterHasNoConverters").GetParameters()[0];
- ReflectedParameterDescriptor pdNoConverters = new ReflectedParameterDescriptor(paramWithNoConverters, new Mock<ActionDescriptor>().Object);
- // Act
- object valueWithOneConverter = helper.PublicGetParameterValue(controllerContext, pdOneConverter);
- object valueWithNoConverters = helper.PublicGetParameterValue(controllerContext, pdNoConverters);
- // Assert
- Assert.Equal("foo_String", valueWithOneConverter);
- Assert.Equal("fooValue", valueWithNoConverters);
- }
- [Fact]
- public void GetParameterValueRespectsBindAttribute()
- {
- // Arrange
- CustomConverterController controller = new CustomConverterController();
- ControllerContext controllerContext = GetControllerContext(controller);
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ParameterInfo paramWithBindAttribute = typeof(CustomConverterController).GetMethod("ParameterHasBindAttribute").GetParameters()[0];
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(paramWithBindAttribute, new Mock<ActionDescriptor>().Object);
- // Act
- object valueWithBindAttribute = helper.PublicGetParameterValue(controllerContext, pd);
- // Assert
- Assert.Equal("foo=True&bar=False", valueWithBindAttribute);
- }
- [Fact]
- public void GetParameterValueRespectsBindAttributePrefix()
- {
- // Arrange
- CustomConverterController controller = new CustomConverterController();
- Dictionary<string, object> values = new Dictionary<string, object> { { "foo", "fooValue" }, { "bar", "barValue" } };
- ControllerContext controllerContext = GetControllerContext(controller, values);
- controller.ControllerContext = controllerContext;
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ParameterInfo paramWithFieldPrefix = typeof(CustomConverterController).GetMethod("ParameterHasFieldPrefix").GetParameters()[0];
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(paramWithFieldPrefix, new Mock<ActionDescriptor>().Object);
- // Act
- object parameterValue = helper.PublicGetParameterValue(controllerContext, pd);
- // Assert
- Assert.Equal("barValue", parameterValue);
- }
- [Fact]
- public void GetParameterValueRespectsBindAttributePrefixOnComplexType()
- {
- // Arrange
- CustomConverterController controller = new CustomConverterController();
- Dictionary<string, object> values = new Dictionary<string, object> { { "intprop", "123" }, { "stringprop", "hello" } };
- ControllerContext controllerContext = GetControllerContext(controller, values);
- controller.ControllerContext = controllerContext;
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ParameterInfo paramWithFieldPrefix = typeof(CustomConverterController).GetMethod("ParameterHasPrefixAndComplexType").GetParameters()[0];
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(paramWithFieldPrefix, new Mock<ActionDescriptor>().Object);
- // Act
- MySimpleModel parameterValue = helper.PublicGetParameterValue(controllerContext, pd) as MySimpleModel;
- // Assert
- Assert.Null(parameterValue);
- }
- [Fact]
- public void GetParameterValueRespectsBindAttributeNullPrefix()
- {
- // Arrange
- CustomConverterController controller = new CustomConverterController();
- Dictionary<string, object> values = new Dictionary<string, object> { { "foo", "fooValue" }, { "bar", "barValue" } };
- ControllerContext controllerContext = GetControllerContext(controller, values);
- controller.ControllerContext = controllerContext;
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ParameterInfo paramWithFieldPrefix = typeof(CustomConverterController).GetMethod("ParameterHasNullFieldPrefix").GetParameters()[0];
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(paramWithFieldPrefix, new Mock<ActionDescriptor>().Object);
- // Act
- object parameterValue = helper.PublicGetParameterValue(controllerContext, pd);
- // Assert
- Assert.Equal("fooValue", parameterValue);
- }
- [Fact]
- public void GetParameterValueRespectsBindAttributeNullPrefixOnComplexType()
- {
- // Arrange
- CustomConverterController controller = new CustomConverterController();
- Dictionary<string, object> values = new Dictionary<string, object> { { "intprop", "123" }, { "stringprop", "hello" } };
- ControllerContext controllerContext = GetControllerContext(controller, values);
- controller.ControllerContext = controllerContext;
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ParameterInfo paramWithFieldPrefix = typeof(CustomConverterController).GetMethod("ParameterHasNoPrefixAndComplexType").GetParameters()[0];
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(paramWithFieldPrefix, new Mock<ActionDescriptor>().Object);
- // Act
- MySimpleModel parameterValue = helper.PublicGetParameterValue(controllerContext, pd) as MySimpleModel;
- // Assert
- Assert.NotNull(parameterValue);
- Assert.Equal(123, parameterValue.IntProp);
- Assert.Equal("hello", parameterValue.StringProp);
- }
- [Fact]
- public void GetParameterValueRespectsBindAttributeEmptyPrefix()
- {
- // Arrange
- CustomConverterController controller = new CustomConverterController();
- Dictionary<string, object> values = new Dictionary<string, object> { { "foo", "fooValue" }, { "bar", "barValue" }, { "intprop", "123" }, { "stringprop", "hello" } };
- ControllerContext controllerContext = GetControllerContext(controller, values);
- controller.ControllerContext = controllerContext;
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ParameterInfo paramWithFieldPrefix = typeof(CustomConverterController).GetMethod("ParameterHasEmptyFieldPrefix").GetParameters()[0];
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(paramWithFieldPrefix, new Mock<ActionDescriptor>().Object);
- // Act
- MySimpleModel parameterValue = helper.PublicGetParameterValue(controllerContext, pd) as MySimpleModel;
- // Assert
- Assert.NotNull(parameterValue);
- Assert.Equal(123, parameterValue.IntProp);
- Assert.Equal("hello", parameterValue.StringProp);
- }
- [Fact]
- public void GetParameterValueRespectsDefaultValueAttribute()
- {
- // Arrange
- CustomConverterController controller = new CustomConverterController();
- ControllerContext controllerContext = GetControllerContext(controller);
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- controller.ValueProvider = new SimpleValueProvider();
- ParameterInfo paramWithDefaultValueAttribute = typeof(CustomConverterController).GetMethod("ParameterHasDefaultValueAttribute").GetParameters()[0];
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(paramWithDefaultValueAttribute, new Mock<ActionDescriptor>().Object);
- // Act
- object valueWithDefaultValueAttribute = helper.PublicGetParameterValue(controllerContext, pd);
- // Assert
- Assert.Equal(42, valueWithDefaultValueAttribute);
- }
- [Fact]
- public void GetParameterValueReturnsNullIfCannotConvertNonRequiredParameter()
- {
- // Arrange
- Dictionary<string, object> dict = new Dictionary<string, object>()
- {
- { "id", DateTime.Now } // cannot convert DateTime to Nullable<int>
- };
- var controller = new ParameterTestingController();
- ControllerContext context = GetControllerContext(controller, dict);
- controller.ControllerContext = context;
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- MethodInfo mi = typeof(ParameterTestingController).GetMethod("TakesNullableInt");
- ParameterInfo[] pis = mi.GetParameters();
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(pis[0], new Mock<ActionDescriptor>().Object);
- // Act
- object oValue = helper.PublicGetParameterValue(context, pd);
- // Assert
- Assert.Null(oValue);
- }
- [Fact]
- public void GetParameterValueReturnsNullIfNullableTypeValueNotFound()
- {
- // Arrange
- var controller = new ParameterTestingController();
- ControllerContext context = GetControllerContext(controller);
- controller.ControllerContext = context;
- controller.ValueProvider = new SimpleValueProvider();
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- MethodInfo mi = typeof(ParameterTestingController).GetMethod("TakesNullableInt");
- ParameterInfo[] pis = mi.GetParameters();
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(pis[0], new Mock<ActionDescriptor>().Object);
- // Act
- object oValue = helper.PublicGetParameterValue(context, pd);
- // Assert
- Assert.Null(oValue);
- }
- [Fact]
- public void GetParameterValueReturnsNullIfReferenceTypeValueNotFound()
- {
- // Arrange
- var controller = new ParameterTestingController();
- ControllerContext context = GetControllerContext(controller);
- controller.ControllerContext = context;
- controller.ValueProvider = new SimpleValueProvider();
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- MethodInfo mi = typeof(ParameterTestingController).GetMethod("Foo");
- ParameterInfo[] pis = mi.GetParameters();
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(pis[0], new Mock<ActionDescriptor>().Object);
- // Act
- object oValue = helper.PublicGetParameterValue(context, pd);
- // Assert
- Assert.Null(oValue);
- }
- [Fact]
- public void GetParameterValuesCallsGetParameterValue()
- {
- // Arrange
- ControllerBase controller = new ParameterTestingController();
- IDictionary<string, object> dict = new Dictionary<string, object>();
- ControllerContext context = GetControllerContext(controller);
- MethodInfo mi = typeof(ParameterTestingController).GetMethod("Foo");
- ReflectedActionDescriptor ad = new ReflectedActionDescriptor(mi, "Foo", new Mock<ControllerDescriptor>().Object);
- ParameterDescriptor[] pds = ad.GetParameters();
- Mock<ControllerActionInvokerHelper> mockHelper = new Mock<ControllerActionInvokerHelper>() { CallBase = true };
- mockHelper.Setup(h => h.PublicGetParameterValue(context, pds[0])).Returns("Myfoo").Verifiable();
- mockHelper.Setup(h => h.PublicGetParameterValue(context, pds[1])).Returns("Mybar").Verifiable();
- mockHelper.Setup(h => h.PublicGetParameterValue(context, pds[2])).Returns("Mybaz").Verifiable();
- ControllerActionInvokerHelper helper = mockHelper.Object;
- // Act
- IDictionary<string, object> parameters = helper.PublicGetParameterValues(context, ad);
- // Assert
- Assert.Equal(3, parameters.Count);
- Assert.Equal("Myfoo", parameters["foo"]);
- Assert.Equal("Mybar", parameters["bar"]);
- Assert.Equal("Mybaz", parameters["baz"]);
- mockHelper.Verify();
- }
- [Fact]
- public void GetParameterValuesReturnsEmptyDictionaryForParameterlessMethod()
- {
- // Arrange
- var controller = new ParameterTestingController();
- ControllerContext context = GetControllerContext(controller);
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- MethodInfo mi = typeof(ParameterTestingController).GetMethod("Parameterless");
- ReflectedActionDescriptor ad = new ReflectedActionDescriptor(mi, "Parameterless", new Mock<ControllerDescriptor>().Object);
- // Act
- IDictionary<string, object> parameters = helper.PublicGetParameterValues(context, ad);
- // Assert
- Assert.Empty(parameters);
- }
- [Fact]
- public void GetParameterValuesReturnsValuesForParametersInOrder()
- {
- // We need to hook into GetParameterValue() to make sure that GetParameterValues() is calling it.
- // Arrange
- var controller = new ParameterTestingController();
- Dictionary<string, object> dict = new Dictionary<string, object>()
- {
- { "foo", "MyFoo" },
- { "bar", "MyBar" },
- { "baz", "MyBaz" }
- };
- ControllerContext context = GetControllerContext(controller, dict);
- controller.ControllerContext = context;
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- MethodInfo mi = typeof(ParameterTestingController).GetMethod("Foo");
- ReflectedActionDescriptor ad = new ReflectedActionDescriptor(mi, "Foo", new Mock<ControllerDescriptor>().Object);
- // Act
- IDictionary<string, object> parameters = helper.PublicGetParameterValues(context, ad);
- // Assert
- Assert.Equal(3, parameters.Count);
- Assert.Equal("MyFoo", parameters["foo"]);
- Assert.Equal("MyBar", parameters["bar"]);
- Assert.Equal("MyBaz", parameters["baz"]);
- }
- [Fact]
- public void GetParameterValueUsesControllerValueProviderAsValueProvider()
- {
- // Arrange
- Dictionary<string, object> values = new Dictionary<string, object>()
- {
- { "foo", "fooValue" }
- };
- CustomConverterController controller = new CustomConverterController();
- ControllerContext controllerContext = GetControllerContext(controller, values);
- ControllerActionInvokerHelper helper = new ControllerActionInvokerHelper();
- ParameterInfo parameter = typeof(CustomConverterController).GetMethod("ParameterHasNoConverters").GetParameters()[0];
- ReflectedParameterDescriptor pd = new ReflectedParameterDescriptor(parameter, new Mock<ActionDescriptor>().Object);
- // Act
- object parameterValue = helper.PublicGetParameterValue(controllerContext, pd);
- // Assert
- Assert.Equal("fooValue", parameterValue);
- }
- [Fact]
- public void InvokeAction()
- {
- // Arrange
- ControllerBase controller = new Mock<ControllerBase>().Object;
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new Mock<ControllerDescriptor>().Object;
- ActionDescriptor ad = new Mock<ActionDescriptor>().Object;
- FilterInfo filterInfo = new FilterInfo();
- IDictionary<string, object> parameters = new Dictionary<string, object>();
- MethodInfo methodInfo = typeof(object).GetMethod("ToString");
- ActionResult actionResult = new EmptyResult();
- ActionExecutedContext postContext = new ActionExecutedContext(context, ad, false /* canceled */, null /* exception */)
- {
- Result = actionResult
- };
- AuthorizationContext authContext = new AuthorizationContext();
- Mock<ControllerActionInvokerHelper> mockHelper = new Mock<ControllerActionInvokerHelper>() { CallBase = true };
- mockHelper.Setup(h => h.PublicGetControllerDescriptor(context)).Returns(cd).Verifiable();
- mockHelper.Setup(h => h.PublicFindAction(context, cd, "SomeMethod")).Returns(ad).Verifiable();
- mockHelper.Setup(h => h.PublicGetFilters(context, ad)).Returns(filterInfo).Verifiable();
- mockHelper.Setup(h => h.PublicInvokeAuthorizationFilters(context, filterInfo.AuthorizationFilters, ad)).Returns(authContext).Verifiable();
- mockHelper.Setup(h => h.PublicGetParameterValues(context, ad)).Returns(parameters).Verifiable();
- mockHelper.Setup(h => h.PublicInvokeActionMethodWithFilters(context, filterInfo.ActionFilters, ad, parameters)).Returns(postContext).Verifiable();
- mockHelper.Setup(h => h.PublicInvokeActionResultWithFilters(context, filterInfo.ResultFilters, actionResult)).Returns((ResultExecutedContext)null).Verifiable();
- ControllerActionInvokerHelper helper = mockHelper.Object;
- // Act
- bool retVal = helper.InvokeAction(context, "SomeMethod");
- Assert.True(retVal);
- mockHelper.Verify();
- }
- [Fact]
- public void InvokeActionCallsValidateRequestIfAsked()
- {
- // Arrange
- ControllerBase controller = new Mock<ControllerBase>().Object;
- controller.ValidateRequest = true;
- bool validateInputWasCalled = false;
- ControllerContext context = GetControllerContext(controller, null, validateInputCallback: () => { validateInputWasCalled = true; });
- ControllerDescriptor cd = new Mock<ControllerDescriptor>().Object;
- ActionDescriptor ad = new Mock<ActionDescriptor>().Object;
- FilterInfo filterInfo = new FilterInfo();
- AuthorizationContext authContext = new AuthorizationContext();
- Mock<ControllerActionInvokerHelper> mockHelper = new Mock<ControllerActionInvokerHelper>();
- mockHelper.CallBase = true;
- mockHelper.Setup(h => h.PublicGetControllerDescriptor(context)).Returns(cd).Verifiable();
- mockHelper.Setup(h => h.PublicFindAction(context, cd, "SomeMethod")).Returns(ad).Verifiable();
- mockHelper.Setup(h => h.PublicGetFilters(context, ad)).Returns(filterInfo).Verifiable();
- mockHelper.Setup(h => h.PublicInvokeAuthorizationFilters(context, filterInfo.AuthorizationFilters, ad)).Returns(authContext).Verifiable();
- ControllerActionInvokerHelper helper = mockHelper.Object;
- // Act
- helper.InvokeAction(context, "SomeMethod");
- // Assert
- Assert.True(validateInputWasCalled);
- mockHelper.Verify();
- }
- [Fact]
- public void InvokeActionDoesNotCallValidateRequestForChildActions()
- {
- // Arrange
- ControllerBase controller = new Mock<ControllerBase>().Object;
- controller.ValidateRequest = true;
- ControllerContext context = GetControllerContext(controller, null);
- Mock.Get<ControllerContext>(context).SetupGet(c => c.IsChildAction).Returns(true);
- ControllerDescriptor cd = new Mock<ControllerDescriptor>().Object;
- ActionDescriptor ad = new Mock<ActionDescriptor>().Object;
- FilterInfo filterInfo = new FilterInfo();
- AuthorizationContext authContext = new AuthorizationContext();
- Mock<ControllerActionInvokerHelper> mockHelper = new Mock<ControllerActionInvokerHelper>();
- mockHelper.CallBase = true;
- mockHelper.Setup(h => h.PublicGetControllerDescriptor(context)).Returns(cd).Verifiable();
- mockHelper.Setup(h => h.PublicFindAction(context, cd, "SomeMethod")).Returns(ad).Verifiable();
- mockHelper.Setup(h => h.PublicGetFilters(context, ad)).Returns(filterInfo).Verifiable();
- mockHelper.Setup(h => h.PublicInvokeAuthorizationFilters(context, filterInfo.AuthorizationFilters, ad)).Returns(authContext).Verifiable();
- ControllerActionInvokerHelper helper = mockHelper.Object;
- // Act
- helper.InvokeAction(context, "SomeMethod"); // No exception thrown
- // Assert
- mockHelper.Verify();
- }
- [Fact]
- public void InvokeActionMethodFilterWhereContinuationThrowsExceptionAndIsHandled()
- {
- // Arrange
- List<string> actions = new List<string>();
- MethodInfo mi = typeof(object).GetMethod("ToString");
- Dictionary<string, object> parameters = new Dictionary<string, object>();
- Exception exception = new Exception();
- ActionDescriptor action = new Mock<ActionDescriptor>().Object;
- ActionFilterImpl filter = new ActionFilterImpl()
- {
- OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actions.Add("OnActionExecuting"); },
- OnActionExecutedImpl = delegate(ActionExecutedContext filterContext)
- {
- actions.Add("OnActionExecuted");
- Assert.Same(exception, filterContext.Exception);
- Assert.Same(action, filterContext.ActionDescriptor);
- Assert.False(filterContext.ExceptionHandled);
- filterContext.ExceptionHandled = true;
- }
- };
- Func<ActionExecutedContext> continuation = delegate
- {
- actions.Add("Continuation");
- throw exception;
- };
- ActionExecutingContext context = new ActionExecutingContext(GetControllerContext(new EmptyController()), action, parameters);
- // Act
- ActionExecutedContext result = ControllerActionInvoker.InvokeActionMethodFilter(filter, context, continuation);
- // Assert
- Assert.Equal(3, actions.Count);
- Assert.Equal("OnActionExecuting", actions[0]);
- Assert.Equal("Continuation", actions[1]);
- Assert.Equal("OnActionExecuted", actions[2]);
- Assert.Same(exception, result.Exception);
- Assert.Same(action, result.ActionDescriptor);
- Assert.True(result.ExceptionHandled);
- }
- [Fact]
- public void InvokeActionMethodFilterWhereContinuationThrowsExceptionAndIsNotHandled()
- {
- // Arrange
- List<string> actions = new List<string>();
- Dictionary<string, object> parameters = new Dictionary<string, object>();
- ActionDescriptor action = new Mock<ActionDescriptor>().Object;
- ActionFilterImpl filter = new ActionFilterImpl()
- {
- OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actions.Add("OnActionExecuting"); },
- OnActionExecutedImpl = delegate(ActionExecutedContext filterContext)
- {
- Assert.NotNull(filterContext.Exception);
- Assert.Equal("Some exception message.", filterContext.Exception.Message);
- Assert.Same(action, filterContext.ActionDescriptor);
- actions.Add("OnActionExecuted");
- }
- };
- Func<ActionExecutedContext> continuation = delegate
- {
- actions.Add("Continuation");
- throw new Exception("Some exception message.");
- };
- ActionExecutingContext context = new ActionExecutingContext(GetControllerContext(new EmptyController()), action, parameters);
- // Act & Assert
- Assert.Throws<Exception>(
- delegate { ControllerActionInvoker.InvokeActionMethodFilter(filter, context, continuation); },
- "Some exception message.");
- Assert.Equal(3, actions.Count);
- Assert.Equal("OnActionExecuting", actions[0]);
- Assert.Equal("Continuation", actions[1]);
- Assert.Equal("OnActionExecuted", actions[2]);
- }
- [Fact]
- public void InvokeActionMethodFilterWhereContinuationThrowsThreadAbortException()
- {
- // Arrange
- List<string> actions = new List<string>();
- ActionResult actionResult = new EmptyResult();
- ActionDescriptor action = new Mock<ActionDescriptor>().Object;
- ActionFilterImpl filter = new ActionFilterImpl()
- {
- OnActionExecutingImpl = delegate(ActionExecutingContext filterContext) { actions.Add("OnActionExecuting"); },
- OnActionExecutedImpl = delegate(ActionExecutedContext filterContext)
- {
- Thread.ResetAbort();
- actions.Add("OnActionExecuted");
- Assert.Null(filterContext.Exception);
- Assert.False(filterContext.ExceptionHandled);
- Assert.Same(action, filterContext.ActionDescriptor);
- }
- };
- Func<ActionExecutedContext> continuation = delegate
- {
- actions.Add("Continuation");
- Thread.CurrentThread.Abort();
- return null;
- };
- ActionExecutingContext context = new ActionExecutingContext(new Mock<ControllerContext>().Object, action, new Dictionary<string, object>());
- // Act & Assert
- Assert.Throws<ThreadAbortException>(
- delegate { ControllerActionInvoker.InvokeActionMethodFilter(filter, context, continuation); },
- "Thread was being aborted.");
- Assert.Equal(3, actions.Count);
- Assert.Equal("OnActionExecuting", actions[0]);
- Assert.Equal("Continuation", actions[1]);
- Assert.Equal("OnActionExecuted", actions[2]);
- }
- [Fact]
- public void InvokeActionMethodFilterWhereOnActionExecutingCancels()
- {
- // Arrange
- bool wasCalled = false;
- ActionDescriptor ad = new Mock<ActionDescriptor>().Object;
- Dictionary<string, object> parameters = new Dictionary<string, object>();
- ActionResult actionResult = new EmptyResult();
- ActionDescriptor action = new Mock<ActionDescriptor>().Object;
- ActionFilterImpl filter = new ActionFilterImpl()
- {
- OnActionExecutingImpl = delegate(ActionExecutingContext filterContext)
- {
- Assert.False(wasCalled);
- wasCalled = true;
- filterContext.Result = actionResult;
- },
- };
- Func<ActionExecutedContext> continuation = delegate
- {
- Assert.True(false, "The continuation should not be called.");
- return null;
- };
- ActionExecutingContext context = new ActionExecutingContext(GetControllerContext(new EmptyController()), action, parameters);
- // Act
- ActionExecutedContext result = ControllerActionInvoker.InvokeActionMethodFilter(filter, context, continuation);
- // Assert
- Assert.True(wasCalled);
- Assert.Null(result.Exception);
- Assert.True(result.Canceled);
- Assert.Same(actionResult, result.Result);
- Assert.Same(action, result.ActionDescriptor);
- }
- [Fact]
- public void InvokeActionMethodFilterWithNormalControlFlow()
- {
- // Arrange
- List<string> actions = new List<string>();
- Dictionary<string, object> parameters = new Dictionary<string, object>();
- ActionDescriptor action = new Mock<ActionDescriptor>().Object;
- ActionExecutingContext preContext = new ActionExecutingContext(GetControllerContext(new EmptyController()), action, parameters);
- Mock<ActionExecutedContext> mockPostContext = new Mock<ActionExecutedContext>();
- ActionFilterImpl filter = new ActionFilterImpl()
- {
- OnActionExecutingImpl = delegate(ActionExecutingContext filterContext)
- {
- Assert.Same(parameters, filterContext.ActionParameters);
- Assert.Null(filterContext.Result);
- actions.Add("OnActionExecuting");
- },
- OnActionExecutedImpl = delegate(ActionExecutedContext filterContext)
- {
- Assert.Equal(mockPostContext.Object, filterContext);
- actions.Add("OnActionExecuted");
- }
- };
- Func<ActionExecutedContext> continuation = delegate
- {
- actions.Add("Continuation");
- return mockPostContext.Object;
- };
- // Act
- ActionExecutedContext result = ControllerActionInvoker.InvokeActionMethodFilter(filter, preContext, continuation);
- // Assert
- Assert.Equal(3, actions.Count);
- Assert.Equal("OnActionExecuting", actions[0]);
- Assert.Equal("Continuation", actions[1]);
- Assert.Equal("OnActionExecuted", actions[2]);
- Assert.Same(result, mockPostContext.Object);
- }
- [Fact]
- public void InvokeActionInvokesExceptionFiltersAndExecutesResultIfExceptionHandled()
- {
- // Arrange
- ControllerBase controller = new Mock<ControllerBase>().Object;
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new Mock<ControllerDescriptor>().Object;
- ActionDescriptor ad = new Mock<ActionDescriptor>().Object;
- FilterInfo filterInfo = new FilterInfo();
- Exception exception = new Exception();
- ActionResult actionResult = new EmptyResult();
- ExceptionContext exContext = new ExceptionContext(context, exception)
- {
- ExceptionHandled = true,
- Result = actionResult
- };
- Mock<ControllerActionInvokerHelper> mockHelper = new Mock<ControllerActionInvokerHelper>() { CallBase = true };
- mockHelper.Setup(h => h.PublicGetControllerDescriptor(context)).Returns(cd).Verifiable();
- mockHelper.Setup(h => h.PublicFindAction(context, cd, "SomeMethod")).Returns(ad).Verifiable();
- mockHelper.Setup(h => h.PublicGetFilters(context, ad)).Returns(filterInfo).Verifiable();
- mockHelper.Setup(h => h.PublicInvokeAuthorizationFilters(context, filterInfo.AuthorizationFilters, ad)).Throws(exception).Verifiable();
- mockHelper.Setup(h => h.PublicInvokeExceptionFilters(context, filterInfo.ExceptionFilters, exception)).Returns(exContext).Verifiable();
- mockHelper.Setup(h => h.PublicInvokeActionResult(context, actionResult)).Verifiable();
- ControllerActionInvokerHelper helper = mockHelper.Object;
- // Act
- bool retVal = helper.InvokeAction(context, "SomeMethod");
- Assert.True(retVal);
- mockHelper.Verify();
- }
- [Fact]
- public void InvokeActionInvokesExceptionFiltersAndRethrowsExceptionIfNotHandled()
- {
- // Arrange
- ControllerBase controller = new Mock<ControllerBase>().Object;
- ControllerContext context = GetControllerContext(controller);
- ControllerDescriptor cd = new Mock<ControllerDescriptor>().Object;
- ActionDescriptor ad = new Mock<ActionDescriptor>().Object;
- FilterInfo filterInfo = new FilterInfo();
- Exception exception = new Exception();
- ExceptionContext exContext = new ExceptionContext(context, exception);
- Mock<ControllerActionInvokerHelper> mockHelper = new Mock<ControllerActionInvokerHelper>() { CallBase = true };
- mockHelper.Setup(h => h.PublicGetControllerDescriptor(context)).Returns(cd).Verifiable();
- mockHelper.Setup(h => h.PublicFindAction(context, cd, "