Remove Binder from Page and PageModel
This commit is contained in:
parent
f4d84f50cd
commit
5a184df808
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue