Action invocation changes:

Changed 404s to throw
Propagate reflected exception
Add resources for specific errors
This commit is contained in:
Yishai Galatzer 2014-04-01 09:48:24 -07:00
parent 1b4754454b
commit 9756f74565
4 changed files with 125 additions and 74 deletions

View File

@ -1,6 +1,6 @@
using System;
using System.Reflection;
using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
@ -22,23 +22,18 @@ namespace Microsoft.AspNet.Mvc
var actionDescriptor = actionContext.ActionDescriptor as ReflectedActionDescriptor;
if (actionDescriptor == null)
{
return null;
throw new ArgumentException(
Resources.FormatDefaultControllerFactory_ActionDescriptorMustBeReflected(
typeof(ReflectedActionDescriptor)),
"actionContext");
}
try
{
var controller = _activator.CreateInstance(_serviceProvider, actionDescriptor.ControllerDescriptor.ControllerTypeInfo.AsType());
var controller = _activator.CreateInstance(_serviceProvider, actionDescriptor.ControllerDescriptor.ControllerTypeInfo.AsType());
// TODO: How do we feed the controller with context (need DI improvements)
InitializeController(controller, actionContext);
// TODO: How do we feed the controller with context (need DI improvements)
InitializeController(controller, actionContext);
return controller;
} // TODO: Should we not catch it here?
catch (ReflectionTypeLoadException)
{
}
return null;
return controller;
}
public void ReleaseController(object controller)

View File

@ -201,7 +201,7 @@ namespace Microsoft.AspNet.Mvc.Core
{
return string.Format(CultureInfo.CurrentCulture, GetString("ViewComponent_InvalidReturnValue"), p0, p1, p2);
}
/// <summary>
/// Replacing the action context is not supported.
/// </summary>
@ -234,6 +234,54 @@ namespace Microsoft.AspNet.Mvc.Core
return string.Format(CultureInfo.CurrentCulture, GetString("ActionInvokerFactory_CouldNotCreateInvoker"), p0);
}
/// <summary>
/// The action descriptor must be of type '{0}'.
/// </summary>
internal static string DefaultControllerFactory_ActionDescriptorMustBeReflected
{
get { return GetString("DefaultControllerFactory_ActionDescriptorMustBeReflected"); }
}
/// <summary>
/// The action descriptor must be of type '{0}'.
/// </summary>
internal static string FormatDefaultControllerFactory_ActionDescriptorMustBeReflected(object p0)
{
return string.Format(CultureInfo.CurrentCulture, GetString("DefaultControllerFactory_ActionDescriptorMustBeReflected"), p0);
}
/// <summary>
/// The '{0}' property of '{1}' must not be null.
/// </summary>
internal static string PropertyOfTypeCannotBeNull
{
get { return GetString("PropertyOfTypeCannotBeNull"); }
}
/// <summary>
/// The '{0}' property of '{1}' must not be null.
/// </summary>
internal static string FormatPropertyOfTypeCannotBeNull(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("PropertyOfTypeCannotBeNull"), p0, p1);
}
/// <summary>
/// The '{0}' must return a non null '{1}'.
/// </summary>
internal static string MethodMustReturnNotNullValue
{
get { return GetString("MethodMustReturnNotNullValue"); }
}
/// <summary>
/// The '{0}' must return a non null '{1}'.
/// </summary>
internal static string FormatMethodMustReturnNotNullValue(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("MethodMustReturnNotNullValue"), p0, p1);
}
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);

View File

@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.Core;
using Microsoft.AspNet.Mvc.Filters;
using Microsoft.AspNet.Mvc.ModelBinding;
@ -21,12 +23,12 @@ namespace Microsoft.AspNet.Mvc
private readonly List<IActionFilter> _actionFilters = new List<IActionFilter>();
private readonly List<IActionResultFilter> _actionResultFilters = new List<IActionResultFilter>();
public ReflectedActionInvoker(ActionContext actionContext,
ReflectedActionDescriptor descriptor,
IActionResultFactory actionResultFactory,
IControllerFactory controllerFactory,
IActionBindingContextProvider bindingContextProvider,
INestedProviderManager<FilterProviderContext> filterProvider)
public ReflectedActionInvoker([NotNull] ActionContext actionContext,
[NotNull] ReflectedActionDescriptor descriptor,
[NotNull] IActionResultFactory actionResultFactory,
[NotNull] IControllerFactory controllerFactory,
[NotNull] IActionBindingContextProvider bindingContextProvider,
[NotNull] INestedProviderManager<FilterProviderContext> filterProvider)
{
_actionContext = actionContext;
_descriptor = descriptor;
@ -34,6 +36,14 @@ namespace Microsoft.AspNet.Mvc
_controllerFactory = controllerFactory;
_bindingProvider = bindingContextProvider;
_filterProvider = filterProvider;
if (descriptor.MethodInfo == null)
{
throw new ArgumentException(
Resources.FormatPropertyOfTypeCannotBeNull(typeof(ReflectedActionDescriptor),
"MethodInfo"),
"descriptor");
}
}
public async Task InvokeActionAsync()
@ -54,67 +64,56 @@ namespace Microsoft.AspNet.Mvc
if (controller == null)
{
// TODO: See if these return 404s should turn into 500s
actionResult = new HttpStatusCodeResult(404);
throw new InvalidOperationException(
Resources.FormatMethodMustReturnNotNullValue(typeof(IControllerFactory),
"controller"));
}
else
{
var method = _descriptor.MethodInfo;
if (method == null)
if (_authorizationFilters.Count > 0)
{
var authZEndPoint = new AuthorizationFilterEndPoint();
_authorizationFilters.Add(authZEndPoint);
var authZContext = new AuthorizationFilterContext(_actionContext, filterMetaItems);
var authZPipeline = new FilterPipelineBuilder<AuthorizationFilterContext>(_authorizationFilters, authZContext);
await authZPipeline.InvokeAsync();
if (authZContext.ActionResult == null &&
!authZContext.HasFailed &&
authZEndPoint.EndPointCalled)
{
// TODO: See if these return 404s should turn into 500s
actionResult = new HttpStatusCodeResult(404);
actionResult = null;
}
else
{
if (_authorizationFilters.Count > 0)
{
var authZEndPoint = new AuthorizationFilterEndPoint();
_authorizationFilters.Add(authZEndPoint);
var authZContext = new AuthorizationFilterContext(_actionContext, filterMetaItems);
var authZPipeline = new FilterPipelineBuilder<AuthorizationFilterContext>(_authorizationFilters, authZContext);
await authZPipeline.InvokeAsync();
if (authZContext.ActionResult == null &&
!authZContext.HasFailed &&
authZEndPoint.EndPointCalled)
{
actionResult = null;
}
else
{
// User cleaned out the result but we failed or short circuited the end point.
actionResult = authZContext.ActionResult ?? new HttpStatusCodeResult(401);
}
}
else
{
actionResult = null;
}
if (actionResult == null)
{
var parameterValues = await GetParameterValues(_actionContext.ModelState);
var actionFilterContext = new ActionFilterContext(_actionContext,
filterMetaItems,
parameterValues);
var actionEndPoint = new ReflectedActionFilterEndPoint(_actionResultFactory, controller);
_actionFilters.Add(actionEndPoint);
var actionFilterPipeline = new FilterPipelineBuilder<ActionFilterContext>(_actionFilters,
actionFilterContext);
await actionFilterPipeline.InvokeAsync();
actionResult = actionFilterContext.ActionResult;
}
// User cleaned out the result but we failed or short circuited the end point.
actionResult = authZContext.ActionResult ?? new HttpStatusCodeResult(401);
}
}
else
{
actionResult = null;
}
if (actionResult == null)
{
var parameterValues = await GetParameterValues(_actionContext.ModelState);
var actionFilterContext = new ActionFilterContext(_actionContext,
filterMetaItems,
parameterValues);
var actionEndPoint = new ReflectedActionFilterEndPoint(_actionResultFactory, controller);
_actionFilters.Add(actionEndPoint);
var actionFilterPipeline = new FilterPipelineBuilder<ActionFilterContext>(_actionFilters,
actionFilterContext);
await actionFilterPipeline.InvokeAsync();
actionResult = actionFilterContext.ActionResult;
}
var actionResultFilterContext = new ActionResultFilterContext(_actionContext, filterMetaItems, actionResult);
var actionResultFilterEndPoint = new ActionResultFilterEndPoint();

View File

@ -159,4 +159,13 @@
<data name="ActionInvokerFactory_CouldNotCreateInvoker" xml:space="preserve">
<value>An action invoker could not be created for action '{0}'.</value>
</data>
<data name="DefaultControllerFactory_ActionDescriptorMustBeReflected" xml:space="preserve">
<value>The action descriptor must be of type '{0}'.</value>
</data>
<data name="PropertyOfTypeCannotBeNull" xml:space="preserve">
<value>The '{0}' property of '{1}' must not be null.</value>
</data>
<data name="MethodMustReturnNotNullValue" xml:space="preserve">
<value>The '{0}' must return a non null '{1}'.</value>
</data>
</root>