diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Controllers/DefaultControllerActivator.cs b/src/Microsoft.AspNetCore.Mvc.Core/Controllers/DefaultControllerActivator.cs index fc35b6286d..d54cef2124 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Controllers/DefaultControllerActivator.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Controllers/DefaultControllerActivator.cs @@ -46,16 +46,12 @@ namespace Microsoft.AspNetCore.Mvc.Controllers } var controllerTypeInfo = controllerContext.ActionDescriptor.ControllerTypeInfo; - if (controllerTypeInfo.IsValueType || - controllerTypeInfo.IsInterface || - controllerTypeInfo.IsAbstract || - (controllerTypeInfo.IsGenericType && controllerTypeInfo.IsGenericTypeDefinition)) - { - var message = Resources.FormatValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated( - controllerTypeInfo.FullName, - GetType().FullName); - throw new InvalidOperationException(message); + if (controllerTypeInfo == null) + { + throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( + nameof(controllerContext.ActionDescriptor.ControllerTypeInfo), + nameof(ControllerContext.ActionDescriptor))); } var serviceProvider = controllerContext.HttpContext.RequestServices; diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewComponents/DefaultViewComponentActivator.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewComponents/DefaultViewComponentActivator.cs index 01b048cfe3..7a8edaa71a 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewComponents/DefaultViewComponentActivator.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewComponents/DefaultViewComponentActivator.cs @@ -45,17 +45,12 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents } var componentType = context.ViewComponentDescriptor.TypeInfo; - - if (componentType.IsValueType || - componentType.IsInterface || - componentType.IsAbstract || - (componentType.IsGenericType && componentType.IsGenericTypeDefinition)) + + if (componentType == null) { - var message = Resources.FormatValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated( - componentType.FullName, - GetType().FullName); - - throw new InvalidOperationException(message); + throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( + nameof(context.ViewComponentDescriptor.TypeInfo), + nameof(context.ViewComponentDescriptor))); } var viewComponent = _typeActivatorCache.CreateInstance( diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/ControllerFeatureProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/ControllerFeatureProviderTest.cs index d4579aad0b..e0d5102a54 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/ControllerFeatureProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/ControllerFeatureProviderTest.cs @@ -121,6 +121,21 @@ namespace Microsoft.AspNetCore.Mvc.Controllers // Assert Assert.Empty(feature.Controllers); } + + [Fact] + public void ValueTypeClass_IsNotController() + { + // Arrange + var controllerType = typeof(int).GetTypeInfo(); + var manager = GetApplicationPartManager(controllerType); + var feature = new ControllerFeature(); + + // Act + manager.PopulateFeature(feature); + + // Assert + Assert.Empty(feature.Controllers); + } [Fact] public void AbstractClass_IsNotController() diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerActivatorTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerActivatorTest.cs index c45c8d775a..0838bfc7df 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerActivatorTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Controllers/DefaultControllerActivatorTest.cs @@ -58,38 +58,7 @@ namespace Microsoft.AspNetCore.Mvc.Controllers // Assert Assert.Equal(true, controller.Disposed); } - - [Theory] - [InlineData(typeof(int))] - [InlineData(typeof(OpenGenericType<>))] - [InlineData(typeof(AbstractType))] - [InlineData(typeof(InterfaceType))] - public void CreateController_ThrowsIfControllerCannotBeActivated(Type type) - { - // Arrange - var actionDescriptor = new ControllerActionDescriptor - { - ControllerTypeInfo = type.GetTypeInfo() - }; - - var context = new ControllerContext() - { - ActionDescriptor = actionDescriptor, - HttpContext = new DefaultHttpContext() - { - RequestServices = GetServices(), - }, - }; - var factory = new DefaultControllerActivator(new TypeActivatorCache()); - - // Act and Assert - var exception = Assert.Throws(() => factory.Create(context)); - Assert.Equal( - $"The type '{type.FullName}' cannot be activated by '{typeof(DefaultControllerActivator).FullName}' " + - "because it is either a value type, an interface, an abstract class or an open generic type.", - exception.Message); - } - + [Fact] public void DefaultControllerActivator_ReleasesNonIDisposableController() { @@ -174,18 +143,6 @@ namespace Microsoft.AspNetCore.Mvc.Controllers { } - private class OpenGenericType : Controller - { - } - - private abstract class AbstractType : Controller - { - } - - private interface InterfaceType - { - } - private class MyController : IDisposable { public bool Disposed { get; set; } diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponents/DefaultViewComponentActivatorTests.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponents/DefaultViewComponentActivatorTests.cs index 58f0402770..24b940460a 100644 --- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponents/DefaultViewComponentActivatorTests.cs +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponents/DefaultViewComponentActivatorTests.cs @@ -38,41 +38,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents Assert.Same(context, instance.ViewComponentContext); } - [Theory] - [InlineData(typeof(int))] - [InlineData(typeof(OpenGenericType<>))] - [InlineData(typeof(AbstractType))] - [InlineData(typeof(InterfaceType))] - public void Create_ThrowsIfControllerCannotBeActivated(Type type) - { - // Arrange - var actionDescriptor = new ViewComponentDescriptor - { - TypeInfo = type.GetTypeInfo() - }; - - var context = new ViewComponentContext - { - ViewComponentDescriptor = actionDescriptor, - ViewContext = new ViewContext - { - HttpContext = new DefaultHttpContext() - { - RequestServices = Mock.Of() - }, - } - }; - - var activator = new DefaultViewComponentActivator(new TypeActivatorCache()); - - // Act and Assert - var exception = Assert.Throws(() => activator.Create(context)); - Assert.Equal( - $"The type '{type.FullName}' cannot be activated by '{typeof(DefaultViewComponentActivator).FullName}' " + - "because it is either a value type, an interface, an abstract class or an open generic type.", - exception.Message); - } - [Fact] public void DefaultViewComponentActivator_ActivatesViewComponentContext_IgnoresNonPublic() { @@ -116,18 +81,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents }; } - private class OpenGenericType : Controller - { - } - - private abstract class AbstractType : Controller - { - } - - private interface InterfaceType - { - } - private class TestViewComponent : ViewComponent { public Task ExecuteAsync() diff --git a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponents/ViewComponentConventionsTest.cs b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponents/ViewComponentConventionsTest.cs index ec37d26fe6..cbcef0f599 100644 --- a/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponents/ViewComponentConventionsTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.ViewFeatures.Test/ViewComponents/ViewComponentConventionsTest.cs @@ -35,6 +35,9 @@ namespace Microsoft.AspNetCore.Mvc.ViewComponents // The Attribute does apply to derived classes. [InlineData(typeof(WithAttribute), true)] [InlineData(typeof(DerivedWithAttribute), true)] + + // Value types cannot be view components + [InlineData(typeof(int), false)] public void IsComponent(Type type, bool expected) { // Arrange & Act