Make ValueProvider creation lazy
We want this change to avoid MVC eagerly reading the form. This is good for general perf and also for scenarios where you want read the body yourself (large file uploads). We DO have scenarios where you want to configure the value providers per-request or also to change the limits on the value providers (form) so it's worth keeping these around on the context.
This commit is contained in:
parent
e483478415
commit
4d63ffa879
|
|
@ -1064,7 +1064,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
[NonAction]
|
||||
public virtual Task<bool> TryUpdateModelAsync<TModel>(
|
||||
public virtual async Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix)
|
||||
where TModel : class
|
||||
|
|
@ -1079,7 +1079,8 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
throw new ArgumentNullException(nameof(prefix));
|
||||
}
|
||||
|
||||
return TryUpdateModelAsync(model, prefix, new CompositeValueProvider(ControllerContext.ValueProviders));
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(ControllerContext);
|
||||
return await TryUpdateModelAsync(model, prefix, valueProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -1136,7 +1137,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// which need to be included for the current model.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
[NonAction]
|
||||
public Task<bool> TryUpdateModelAsync<TModel>(
|
||||
public async Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix,
|
||||
params Expression<Func<TModel, object>>[] includeExpressions)
|
||||
|
|
@ -1152,13 +1153,14 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
throw new ArgumentNullException(nameof(includeExpressions));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(ControllerContext);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
ControllerContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
new CompositeValueProvider(ControllerContext.ValueProviders),
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
includeExpressions);
|
||||
}
|
||||
|
|
@ -1174,7 +1176,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// <param name="propertyFilter">A predicate which can be used to filter properties at runtime.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
[NonAction]
|
||||
public Task<bool> TryUpdateModelAsync<TModel>(
|
||||
public async Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix,
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
|
|
@ -1190,13 +1192,14 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(ControllerContext);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
ControllerContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
new CompositeValueProvider(ControllerContext.ValueProviders),
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
propertyFilter);
|
||||
}
|
||||
|
|
@ -1302,7 +1305,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
[NonAction]
|
||||
public virtual Task<bool> TryUpdateModelAsync(
|
||||
public virtual async Task<bool> TryUpdateModelAsync(
|
||||
object model,
|
||||
Type modelType,
|
||||
string prefix)
|
||||
|
|
@ -1317,14 +1320,15 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
throw new ArgumentNullException(nameof(modelType));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(ControllerContext);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
modelType,
|
||||
prefix,
|
||||
ControllerContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
new CompositeValueProvider(ControllerContext.ValueProviders),
|
||||
valueProvider,
|
||||
ObjectValidator);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </summary>
|
||||
public class ControllerContext : ActionContext
|
||||
{
|
||||
private IList<IValueProvider> _valueProviders;
|
||||
private IList<IValueProviderFactory> _valueProviderFactories;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="ControllerContext"/>.
|
||||
|
|
@ -52,18 +52,18 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of <see cref="IValueProvider"/> instances for the current request.
|
||||
/// Gets or sets the list of <see cref="IValueProviderFactory"/> instances for the current request.
|
||||
/// </summary>
|
||||
public virtual IList<IValueProvider> ValueProviders
|
||||
public virtual IList<IValueProviderFactory> ValueProviderFactories
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_valueProviders == null)
|
||||
if (_valueProviderFactories == null)
|
||||
{
|
||||
_valueProviders = new List<IValueProvider>();
|
||||
_valueProviderFactories = new List<IValueProviderFactory>();
|
||||
}
|
||||
|
||||
return _valueProviders;
|
||||
return _valueProviderFactories;
|
||||
}
|
||||
set
|
||||
{
|
||||
|
|
@ -72,7 +72,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
_valueProviders = value;
|
||||
_valueProviderFactories = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ using System.Threading.Tasks;
|
|||
using Microsoft.AspNetCore.Mvc.Controllers;
|
||||
using Microsoft.AspNetCore.Mvc.Core;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Internal;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
}
|
||||
else if (actionDescriptor.BoundProperties.Count == 0)
|
||||
{
|
||||
return PopulateArgumentsAsync(controllerContext, actionDescriptor.Parameters);
|
||||
return BindActionArgumentsCoreAsync(controllerContext, actionDescriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -81,19 +81,36 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<IDictionary<string, object>> BindActionArgumentsCoreAsync(
|
||||
ControllerContext controllerContext,
|
||||
ControllerActionDescriptor actionDescriptor)
|
||||
{
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(controllerContext);
|
||||
|
||||
var actionArguments = await PopulateArgumentsAsync(
|
||||
controllerContext,
|
||||
actionDescriptor.Parameters,
|
||||
valueProvider);
|
||||
return actionArguments;
|
||||
}
|
||||
|
||||
private async Task<IDictionary<string, object>> BindActionArgumentsAndPropertiesCoreAsync(
|
||||
ControllerContext controllerContext,
|
||||
object controller,
|
||||
ControllerActionDescriptor actionDescriptor)
|
||||
{
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(controllerContext);
|
||||
|
||||
var controllerProperties = await PopulateArgumentsAsync(
|
||||
controllerContext,
|
||||
actionDescriptor.BoundProperties);
|
||||
actionDescriptor.BoundProperties,
|
||||
valueProvider);
|
||||
ActivateProperties(actionDescriptor, controller, controllerProperties);
|
||||
|
||||
var actionArguments = await PopulateArgumentsAsync(
|
||||
controllerContext,
|
||||
actionDescriptor.Parameters);
|
||||
actionDescriptor.Parameters,
|
||||
valueProvider);
|
||||
return actionArguments;
|
||||
}
|
||||
|
||||
|
|
@ -111,10 +128,35 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
throw new ArgumentNullException(nameof(controllerContext));
|
||||
}
|
||||
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(controllerContext);
|
||||
|
||||
return await BindModelAsync(parameter, controllerContext, valueProvider);
|
||||
}
|
||||
|
||||
public async Task<ModelBindingResult?> BindModelAsync(
|
||||
ParameterDescriptor parameter,
|
||||
ControllerContext controllerContext,
|
||||
IValueProvider valueProvider)
|
||||
{
|
||||
if (parameter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(parameter));
|
||||
}
|
||||
|
||||
if (controllerContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(controllerContext));
|
||||
}
|
||||
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
var metadata = _modelMetadataProvider.GetMetadataForType(parameter.ParameterType);
|
||||
var modelBindingContext = DefaultModelBindingContext.CreateBindingContext(
|
||||
controllerContext,
|
||||
new CompositeValueProvider(controllerContext.ValueProviders),
|
||||
valueProvider,
|
||||
metadata,
|
||||
parameter.BindingInfo,
|
||||
parameter.Name);
|
||||
|
|
@ -241,7 +283,8 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
|
||||
private async Task<IDictionary<string, object>> PopulateArgumentsAsync(
|
||||
ControllerContext controllerContext,
|
||||
IList<ParameterDescriptor> parameters)
|
||||
IList<ParameterDescriptor> parameters,
|
||||
IValueProvider valueProvider)
|
||||
{
|
||||
var arguments = new Dictionary<string, object>(StringComparer.Ordinal);
|
||||
|
||||
|
|
@ -249,7 +292,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
for (var i = 0; i < parameters.Count; i++)
|
||||
{
|
||||
var parameter = parameters[i];
|
||||
var modelBindingResult = await BindModelAsync(parameter, controllerContext);
|
||||
var modelBindingResult = await BindModelAsync(parameter, controllerContext, valueProvider);
|
||||
if (modelBindingResult != null && modelBindingResult.Value.IsModelSet)
|
||||
{
|
||||
arguments[parameter.Name] = modelBindingResult.Value.Model;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
public abstract class FilterActionInvoker : IActionInvoker
|
||||
{
|
||||
private readonly ControllerActionInvokerCache _controllerActionInvokerCache;
|
||||
private readonly IReadOnlyList<IValueProviderFactory> _valueProviderFactories;
|
||||
|
||||
private readonly DiagnosticSource _diagnosticSource;
|
||||
private readonly int _maxModelValidationErrors;
|
||||
|
||||
|
|
@ -71,13 +71,17 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
throw new ArgumentNullException(nameof(diagnosticSource));
|
||||
}
|
||||
|
||||
Context = new ControllerContext(actionContext);
|
||||
|
||||
_controllerActionInvokerCache = controllerActionInvokerCache;
|
||||
_valueProviderFactories = valueProviderFactories;
|
||||
Logger = logger;
|
||||
_diagnosticSource = diagnosticSource;
|
||||
_maxModelValidationErrors = maxModelValidationErrors;
|
||||
|
||||
Context = new ControllerContext(actionContext);
|
||||
Context.ModelState.MaxAllowedErrors = _maxModelValidationErrors;
|
||||
|
||||
// PERF: These are rarely going to be changed, so let's go copy-on-write.
|
||||
Context.ValueProviderFactories = new CopyOnWriteList<IValueProviderFactory>(valueProviderFactories);
|
||||
}
|
||||
|
||||
protected ControllerContext Context { get; }
|
||||
|
|
@ -110,8 +114,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
_controllerActionMethodExecutor = controllerActionInvokerState.ActionMethodExecutor;
|
||||
_cursor = new FilterCursor(_filters);
|
||||
|
||||
Context.ModelState.MaxAllowedErrors = _maxModelValidationErrors;
|
||||
|
||||
await InvokeAllAuthorizationFiltersAsync();
|
||||
|
||||
// If Authorization Filters return a result, it's a short circuit because
|
||||
|
|
@ -301,18 +303,6 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
}
|
||||
else
|
||||
{
|
||||
// We've reached the end of resource filters, so move to setting up state to invoke model
|
||||
// binding.
|
||||
var valueProviders = new List<IValueProvider>();
|
||||
var factoryContext = new ValueProviderFactoryContext(Context);
|
||||
|
||||
for (var i = 0; i < _valueProviderFactories.Count; i++)
|
||||
{
|
||||
var factory = _valueProviderFactories[i];
|
||||
await factory.CreateValueProviderAsync(factoryContext);
|
||||
}
|
||||
Context.ValueProviders = factoryContext.ValueProviders;
|
||||
|
||||
// >> ExceptionFilters >> Model Binding >> ActionFilters >> Action
|
||||
await InvokeAllExceptionFiltersAsync();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||
{
|
||||
|
|
@ -34,6 +35,33 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously creates a <see cref="CompositeValueProvider"/> using the provided
|
||||
/// <paramref name="controllerContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="controllerContext">The <see cref="ControllerContext"/> associated with the current request.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="Task{TResult}"/> which, when completed, asynchronously returns a
|
||||
/// <see cref="CompositeValueProvider"/>.
|
||||
/// </returns>
|
||||
public static async Task<CompositeValueProvider> CreateAsync(ControllerContext controllerContext)
|
||||
{
|
||||
if (controllerContext == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(controllerContext));
|
||||
}
|
||||
|
||||
var factories = controllerContext.ValueProviderFactories;
|
||||
var valueProviderFactoryContext = new ValueProviderFactoryContext(controllerContext);
|
||||
for (var i = 0; i < factories.Count; i++)
|
||||
{
|
||||
var factory = factories[i];
|
||||
await factory.CreateValueProviderAsync(valueProviderFactoryContext);
|
||||
}
|
||||
|
||||
return new CompositeValueProvider(valueProviderFactoryContext.ValueProviders);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual bool ContainsPrefix(string prefix)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an aggregate of <see cref="IValueProviderFactory"/>.
|
||||
/// </summary>
|
||||
public interface ICompositeValueProviderFactory : IValueProviderFactory
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -1488,10 +1488,11 @@ namespace Microsoft.AspNetCore.Mvc.Core.Test
|
|||
stringLocalizerFactory: null),
|
||||
};
|
||||
|
||||
valueProvider = valueProvider ?? new SimpleValueProvider();
|
||||
var controllerContext = new ControllerContext()
|
||||
{
|
||||
HttpContext = httpContext,
|
||||
ValueProviders = new[] { valueProvider, },
|
||||
ValueProviderFactories = new[] { new SimpleValueProviderFactory(valueProvider), },
|
||||
};
|
||||
|
||||
var binderFactory = new Mock<IModelBinderFactory>();
|
||||
|
|
|
|||
|
|
@ -537,7 +537,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
});
|
||||
|
||||
var factory = GetModelBinderFactory(binder);
|
||||
controllerContext.ValueProviders.Add(new SimpleValueProvider());
|
||||
controllerContext.ValueProviderFactories.Add(new SimpleValueProviderFactory());
|
||||
|
||||
var argumentBinder = GetArgumentBinder(factory);
|
||||
var controller = new TestController();
|
||||
|
|
@ -563,7 +563,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
|||
RouteData = new RouteData(),
|
||||
};
|
||||
|
||||
context.ValueProviders.Add(new SimpleValueProvider());
|
||||
context.ValueProviderFactories.Add(new SimpleValueProviderFactory());
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
{
|
||||
var httpContext = GetHttpContext(updateRequest, updateOptions);
|
||||
var services = httpContext.RequestServices;
|
||||
var options = services.GetRequiredService<IOptions<MvcOptions>>();
|
||||
|
||||
var context = new ModelBindingTestContext()
|
||||
{
|
||||
|
|
@ -33,17 +34,9 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
HttpContext = httpContext,
|
||||
MetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
RouteData = new RouteData(),
|
||||
ValueProviderFactories = new List<IValueProviderFactory>(options.Value.ValueProviderFactories),
|
||||
};
|
||||
|
||||
var options = services.GetRequiredService<IOptions<MvcOptions>>();
|
||||
var valueProviderFactoryContext = new ValueProviderFactoryContext(context);
|
||||
foreach (var factory in options.Value.ValueProviderFactories)
|
||||
{
|
||||
factory.CreateValueProviderAsync(valueProviderFactoryContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
context.ValueProviders = valueProviderFactoryContext.ValueProviders;
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
|
|
@ -129,19 +122,5 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
|
||||
return serviceCollection.BuildServiceProvider();
|
||||
}
|
||||
|
||||
private static ControllerContext GetControllerContext(MvcOptions options, ActionContext context)
|
||||
{
|
||||
var valueProviderFactoryContext = new ValueProviderFactoryContext(context);
|
||||
foreach (var factory in options.ValueProviderFactories)
|
||||
{
|
||||
factory.CreateValueProviderAsync(valueProviderFactoryContext).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
return new ControllerContext(context)
|
||||
{
|
||||
ValueProviders = valueProviderFactoryContext.ValueProviders
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var oldModel = model;
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Address();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -134,7 +134,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
};
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -184,7 +184,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var oldModel = model;
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -225,7 +225,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Person2();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -265,7 +265,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var collection = model.Address;
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -327,7 +327,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
};
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -367,7 +367,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Person6();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -406,7 +406,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Person4();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -453,7 +453,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var collection = model.Address;
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -495,7 +495,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Person5();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, string.Empty, testContext);
|
||||
var result = await TryUpdateModelAsync(model, string.Empty, testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -530,7 +530,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var oldModel = model;
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -565,7 +565,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Address();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -616,7 +616,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
};
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -666,7 +666,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var oldModel = model;
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -702,7 +702,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Person2();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -742,7 +742,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var collection = model.Address;
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -794,7 +794,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
};
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -829,7 +829,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Person6();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -863,7 +863,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Person4();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -910,7 +910,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var collection = model.Address;
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -947,7 +947,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
var model = new Person5();
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, "prefix", testContext);
|
||||
var result = await TryUpdateModelAsync(model, "prefix", testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -979,7 +979,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
};
|
||||
|
||||
// Act
|
||||
var result = await TryUpdateModel(model, prefix: "files", testContext: testContext);
|
||||
var result = await TryUpdateModelAsync(model, prefix: "files", testContext: testContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
|
@ -1085,19 +1085,20 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
}
|
||||
}
|
||||
|
||||
private Task<bool> TryUpdateModel(
|
||||
private async Task<bool> TryUpdateModelAsync(
|
||||
object model,
|
||||
string prefix,
|
||||
ModelBindingTestContext testContext)
|
||||
{
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(testContext);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
model.GetType(),
|
||||
prefix,
|
||||
testContext,
|
||||
testContext.MetadataProvider,
|
||||
TestModelBinderFactory.CreateDefault(),
|
||||
new CompositeValueProvider(testContext.ValueProviders),
|
||||
valueProvider,
|
||||
ModelBindingTestHelper.GetObjectValidator(testContext.MetadataProvider));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.Internal;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||
{
|
||||
public class SimpleValueProviderFactory : IValueProviderFactory
|
||||
{
|
||||
private readonly IValueProvider _valueProvider;
|
||||
|
||||
public SimpleValueProviderFactory()
|
||||
{
|
||||
_valueProvider = new SimpleValueProvider();
|
||||
}
|
||||
|
||||
public SimpleValueProviderFactory(IValueProvider valueProvider)
|
||||
{
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
_valueProvider = valueProvider;
|
||||
}
|
||||
|
||||
public Task CreateValueProviderAsync(ValueProviderFactoryContext context)
|
||||
{
|
||||
context.ValueProviders.Add(_valueProvider);
|
||||
return TaskCache.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -287,10 +287,11 @@ namespace Microsoft.AspNetCore.Mvc.Test
|
|||
stringLocalizerFactory: null),
|
||||
};
|
||||
|
||||
valueProvider = valueProvider ?? new SimpleValueProvider();
|
||||
var controllerContext = new ControllerContext()
|
||||
{
|
||||
HttpContext = httpContext,
|
||||
ValueProviders = new[] { valueProvider, },
|
||||
ValueProviderFactories = new[] { new SimpleValueProviderFactory(valueProvider), },
|
||||
};
|
||||
|
||||
var controller = new TestableController()
|
||||
|
|
|
|||
Loading…
Reference in New Issue