Fix for issue #610 - Ignore internal and nested types
This change exludes internal and nested types from being treated as controllers. This is consistent with MVC5's behavior. DefaultActionSelectionConventions was primarily tested through running action selection. I wanted to also test the methods with substantial logic in this class, so I moved a spate of a classes from private classes inside of the integration tests to public classes so they could be shared. I also added tests to fill gaps in DefaultActionSelectionConventions, which is the vast vast majority of this change.
This commit is contained in:
parent
9f8c656b31
commit
bff94f169f
|
|
@ -35,6 +35,10 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
if (!typeInfo.IsClass ||
|
||||
typeInfo.IsAbstract ||
|
||||
|
||||
// We only consider public top-level classes as controllers. IsPublic returns false for nested
|
||||
// classes, regardless of visibility modifiers.
|
||||
!typeInfo.IsPublic ||
|
||||
typeInfo.ContainsGenericParameters)
|
||||
{
|
||||
return false;
|
||||
|
|
@ -84,7 +88,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
/// </summary>
|
||||
/// <param name="method">The <see cref="MethodInfo"/>.</param>
|
||||
/// <returns>true if the method is a valid action. Otherwise, false.</returns>
|
||||
protected virtual bool IsValidActionMethod(MethodInfo method)
|
||||
public virtual bool IsValidActionMethod(MethodInfo method)
|
||||
{
|
||||
return
|
||||
method.IsPublic &&
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
{
|
||||
public class ActionAttributeTests
|
||||
{
|
||||
private DefaultActionDiscoveryConventions _actionDiscoveryConventions = new DefaultActionDiscoveryConventions();
|
||||
private IEnumerable<Assembly> _controllerAssemblies = new[] { Assembly.GetExecutingAssembly() };
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET")]
|
||||
[InlineData("PUT")]
|
||||
|
|
@ -116,7 +113,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
public void NonActionAttribute_ActionNotReachable(string actionName)
|
||||
{
|
||||
// Arrange
|
||||
var actionDescriptorProvider = GetActionDescriptorProvider(_actionDiscoveryConventions);
|
||||
var actionDescriptorProvider = GetActionDescriptorProvider();
|
||||
|
||||
// Act
|
||||
var result = actionDescriptorProvider.GetDescriptors()
|
||||
|
|
@ -185,13 +182,9 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
Assert.Equal(actionName, result.Name);
|
||||
}
|
||||
|
||||
private async Task<ActionDescriptor> InvokeActionSelector(RouteContext context)
|
||||
{
|
||||
return await InvokeActionSelector(context, _actionDiscoveryConventions);
|
||||
}
|
||||
|
||||
private async Task<ActionDescriptor> InvokeActionSelector(RouteContext context,
|
||||
DefaultActionDiscoveryConventions actionDiscoveryConventions)
|
||||
private async Task<ActionDescriptor> InvokeActionSelector(
|
||||
RouteContext context,
|
||||
IActionDiscoveryConventions actionDiscoveryConventions = null)
|
||||
{
|
||||
var actionDescriptorProvider = GetActionDescriptorProvider(actionDiscoveryConventions);
|
||||
var descriptorProvider =
|
||||
|
|
@ -211,13 +204,22 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
return await defaultActionSelector.SelectAsync(context);
|
||||
}
|
||||
|
||||
private ReflectedActionDescriptorProvider GetActionDescriptorProvider(DefaultActionDiscoveryConventions actionDiscoveryConventions)
|
||||
private ReflectedActionDescriptorProvider GetActionDescriptorProvider(
|
||||
IActionDiscoveryConventions actionDiscoveryConventions = null)
|
||||
{
|
||||
var controllerAssemblyProvider = new Mock<IControllerAssemblyProvider>();
|
||||
controllerAssemblyProvider.SetupGet(x => x.CandidateAssemblies).Returns(_controllerAssemblies);
|
||||
var controllerAssemblyProvider = new StaticControllerAssemblyProvider();
|
||||
|
||||
if (actionDiscoveryConventions == null)
|
||||
{
|
||||
var controllerTypes = typeof(ActionAttributeTests)
|
||||
.GetNestedTypes(BindingFlags.NonPublic)
|
||||
.Select(t => t.GetTypeInfo());
|
||||
|
||||
actionDiscoveryConventions = new StaticActionDiscoveryConventions(controllerTypes.ToArray());
|
||||
}
|
||||
|
||||
return new ReflectedActionDescriptorProvider(
|
||||
controllerAssemblyProvider.Object,
|
||||
controllerAssemblyProvider,
|
||||
actionDiscoveryConventions,
|
||||
null,
|
||||
new MockMvcOptionsAccessor(),
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ using System.ComponentModel.Design;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.DependencyInjection.NestedProviders;
|
||||
using Moq;
|
||||
|
|
@ -18,11 +18,8 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
public class ActionSelectionConventionTests
|
||||
public class DefaultActionDiscoveryConventionsActionSelectionTests
|
||||
{
|
||||
private DefaultActionDiscoveryConventions _actionDiscoveryConventions = new DefaultActionDiscoveryConventions();
|
||||
private IEnumerable<Assembly> _controllerAssemblies = new[] { Assembly.GetExecutingAssembly() };
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET")]
|
||||
[InlineData("POST")]
|
||||
|
|
@ -156,10 +153,16 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
|
||||
private async Task<ActionDescriptor> InvokeActionSelector(RouteContext context)
|
||||
{
|
||||
return await InvokeActionSelector(context, _actionDiscoveryConventions);
|
||||
var controllerTypeInfos = typeof(DefaultActionDiscoveryConventionsActionSelectionTests)
|
||||
.GetNestedTypes(BindingFlags.NonPublic)
|
||||
.Select(ct => ct.GetTypeInfo())
|
||||
.ToArray();
|
||||
|
||||
var conventions = new StaticActionDiscoveryConventions(controllerTypeInfos);
|
||||
return await InvokeActionSelector(context, conventions);
|
||||
}
|
||||
|
||||
private async Task<ActionDescriptor> InvokeActionSelector(RouteContext context,
|
||||
private async Task<ActionDescriptor> InvokeActionSelector(RouteContext context,
|
||||
DefaultActionDiscoveryConventions actionDiscoveryConventions)
|
||||
{
|
||||
var actionDescriptorProvider = GetActionDescriptorProvider(actionDiscoveryConventions);
|
||||
|
|
@ -182,8 +185,9 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
|
||||
private ReflectedActionDescriptorProvider GetActionDescriptorProvider(DefaultActionDiscoveryConventions actionDiscoveryConventions)
|
||||
{
|
||||
var assemblies = new Assembly[] { typeof(DefaultActionDiscoveryConventionsActionSelectionTests).GetTypeInfo().Assembly, };
|
||||
var controllerAssemblyProvider = new Mock<IControllerAssemblyProvider>();
|
||||
controllerAssemblyProvider.SetupGet(x => x.CandidateAssemblies).Returns(_controllerAssemblies);
|
||||
controllerAssemblyProvider.SetupGet(x => x.CandidateAssemblies).Returns(assemblies);
|
||||
return new ReflectedActionDescriptorProvider(
|
||||
controllerAssemblyProvider.Object,
|
||||
actionDiscoveryConventions,
|
||||
|
|
@ -206,6 +210,15 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
|
||||
private class CustomActionConvention : DefaultActionDiscoveryConventions
|
||||
{
|
||||
public override bool IsController([NotNull]TypeInfo typeInfo)
|
||||
{
|
||||
return
|
||||
typeof(DefaultActionDiscoveryConventionsActionSelectionTests)
|
||||
.GetNestedTypes(BindingFlags.NonPublic)
|
||||
.Select(ct => ct.GetTypeInfo())
|
||||
.Contains(typeInfo);
|
||||
}
|
||||
|
||||
public override IEnumerable<string> GetSupportedHttpMethods(MethodInfo methodInfo)
|
||||
{
|
||||
if (methodInfo.Name.Equals("PostSomething", StringComparison.OrdinalIgnoreCase))
|
||||
|
|
@ -217,8 +230,6 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
}
|
||||
}
|
||||
|
||||
#region Controller Classes
|
||||
|
||||
private class MixedRpcAndRestController
|
||||
{
|
||||
public void Index()
|
||||
|
|
@ -304,8 +315,6 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
public void Index(string s)
|
||||
{ }
|
||||
}
|
||||
|
||||
#endregion Controller Classes
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Mvc.DefaultActionDiscoveryConventionsControllers;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class DefaultActionDiscoveryConventionsTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("GetFromDerived", true)]
|
||||
[InlineData("NewMethod", true)] // "NewMethod" is a public method declared with keyword "new".
|
||||
[InlineData("GetFromBase", true)]
|
||||
public void IsValidActionMethod_WithInheritedMethods(string methodName, bool expected)
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var method = typeof(DerivedController).GetMethod(methodName);
|
||||
Assert.NotNull(method);
|
||||
|
||||
// Act
|
||||
var isValid = conventions.IsValidActionMethod(method);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, isValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsValidActionMethod_OverridenMethodControllerClass()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var method = typeof(BaseController).GetMethod("Redirect");
|
||||
Assert.NotNull(method);
|
||||
|
||||
// Act
|
||||
var isValid = conventions.IsValidActionMethod(method);
|
||||
|
||||
// Assert
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsValidActionMethod_PrivateMethod_FromUserDefinedController()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var method = typeof(DerivedController).GetMethod(
|
||||
"PrivateMethod",
|
||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
Assert.NotNull(method);
|
||||
|
||||
// Act
|
||||
var isValid = conventions.IsValidActionMethod(method);
|
||||
|
||||
// Assert
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsValidActionMethod_OperatorOverloadingMethod_FromOperatorOverloadingController()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var method = typeof(OperatorOverloadingController).GetMethod("op_Addition");
|
||||
Assert.NotNull(method);
|
||||
Assert.True(method.IsSpecialName);
|
||||
|
||||
// Act
|
||||
var isValid = conventions.IsValidActionMethod(method);
|
||||
|
||||
// Assert
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsValidActionMethod_GenericMethod_FromUserDefinedController()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var method = typeof(DerivedController).GetMethod("GenericMethod");
|
||||
Assert.NotNull(method);
|
||||
|
||||
// Act
|
||||
var isValid = conventions.IsValidActionMethod(method);
|
||||
|
||||
// Assert
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsValidActionMethod_OverridenNonActionMethod()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var method = typeof(DerivedController).GetMethod("OverridenNonActionMethod");
|
||||
Assert.NotNull(method);
|
||||
|
||||
// Act
|
||||
var isValid = conventions.IsValidActionMethod(method);
|
||||
|
||||
// Assert
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("Equals")]
|
||||
[InlineData("GetHashCode")]
|
||||
[InlineData("MemberwiseClone")]
|
||||
[InlineData("ToString")]
|
||||
public void IsValidActionMethod_OverriddenMethodsFromObjectClass(string methodName)
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var method = typeof(DerivedController).GetMethod(
|
||||
methodName,
|
||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
Assert.NotNull(method);
|
||||
|
||||
// Act
|
||||
var isValid = conventions.IsValidActionMethod(method);
|
||||
|
||||
// Assert
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("StaticMethod")]
|
||||
[InlineData("ProtectedStaticMethod")]
|
||||
[InlineData("PrivateStaticMethod")]
|
||||
public void IsValidActionMethod_StaticMethods(string methodName)
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var method = typeof(DerivedController).GetMethod(
|
||||
methodName,
|
||||
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
Assert.NotNull(method);
|
||||
|
||||
// Act
|
||||
var isValid = conventions.IsValidActionMethod(method);
|
||||
|
||||
// Assert
|
||||
Assert.False(isValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_UserDefinedClass()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(BaseController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.True(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_FrameworkControllerClass()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(Controller).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.False(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_UserDefinedControllerClass()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(DefaultActionDiscoveryConventionsControllers.Controller).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.False(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_Interface()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(IController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.False(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_AbstractClass()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(AbstractController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.False(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_DerivedAbstractClass()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(DerivedAbstractController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.True(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_OpenGenericClass()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(OpenGenericController<>).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.False(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_ClosedGenericClass()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(OpenGenericController<string>).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.False(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_DerivedGenericClass()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(DerivedGenericController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.True(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_Poco_WithNamingConvention()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(PocoController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.True(isController);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsController_NoControllerSuffix()
|
||||
{
|
||||
// Arrange
|
||||
var conventions = new DefaultActionDiscoveryConventions();
|
||||
var typeInfo = typeof(NoSuffix).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var isController = conventions.IsController(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.True(isController);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These controllers are used to test the DefaultActionDiscoveryConventions implementation
|
||||
// which REQUIRES that they be public top-level classes. To avoid having to stub out the
|
||||
// implementation of this class to test it, they are just top level classes. Don't reuse
|
||||
// these outside this test - find a better way or use nested classes to keep the tests
|
||||
// independent.
|
||||
namespace Microsoft.AspNet.Mvc.DefaultActionDiscoveryConventionsControllers
|
||||
{
|
||||
public abstract class AbstractController : Mvc.Controller
|
||||
{
|
||||
}
|
||||
|
||||
public class DerivedAbstractController : AbstractController
|
||||
{
|
||||
}
|
||||
|
||||
public class BaseController : Mvc.Controller
|
||||
{
|
||||
public void GetFromBase() // Valid action method.
|
||||
{
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public virtual void OverridenNonActionMethod()
|
||||
{
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public virtual void NewMethod()
|
||||
{
|
||||
}
|
||||
|
||||
public override RedirectResult Redirect(string url)
|
||||
{
|
||||
return base.Redirect(url + "#RedirectOverride");
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedController : BaseController
|
||||
{
|
||||
public void GetFromDerived() // Valid action method.
|
||||
{
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public override void OverridenNonActionMethod()
|
||||
{
|
||||
}
|
||||
|
||||
public new void NewMethod() // Valid action method.
|
||||
{
|
||||
}
|
||||
|
||||
public void GenericMethod<T>()
|
||||
{
|
||||
}
|
||||
|
||||
private void PrivateMethod()
|
||||
{
|
||||
}
|
||||
|
||||
public static void StaticMethod()
|
||||
{
|
||||
}
|
||||
|
||||
protected static void ProtectedStaticMethod()
|
||||
{
|
||||
}
|
||||
|
||||
private static void PrivateStaticMethod()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Controller
|
||||
{
|
||||
}
|
||||
|
||||
public class OpenGenericController<T>
|
||||
{
|
||||
}
|
||||
|
||||
public class DerivedGenericController : OpenGenericController<string>
|
||||
{
|
||||
}
|
||||
|
||||
public interface IController
|
||||
{
|
||||
}
|
||||
|
||||
public class NoSuffix : Mvc.Controller
|
||||
{
|
||||
}
|
||||
|
||||
public class PocoController
|
||||
{
|
||||
}
|
||||
|
||||
public class OperatorOverloadingController : Mvc.Controller
|
||||
{
|
||||
public static OperatorOverloadingController operator +(
|
||||
OperatorOverloadingController c1,
|
||||
OperatorOverloadingController c2)
|
||||
{
|
||||
return new OperatorOverloadingController();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,9 +28,10 @@
|
|||
<Compile Include="ActionResults\RedirectToActionResultTest.cs" />
|
||||
<Compile Include="ActionResults\RedirectToRouteResultTest.cs" />
|
||||
<Compile Include="ActionResults\RedirectResultTest.cs" />
|
||||
<Compile Include="ActionSelectionConventionTests.cs" />
|
||||
<Compile Include="DefaultActionDiscoveryConventionsActionSelectionTests.cs" />
|
||||
<Compile Include="AntiXsrf\AntiForgeryOptionsTests.cs" />
|
||||
<Compile Include="ExpiringFileInfoCacheTest.cs" />
|
||||
<Compile Include="DefaultActionDiscoveryConventionsTests.cs" />
|
||||
<Compile Include="Extensions\ViewEngineDscriptorExtensionsTest.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\ReflectedParameterModelTests.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\ReflectedActionModelTests.cs" />
|
||||
|
|
@ -74,6 +75,7 @@
|
|||
<Compile Include="Rendering\DefaultViewEngineProviderTest.cs" />
|
||||
<Compile Include="Routing\AttributeRoutePrecedenceTests.cs" />
|
||||
<Compile Include="Routing\AttributeRouteTemplateTests.cs" />
|
||||
<Compile Include="StaticControllerAssemblyProvider.cs" />
|
||||
<Compile Include="TestController.cs" />
|
||||
<Compile Include="TypeHelperTest.cs" />
|
||||
<Compile Include="StaticActionDiscoveryConventions.cs" />
|
||||
|
|
@ -82,4 +84,4 @@
|
|||
<Compile Include="ViewComponentTests.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -14,117 +14,17 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
public class ReflectedActionDescriptorProviderTests
|
||||
{
|
||||
[Fact]
|
||||
public void GetDescriptors_GetsDescriptorsOnlyForValidActionsInBaseAndDerivedController()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionNames = GetActionNamesFromDerivedController();
|
||||
|
||||
// Assert
|
||||
// "NewMethod" is a public method declared with keyword "new".
|
||||
Assert.Equal(new[] { "GetFromDerived", "NewMethod", "GetFromBase" }, actionNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_OverridenRedirect_FromControllerClass()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionNames = GetDescriptors(typeof(BaseController).GetTypeInfo()).Select(a => a.Name);
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain("Redirect", actionNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_PrivateMethod_FromUserDefinedController()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionNames = GetActionNamesFromDerivedController();
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain("PrivateMethod", actionNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_Constructor_FromUserDefinedController()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionNames = GetActionNamesFromDerivedController();
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain("DerivedController", actionNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_OperatorOverloadingMethod_FromOperatorOverloadingController()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionDescriptors = GetDescriptors(typeof(OperatorOverloadingController).GetTypeInfo());
|
||||
|
||||
// Assert
|
||||
Assert.Empty(actionDescriptors);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_GenericMethod_FromUserDefinedController()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionNames = GetActionNamesFromDerivedController();
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain("GenericMethod", actionNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_OverridenNonActionMethod_FromDerivedController()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionNames = GetActionNamesFromDerivedController();
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain("OverridenNonActionMethod", actionNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_MethodsFromObjectClass_FromUserDefinedController()
|
||||
public void GetDescriptors_GetsDescriptorsOnlyForValidActions()
|
||||
{
|
||||
// Arrange
|
||||
var methodsFromObjectClass = typeof(object).GetMethods().Select(m => m.Name);
|
||||
var provider = GetProvider(typeof(PersonController).GetTypeInfo());
|
||||
|
||||
// Act
|
||||
var actionNames = GetActionNamesFromDerivedController();
|
||||
var descriptors = provider.GetDescriptors();
|
||||
var actionNames = descriptors.Select(ad => ad.Name);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(methodsFromObjectClass.Intersect(actionNames));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_StaticMethod_FromUserDefinedController()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionNames = GetActionNamesFromDerivedController();
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain("StaticMethod", actionNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_ProtectedStaticMethod_FromUserDefinedController()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionNames = GetActionNamesFromDerivedController();
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain("ProtectedStaticMethod", actionNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_Ignores_PrivateStaticMethod_FromUserDefinedController()
|
||||
{
|
||||
// Arrange & Act
|
||||
var actionNames = GetActionNamesFromDerivedController();
|
||||
|
||||
// Assert
|
||||
Assert.DoesNotContain("PrivateStaticMethod", actionNames);
|
||||
Assert.Equal(new[] { "GetPerson", "ListPeople", }, actionNames);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -276,7 +176,7 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
{
|
||||
// Arrange
|
||||
var filter = new MyFilterAttribute(1);
|
||||
var provider = GetProvider(typeof(BaseController).GetTypeInfo(), new IFilter[]
|
||||
var provider = GetProvider(typeof(PersonController).GetTypeInfo(), new IFilter[]
|
||||
{
|
||||
filter,
|
||||
});
|
||||
|
|
@ -289,11 +189,6 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
Assert.Same(filter, Assert.Single(filters));
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetActionNamesFromDerivedController()
|
||||
{
|
||||
return GetDescriptors(typeof(DerivedController).GetTypeInfo()).Select(a => a.Name).ToArray();
|
||||
}
|
||||
|
||||
private ReflectedActionDescriptorProvider GetProvider(
|
||||
TypeInfo controllerTypeInfo,
|
||||
IEnumerable<IFilter> filters = null)
|
||||
|
|
@ -334,93 +229,6 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
return provider.GetDescriptors();
|
||||
}
|
||||
|
||||
private class DerivedController : BaseController
|
||||
{
|
||||
public void GetFromDerived() // Valid action method.
|
||||
{
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public override void OverridenNonActionMethod()
|
||||
{
|
||||
}
|
||||
|
||||
public new void NewMethod() // Valid action method.
|
||||
{
|
||||
}
|
||||
|
||||
public void GenericMethod<T>()
|
||||
{
|
||||
}
|
||||
|
||||
private void PrivateMethod()
|
||||
{
|
||||
}
|
||||
|
||||
public static void StaticMethod()
|
||||
{
|
||||
}
|
||||
|
||||
protected static void ProtectedStaticMethod()
|
||||
{
|
||||
}
|
||||
|
||||
private static void PrivateStaticMethod()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class OperatorOverloadingController : Controller
|
||||
{
|
||||
public static OperatorOverloadingController operator +(
|
||||
OperatorOverloadingController c1,
|
||||
OperatorOverloadingController c2)
|
||||
{
|
||||
return new OperatorOverloadingController();
|
||||
}
|
||||
}
|
||||
|
||||
private class BaseController : Controller
|
||||
{
|
||||
public void GetFromBase() // Valid action method.
|
||||
{
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public virtual void OverridenNonActionMethod()
|
||||
{
|
||||
}
|
||||
|
||||
[NonAction]
|
||||
public virtual void NewMethod()
|
||||
{
|
||||
}
|
||||
|
||||
public override RedirectResult Redirect(string url)
|
||||
{
|
||||
return base.Redirect(url + "#RedirectOverride");
|
||||
}
|
||||
}
|
||||
|
||||
[MyFilter(2)]
|
||||
private class FiltersController
|
||||
{
|
||||
[MyFilter(3)]
|
||||
public void FilterAction()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class MyFilterAttribute : Attribute, IFilter
|
||||
{
|
||||
public MyFilterAttribute(int value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public int Value { get; private set; }
|
||||
}
|
||||
|
||||
private class HttpMethodController
|
||||
{
|
||||
[HttpPost]
|
||||
|
|
@ -429,6 +237,27 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
}
|
||||
}
|
||||
|
||||
private class PersonController
|
||||
{
|
||||
public void GetPerson()
|
||||
{ }
|
||||
|
||||
public void ListPeople()
|
||||
{ }
|
||||
|
||||
[NonAction]
|
||||
public void NotAnAction()
|
||||
{ }
|
||||
}
|
||||
|
||||
public class MyRouteConstraintAttribute : RouteConstraintAttribute
|
||||
{
|
||||
public MyRouteConstraintAttribute(bool blockNonAttributedActions)
|
||||
: base("key", "value", blockNonAttributedActions)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[MyRouteConstraintAttribute(blockNonAttributedActions: true)]
|
||||
private class BlockNonAttributedActionsController
|
||||
{
|
||||
|
|
@ -445,10 +274,21 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
}
|
||||
}
|
||||
|
||||
private class MyRouteConstraintAttribute : RouteConstraintAttribute
|
||||
private class MyFilterAttribute : Attribute, IFilter
|
||||
{
|
||||
public MyRouteConstraintAttribute(bool blockNonAttributedActions)
|
||||
: base("key", "value", blockNonAttributedActions)
|
||||
public MyFilterAttribute(int value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public int Value { get; private set; }
|
||||
}
|
||||
|
||||
[MyFilter(2)]
|
||||
private class FiltersController
|
||||
{
|
||||
[MyFilter(3)]
|
||||
public void FilterAction()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
/// <summary>
|
||||
/// An implementation of IControllerAssemblyProvider that provides just this assembly.
|
||||
/// </summary>
|
||||
public class StaticControllerAssemblyProvider : IControllerAssemblyProvider
|
||||
{
|
||||
public IEnumerable<Assembly> CandidateAssemblies
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return typeof(StaticActionDiscoveryConventions).GetTypeInfo().Assembly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue