Remove Binder from Page and PageModel

This commit is contained in:
Ryan Brandenburg 2017-04-19 14:57:34 -07:00 committed by Ryan Nowak
parent f4d84f50cd
commit 5a184df808
10 changed files with 215 additions and 151 deletions

View File

@ -12,10 +12,14 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
{
public MethodInfo Method { get; set; }
public Func<Page, object, Task<IActionResult>> Executor { get; set; }
public Func<object, object[], Task<IActionResult>> Executor { get; set; }
public string HttpMethod { get; set; }
public StringSegment FormAction { get; set; }
public HandlerParameterDescriptor[] Parameters { get; set; }
public bool OnPage { get; set; }
}
}
}

View File

@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.Abstractions;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
{
public class HandlerParameterDescriptor : ParameterDescriptor
{
public object DefaultValue { get; set; }
public ParameterInfo Parameter { get; set; }
}
}

View File

@ -5,15 +5,17 @@ using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.Extensions.Internal;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
public static class ExecutorFactory
{
public static Func<Page, object, Task<IActionResult>> CreateExecutor(
public static Func<object, object[], Task<IActionResult>> CreateExecutor(
CompiledPageActionDescriptor actionDescriptor,
MethodInfo method)
MethodInfo method,
HandlerParameterDescriptor[] parameters)
{
if (actionDescriptor == null)
{
@ -25,48 +27,24 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
throw new ArgumentNullException(nameof(method));
}
var methodIsDeclaredOnPage = method.DeclaringType.GetTypeInfo().IsAssignableFrom(actionDescriptor.PageTypeInfo);
var handler = CreateHandlerMethod(method);
return async (page, model) =>
if (parameters == null)
{
var arguments = new object[handler.Parameters.Length];
for (var i = 0; i < handler.Parameters.Length; i++)
{
var parameter = handler.Parameters[i];
arguments[i] = await page.Binder.BindModelAsync(
page.PageContext,
parameter.Type,
parameter.DefaultValue,
parameter.Name);
}
throw new ArgumentNullException(nameof(parameters));
}
var receiver = methodIsDeclaredOnPage ? page : model;
var methodIsDeclaredOnPage = method.DeclaringType.GetTypeInfo().IsAssignableFrom(actionDescriptor.PageTypeInfo);
var handler = CreateHandlerMethod(method, parameters);
return async (receiver, arguments) =>
{
var result = await handler.Execute(receiver, arguments);
return result;
};
}
private static HandlerMethod CreateHandlerMethod(MethodInfo method)
private static HandlerMethod CreateHandlerMethod(MethodInfo method, HandlerParameterDescriptor[] parameters)
{
var methodParameters = method.GetParameters();
var parameters = new HandlerParameter[methodParameters.Length];
for (var i = 0; i < methodParameters.Length; i++)
{
var methodParameter = methodParameters[i];
object defaultValue = null;
if (methodParameter.HasDefaultValue)
{
defaultValue = methodParameter.DefaultValue;
}
else if (methodParameter.ParameterType.GetTypeInfo().IsValueType)
{
defaultValue = Activator.CreateInstance(methodParameter.ParameterType);
}
parameters[i] = new HandlerParameter(methodParameter.Name, methodParameter.ParameterType, defaultValue);
}
var returnType = method.ReturnType;
var returnTypeInfo = method.ReturnType.GetTypeInfo();
@ -96,25 +74,25 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
private abstract class HandlerMethod
{
protected static Expression[] Unpack(Expression arguments, HandlerParameter[] parameters)
protected static Expression[] Unpack(Expression arguments, HandlerParameterDescriptor[] parameters)
{
var unpackExpressions = new Expression[parameters.Length];
for (var i = 0; i < parameters.Length; i++)
{
unpackExpressions[i] = Expression.Convert(
Expression.ArrayIndex(arguments, Expression.Constant(i)),
parameters[i].Type);
parameters[i].ParameterType);
}
return unpackExpressions;
}
protected HandlerMethod(HandlerParameter[] parameters)
protected HandlerMethod(HandlerParameterDescriptor[] parameters)
{
Parameters = parameters;
}
public HandlerParameter[] Parameters { get; }
public HandlerParameterDescriptor[] Parameters { get; }
public abstract Task<IActionResult> Execute(object receiver, object[] arguments);
}
@ -123,7 +101,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
private readonly Func<object, object[], Task> _thunk;
public NonGenericTaskHandlerMethod(HandlerParameter[] parameters, MethodInfo method)
public NonGenericTaskHandlerMethod(HandlerParameterDescriptor[] parameters, MethodInfo method)
: base(parameters)
{
var receiver = Expression.Parameter(typeof(object), "receiver");
@ -153,7 +131,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
private readonly Func<object, object[], Task<object>> _thunk;
public GenericTaskHandlerMethod(HandlerParameter[] parameters, MethodInfo method)
public GenericTaskHandlerMethod(HandlerParameterDescriptor[] parameters, MethodInfo method)
: base(parameters)
{
var receiver = Expression.Parameter(typeof(object), "receiver");
@ -189,7 +167,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
private readonly Action<object, object[]> _thunk;
public VoidHandlerMethod(HandlerParameter[] parameters, MethodInfo method)
public VoidHandlerMethod(HandlerParameterDescriptor[] parameters, MethodInfo method)
: base(parameters)
{
var receiver = Expression.Parameter(typeof(object), "receiver");
@ -215,7 +193,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
private readonly Func<object, object[], IActionResult> _thunk;
public ActionResultHandlerMethod(HandlerParameter[] parameters, MethodInfo method)
public ActionResultHandlerMethod(HandlerParameterDescriptor[] parameters, MethodInfo method)
: base(parameters)
{
var receiver = Expression.Parameter(typeof(object), "receiver");
@ -237,21 +215,5 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
return Task.FromResult(_thunk(receiver, arguments));
}
}
private struct HandlerParameter
{
public HandlerParameter(string name, Type type, object defaultValue)
{
Name = name;
Type = type;
DefaultValue = defaultValue;
}
public string Name { get; }
public Type Type { get; }
public object DefaultValue { get; }
}
}
}
}

View File

@ -22,6 +22,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
{
private readonly IPageHandlerMethodSelector _selector;
private readonly PageContext _pageContext;
private readonly ParameterBinder _parameterBinder;
private Page _page;
private object _model;
@ -34,7 +35,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
PageContext pageContext,
IFilterMetadata[] filterMetadata,
IList<IValueProviderFactory> valueProviderFactories,
PageActionInvokerCacheEntry cacheEntry)
PageActionInvokerCacheEntry cacheEntry,
ParameterBinder parameterBinder)
: base(
diagnosticSource,
logger,
@ -45,6 +47,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
_selector = handlerMethodSelector;
_pageContext = pageContext;
CacheEntry = cacheEntry;
_parameterBinder = parameterBinder;
}
public PageActionInvokerCacheEntry CacheEntry { get; }
@ -374,8 +377,10 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var handler = _selector.Select(_pageContext);
if (handler != null)
{
var arguments = await GetArguments(handler);
var executor = handler.Executor;
result = await executor(_page, _model);
result = await executor(handler.OnPage ? _page : _model, arguments);
}
if (result == null)
@ -386,6 +391,27 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
await result.ExecuteResultAsync(_pageContext);
}
private async Task<object[]> GetArguments(HandlerMethodDescriptor handler)
{
var arguments = new object[handler.Parameters.Length];
var valueProvider = await CompositeValueProvider.CreateAsync(_pageContext, _pageContext.ValueProviderFactories);
for (var i = 0; i < handler.Parameters.Length; i++)
{
var parameter = handler.Parameters[i];
var result = await _parameterBinder.BindModelAsync(
_page.PageContext,
valueProvider,
parameter,
value: null);
arguments[i] = result.IsModelSet ? result.Model : parameter.DefaultValue;
}
return arguments;
}
private async Task InvokeNextExceptionFilterAsync()
{
try

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal

View File

@ -15,7 +15,6 @@ using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
@ -162,7 +161,8 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
pageContext,
filters,
new CopyOnWriteList<IValueProviderFactory>(_valueProviderFactories),
cacheEntry);
cacheEntry,
_parameterBinder);
}
private PageActionInvokerCacheEntry CreateCacheEntry(
@ -264,18 +264,59 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
var formAction = new StringSegment(method.Name, formActionStart, formActionLength);
var parameters = GetHandlerParameters(method);
var handlerMethodDescriptor = new HandlerMethodDescriptor
{
Method = method,
Executor = ExecutorFactory.CreateExecutor(actionDescriptor, method),
Executor = ExecutorFactory.CreateExecutor(actionDescriptor, method, parameters),
FormAction = formAction,
HttpMethod = httpMethod,
Parameters = parameters,
OnPage = actionDescriptor.PageTypeInfo == type,
};
actionDescriptor.HandlerMethods.Add(handlerMethodDescriptor);
}
}
private static HandlerParameterDescriptor[] GetHandlerParameters(MethodInfo methodInfo)
{
var methodParameters = methodInfo.GetParameters();
var parameters = new HandlerParameterDescriptor[methodParameters.Length];
for (var i = 0; i < methodParameters.Length; i++)
{
var parameter = methodParameters[i];
parameters[i] = new HandlerParameterDescriptor()
{
BindingInfo = BindingInfo.GetBindingInfo(parameter.GetCustomAttributes()),
DefaultValue = GetDefaultValue(parameter),
Name = parameter.Name,
Parameter = parameter,
ParameterType = parameter.ParameterType,
};
}
return parameters;
}
private static object GetDefaultValue(ParameterInfo methodParameter)
{
object defaultValue = null;
if (methodParameter.HasDefaultValue)
{
defaultValue = methodParameter.DefaultValue;
}
else if (methodParameter.ParameterType.GetTypeInfo().IsValueType)
{
defaultValue = Activator.CreateInstance(methodParameter.ParameterType);
}
return defaultValue;
}
private static bool IsValidHandler(MethodInfo methodInfo)
{
// The SpecialName bit is set to flag members that are treated in a special way by some compilers

View File

@ -27,7 +27,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// </summary>
public abstract class Page : RazorPageBase, IRazorPage
{
private PageArgumentBinder _binder;
private IObjectModelValidator _objectValidator;
private IModelMetadataProvider _metadataProvider;
private IModelBinderFactory _modelBinderFactory;
@ -62,32 +61,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
/// </summary>
public HttpResponse Response => HttpContext?.Response;
/// <summary>
/// Gets or sets the <see cref="PageArgumentBinder"/>.
/// </summary>
public PageArgumentBinder Binder
{
get
{
if (_binder == null)
{
_binder = PageContext.HttpContext.RequestServices.GetRequiredService<PageArgumentBinder>();
}
return _binder;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_binder = value;
}
}
/// <summary>
/// Gets the <see cref="AspNetCore.Routing.RouteData"/> for the executing action.
/// </summary>

View File

@ -16,7 +16,6 @@ using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Net.Http.Headers;
@ -25,38 +24,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
{
public abstract class PageModel
{
private PageArgumentBinder _binder;
private IObjectModelValidator _objectValidator;
private IModelMetadataProvider _metadataProvider;
private IModelBinderFactory _modelBinderFactory;
private IUrlHelper _urlHelper;
/// <summary>
/// Gets or sets the <see cref="PageArgumentBinder"/>.
/// </summary>
public PageArgumentBinder Binder
{
get
{
if (_binder == null)
{
_binder = HttpContext?.RequestServices?.GetRequiredService<PageArgumentBinder>();
}
return _binder;
}
set
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
_binder = value;
}
}
/// <summary>
/// Gets or sets the <see cref="IUrlHelper"/>.
/// </summary>

View File

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
@ -25,7 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPage).GetMethod(nameof(TestPage.ActionResultReturningHandler));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, new HandlerParameterDescriptor[0]);
// Assert
Assert.NotNull(executor);
@ -45,7 +46,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPage).GetMethod(nameof(TestPage.ConcreteActionResult));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, new HandlerParameterDescriptor[0]);
// Assert
Assert.NotNull(executor);
@ -63,13 +64,14 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
PageTypeInfo = typeof(TestPage).GetTypeInfo(),
};
var methodInfo = typeof(TestPage).GetMethod(nameof(TestPage.ActionResultReturnHandlerWithParameters));
var parameters = CreateParameters(methodInfo);
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, parameters);
// Assert
Assert.NotNull(executor);
var actionResultTask = executor(new TestPage(), null);
var actionResultTask = executor(new TestPage(), CreateArguments(methodInfo));
var actionResult = await actionResultTask;
var contentResult = Assert.IsType<ContentResult>(actionResult);
Assert.Equal("Hello 0", contentResult.Content);
@ -87,7 +89,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPage).GetMethod(nameof(TestPage.VoidReturningHandler));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, new HandlerParameterDescriptor[0]);
// Assert
Assert.NotNull(executor);
@ -109,7 +111,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPage).GetMethod(nameof(TestPage.VoidTaskReturningHandler));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, new HandlerParameterDescriptor[0]);
// Assert
Assert.NotNull(executor);
@ -130,7 +132,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPage).GetMethod(nameof(TestPage.GenericTaskHandler));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, CreateParameters(methodInfo));
// Assert
Assert.NotNull(executor);
@ -150,11 +152,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPage).GetMethod(nameof(TestPage.TaskReturningConcreteSubtype));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, CreateParameters(methodInfo));
// Assert
Assert.NotNull(executor);
var actionResultTask = executor(new TestPage(), null);
var actionResultTask = executor(new TestPage(), CreateArguments(methodInfo));
var actionResult = await actionResultTask;
var contentResult = Assert.IsType<ContentResult>(actionResult);
Assert.Equal("value", contentResult.Content);
@ -172,11 +174,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPageModel).GetMethod(nameof(TestPageModel.ActionResultReturningHandler));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, new HandlerParameterDescriptor[0]);
// Assert
Assert.NotNull(executor);
var actionResultTask = executor(new EmptyPage(), new TestPageModel());
var actionResultTask = executor(new TestPageModel(), null);
var actionResult = await actionResultTask;
Assert.IsType<EmptyResult>(actionResult);
}
@ -193,11 +195,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPageModel).GetMethod(nameof(TestPageModel.ConcreteActionResult));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, CreateParameters(methodInfo));
// Assert
Assert.NotNull(executor);
var actionResultTask = executor(new EmptyPage(), new TestPageModel());
var actionResultTask = executor(new TestPageModel(), null);
var actionResult = await actionResultTask;
Assert.IsType<ViewResult>(actionResult);
}
@ -214,11 +216,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPageModel).GetMethod(nameof(TestPageModel.ActionResultReturnHandlerWithParameters));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, CreateParameters(methodInfo));
// Assert
Assert.NotNull(executor);
var actionResultTask = executor(new EmptyPage(), new TestPageModel());
var actionResultTask = executor(new TestPageModel(), CreateArguments(methodInfo));
var actionResult = await actionResultTask;
var contentResult = Assert.IsType<ContentResult>(actionResult);
Assert.Equal("Hello 0", contentResult.Content);
@ -237,11 +239,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPageModel).GetMethod(nameof(TestPageModel.VoidReturningHandler));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, new HandlerParameterDescriptor[0]);
// Assert
Assert.NotNull(executor);
var actionResultTask = executor(new EmptyPage(), model);
var actionResultTask = executor(model, null);
var actionResult = await actionResultTask;
Assert.Null(actionResult);
Assert.True(model.SideEffects);
@ -260,11 +262,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPageModel).GetMethod(nameof(TestPageModel.VoidTaskReturningHandler));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, new HandlerParameterDescriptor[0]);
// Assert
Assert.NotNull(executor);
var actionResultTask = executor(new EmptyPage(), model);
var actionResultTask = executor(model, null);
var actionResult = await actionResultTask;
Assert.Null(actionResult);
Assert.True(model.SideEffects);
@ -282,11 +284,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPageModel).GetMethod(nameof(TestPageModel.GenericTaskHandler));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, CreateParameters(methodInfo));
// Assert
Assert.NotNull(executor);
var actionResultTask = executor(new EmptyPage(), new TestPageModel());
var actionResultTask = executor(new TestPageModel(), null);
var actionResult = await actionResultTask;
Assert.IsType<EmptyResult>(actionResult);
}
@ -303,11 +305,11 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPageModel).GetMethod(nameof(TestPageModel.TaskReturningConcreteSubtype));
// Act
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo);
var executor = ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, CreateParameters(methodInfo));
// Assert
Assert.NotNull(executor);
var actionResultTask = executor(new EmptyPage(), new TestPageModel());
var actionResultTask = executor(new TestPageModel(), CreateArguments(methodInfo));
var actionResult = await actionResultTask;
var contentResult = Assert.IsType<ContentResult>(actionResult);
Assert.Equal("value", contentResult.Content);
@ -328,15 +330,50 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
var methodInfo = typeof(TestPageModel).GetMethod(methodName);
// Act & Assert
var ex = Assert.Throws<InvalidOperationException>(() => ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo));
var ex = Assert.Throws<InvalidOperationException>(() =>
ExecutorFactory.CreateExecutor(actionDescriptor, methodInfo, new HandlerParameterDescriptor[0]));
Assert.Equal($"Unsupported handler method return type '{methodInfo.ReturnType}'.", ex.Message);
}
private static object[] CreateArguments(MethodInfo methodInfo)
{
var parameters = methodInfo.GetParameters();
return parameters.Select(s => GetDefaultValue(s)).ToArray();
}
private static object GetDefaultValue(ParameterInfo methodParameter)
{
object defaultValue = null;
if (methodParameter.HasDefaultValue)
{
defaultValue = methodParameter.DefaultValue;
}
else if (methodParameter.ParameterType.GetTypeInfo().IsValueType)
{
defaultValue = Activator.CreateInstance(methodParameter.ParameterType);
}
return defaultValue;
}
private static HandlerParameterDescriptor[] CreateParameters(MethodInfo methodInfo)
{
var parameters = methodInfo.GetParameters();
return parameters.Select(p => new HandlerParameterDescriptor()
{
BindingInfo = BindingInfo.GetBindingInfo(p.GetCustomAttributes()),
Name = p.Name,
Parameter = p,
ParameterType = p.ParameterType,
}).ToArray();
}
private class TestPage : Page
{
public TestPage()
{
Binder = new MockBinder();
}
public bool SideEffects { get; private set; }
@ -433,7 +470,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Test.Internal
{
public EmptyPage()
{
Binder = new MockBinder();
}
public override Task ExecuteAsync()

View File

@ -11,11 +11,11 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.Internal;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -608,7 +608,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
null,
null,
new FilterItem[0]);
var invoker = new PageActionInvoker(
selector,
diagnosticSource,
@ -616,10 +616,43 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Internal
pageContext,
filters,
valueProviderFactories.AsReadOnly(),
cacheEntry);
cacheEntry,
GetParameterBinder());
return invoker;
}
private static ParameterBinder GetParameterBinder(
IModelBinderFactory factory = null,
IObjectModelValidator validator = null)
{
if (validator == null)
{
validator = CreateMockValidator();
}
if (factory == null)
{
factory = TestModelBinderFactory.CreateDefault();
}
return new ParameterBinder(
TestModelMetadataProvider.CreateDefaultProvider(),
factory,
validator);
}
private static IObjectModelValidator CreateMockValidator()
{
var mockValidator = new Mock<IObjectModelValidator>(MockBehavior.Strict);
mockValidator
.Setup(o => o.Validate(
It.IsAny<ActionContext>(),
It.IsAny<ValidationStateDictionary>(),
It.IsAny<string>(),
It.IsAny<object>()));
return mockValidator.Object;
}
private class TestPageResultExecutor : PageResultExecutor
{
private readonly Func<PageContext, Task> _executeAction;