[Fixes #662] Throw if controller cannot be activated

This commit is contained in:
Ajay Bhargav Baaskaran 2015-04-21 16:17:45 -07:00
parent 4df7d52210
commit 1511ea34a8
4 changed files with 72 additions and 26 deletions

View File

@ -62,6 +62,17 @@ namespace Microsoft.AspNet.Mvc
} }
var controllerType = actionDescriptor.ControllerTypeInfo.AsType(); var controllerType = actionDescriptor.ControllerTypeInfo.AsType();
var controllerTypeInfo = controllerType.GetTypeInfo();
if (controllerTypeInfo.IsValueType ||
controllerTypeInfo.IsInterface ||
controllerTypeInfo.IsAbstract ||
(controllerTypeInfo.IsGenericType && controllerTypeInfo.IsGenericTypeDefinition))
{
var message = Resources.FormatValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated(
controllerType.FullName, GetType().FullName);
throw new InvalidOperationException(message);
}
var controller = _controllerActivator.Create(actionContext, controllerType); var controller = _controllerActivator.Create(actionContext, controllerType);
ActivateProperties(controller, actionContext); ActivateProperties(controller, actionContext);
@ -87,13 +98,6 @@ namespace Microsoft.AspNet.Mvc
protected virtual void ActivateProperties([NotNull] object controller, [NotNull] ActionContext context) protected virtual void ActivateProperties([NotNull] object controller, [NotNull] ActionContext context)
{ {
var controllerType = controller.GetType(); var controllerType = controller.GetType();
var controllerTypeInfo = controllerType.GetTypeInfo();
if (controllerTypeInfo.IsValueType)
{
var message = Resources.FormatValueTypesCannotBeActivated(GetType().FullName);
throw new InvalidOperationException(message);
}
var propertiesToActivate = _activateActions.GetOrAdd(controllerType, var propertiesToActivate = _activateActions.GetOrAdd(controllerType,
_getPropertiesToActivate); _getPropertiesToActivate);

View File

@ -1082,22 +1082,6 @@ namespace Microsoft.AspNet.Mvc.Core
return string.Format(CultureInfo.CurrentCulture, GetString("ActionResult_ActionReturnValueCannotBeNull"), p0); return string.Format(CultureInfo.CurrentCulture, GetString("ActionResult_ActionReturnValueCannotBeNull"), p0);
} }
/// <summary>
/// Value types cannot be activated by '{0}'.
/// </summary>
internal static string ValueTypesCannotBeActivated
{
get { return GetString("ValueTypesCannotBeActivated"); }
}
/// <summary>
/// Value types cannot be activated by '{0}'.
/// </summary>
internal static string FormatValueTypesCannotBeActivated(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ValueTypesCannotBeActivated"), p0);
}
/// <summary> /// <summary>
/// The type '{0}' must derive from '{1}'. /// The type '{0}' must derive from '{1}'.
/// </summary> /// </summary>
@ -1786,6 +1770,22 @@ namespace Microsoft.AspNet.Mvc.Core
return string.Format(CultureInfo.CurrentCulture, GetString("TempData_CannotSerializeDictionary"), p0, p1); return string.Format(CultureInfo.CurrentCulture, GetString("TempData_CannotSerializeDictionary"), p0, p1);
} }
/// <summary>
/// The type '{0}' cannot be activated by '{1}' because it is either a value type, an interface, an abstract class or an open generic type.
/// </summary>
internal static string ValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated
{
get { return GetString("ValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated"); }
}
/// <summary>
/// The type '{0}' cannot be activated by '{1}' because it is either a value type, an interface, an abstract class or an open generic type.
/// </summary>
internal static string FormatValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated"), p0, p1);
}
private static string GetString(string name, params string[] formatterNames) private static string GetString(string name, params string[] formatterNames)
{ {
var value = _resourceManager.GetString(name); var value = _resourceManager.GetString(name);

View File

@ -319,9 +319,6 @@
<data name="ActionResult_ActionReturnValueCannotBeNull" xml:space="preserve"> <data name="ActionResult_ActionReturnValueCannotBeNull" xml:space="preserve">
<value>Cannot return null from an action method with a return type of '{0}'.</value> <value>Cannot return null from an action method with a return type of '{0}'.</value>
</data> </data>
<data name="ValueTypesCannotBeActivated" xml:space="preserve">
<value>Value types cannot be activated by '{0}'.</value>
</data>
<data name="TypeMustDeriveFromType" xml:space="preserve"> <data name="TypeMustDeriveFromType" xml:space="preserve">
<value>The type '{0}' must derive from '{1}'.</value> <value>The type '{0}' must derive from '{1}'.</value>
</data> </data>
@ -460,4 +457,7 @@
<data name="TempData_CannotSerializeDictionary" xml:space="preserve"> <data name="TempData_CannotSerializeDictionary" xml:space="preserve">
<value>The '{0}' cannot serialize a dictionary with a key of type '{1}' to session state.</value> <value>The '{0}' cannot serialize a dictionary with a key of type '{1}' to session state.</value>
</data> </data>
<data name="ValueInterfaceAbstractOrOpenGenericTypesCannotBeActivated" xml:space="preserve">
<value>The type '{0}' cannot be activated by '{1}' because it is either a value type, an interface, an abstract class or an open generic type.</value>
</data>
</root> </root>

View File

@ -188,6 +188,33 @@ namespace Microsoft.AspNet.Mvc.Core
"' cannot be activated.", exception.Message); "' cannot be activated.", exception.Message);
} }
[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 services = GetServices();
var httpContext = new DefaultHttpContext
{
RequestServices = services
};
var context = new ActionContext(httpContext, new RouteData(), actionDescriptor);
var factory = new DefaultControllerFactory(new DefaultControllerActivator(new DefaultTypeActivatorCache()));
// Act and Assert
var exception = Assert.Throws<InvalidOperationException>(() => factory.CreateController(context));
Assert.Equal("The type '" + type.FullName + "' cannot be activated by '" + typeof(DefaultControllerFactory) +
"' because it is either a value type, an interface, an abstract class or an open generic type.",
exception.Message);
}
[Fact] [Fact]
public void DefaultControllerFactory_DisposesIDisposableController() public void DefaultControllerFactory_DisposesIDisposableController()
{ {
@ -290,5 +317,20 @@ namespace Microsoft.AspNet.Mvc.Core
{ {
} }
private class OpenGenericType<T> : Controller
{
}
private abstract class AbstractType : Controller
{
}
private interface InterfaceType
{
}
} }
} }