Parity between Controller and Page/PageModel
This commit is contained in:
parent
3e8cd1e7c9
commit
c9bfd2296d
|
|
@ -52,7 +52,26 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
var factories = controllerContext.ValueProviderFactories;
|
||||
var valueProviderFactoryContext = new ValueProviderFactoryContext(controllerContext);
|
||||
|
||||
return await CreateAsync(controllerContext, factories);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously creates a <see cref="CompositeValueProvider"/> using the provided
|
||||
/// <paramref name="actionContext"/>.
|
||||
/// </summary>
|
||||
/// <param name="actionContext">The <see cref="ActionContext"/> associated with the current request.</param>
|
||||
/// <param name="factories">The <see cref="IValueProviderFactory"/> to be applied to the context.</param>
|
||||
/// <returns>
|
||||
/// A <see cref="Task{TResult}"/> which, when completed, asynchronously returns a
|
||||
/// <see cref="CompositeValueProvider"/>.
|
||||
/// </returns>
|
||||
public static async Task<CompositeValueProvider> CreateAsync(
|
||||
ActionContext actionContext,
|
||||
IList<IValueProviderFactory> factories)
|
||||
{
|
||||
var valueProviderFactoryContext = new ValueProviderFactoryContext(actionContext);
|
||||
|
||||
for (var i = 0; i < factories.Count; i++)
|
||||
{
|
||||
var factory = factories[i];
|
||||
|
|
|
|||
|
|
@ -4,14 +4,19 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq.Expressions;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.Rendering;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
|
|
@ -23,6 +28,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
public abstract class Page : RazorPageBase, IRazorPage
|
||||
{
|
||||
private PageArgumentBinder _binder;
|
||||
private IObjectModelValidator _objectValidator;
|
||||
private IModelMetadataProvider _metadataProvider;
|
||||
private IModelBinderFactory _modelBinderFactory;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="RazorPages.PageContext"/>.
|
||||
|
|
@ -80,11 +88,61 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="AspNetCore.Routing.RouteData"/> for the executing action.
|
||||
/// </summary>
|
||||
public RouteData RouteData
|
||||
{
|
||||
get
|
||||
{
|
||||
return PageContext.RouteData;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ModelStateDictionary"/>.
|
||||
/// </summary>
|
||||
public ModelStateDictionary ModelState => PageContext?.ModelState;
|
||||
|
||||
private IObjectModelValidator ObjectValidator
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_objectValidator == null)
|
||||
{
|
||||
_objectValidator = HttpContext?.RequestServices?.GetRequiredService<IObjectModelValidator>();
|
||||
}
|
||||
|
||||
return _objectValidator;
|
||||
}
|
||||
}
|
||||
|
||||
private IModelMetadataProvider MetadataProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_metadataProvider == null)
|
||||
{
|
||||
_metadataProvider = HttpContext?.RequestServices?.GetRequiredService<IModelMetadataProvider>();
|
||||
}
|
||||
|
||||
return _metadataProvider;
|
||||
}
|
||||
}
|
||||
|
||||
private IModelBinderFactory ModelBinderFactory
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_modelBinderFactory == null)
|
||||
{
|
||||
_modelBinderFactory = HttpContext?.RequestServices?.GetRequiredService<IModelBinderFactory>();
|
||||
}
|
||||
|
||||
return _modelBinderFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void EnsureRenderedBodyOrSections()
|
||||
{
|
||||
|
|
@ -1130,5 +1188,384 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
return new PageViewResult(this);
|
||||
}
|
||||
#endregion Factory methods
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="Page"/>'s current
|
||||
/// <see cref="IValueProvider"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
public virtual Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
return TryUpdateModelAsync(model, prefix: string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="Page"/>'s current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>.
|
||||
/// </param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
public virtual async Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (prefix == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(prefix));
|
||||
}
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(PageContext, PageContext.ValueProviderFactories);
|
||||
return await TryUpdateModelAsync(model, prefix, valueProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
public virtual Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix,
|
||||
IValueProvider valueProvider)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (prefix == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(prefix));
|
||||
}
|
||||
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="Page"/>'s current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
|
||||
/// 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>
|
||||
public async Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix,
|
||||
params Expression<Func<TModel, object>>[] includeExpressions)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (includeExpressions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(includeExpressions));
|
||||
}
|
||||
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(PageContext, PageContext.ValueProviderFactories);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
includeExpressions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="Page"/>'s current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>.
|
||||
/// </param>
|
||||
/// <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>
|
||||
public async Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix,
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(PageContext, PageContext.ValueProviderFactories);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
|
||||
/// 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>
|
||||
public Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix,
|
||||
IValueProvider valueProvider,
|
||||
params Expression<Func<TModel, object>>[] includeExpressions)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
if (includeExpressions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(includeExpressions));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
includeExpressions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <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>
|
||||
public Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string prefix,
|
||||
IValueProvider valueProvider,
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
prefix,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="Page"/>'s current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="modelType">The type of model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the current <see cref="IValueProvider"/>.
|
||||
/// </param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
public virtual async Task<bool> TryUpdateModelAsync(
|
||||
object model,
|
||||
Type modelType,
|
||||
string prefix)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (modelType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelType));
|
||||
}
|
||||
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(PageContext, PageContext.ValueProviderFactories);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
modelType,
|
||||
prefix,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="prefix"/>.
|
||||
/// </summary>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="modelType">The type of model instance to update.</param>
|
||||
/// <param name="prefix">The prefix to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <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>
|
||||
public Task<bool> TryUpdateModelAsync(
|
||||
object model,
|
||||
Type modelType,
|
||||
string prefix,
|
||||
IValueProvider valueProvider,
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (modelType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelType));
|
||||
}
|
||||
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
modelType,
|
||||
prefix,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the specified <paramref name="model"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="model">The model to validate.</param>
|
||||
/// <returns><c>true</c> if the <see cref="ModelState"/> is valid; <c>false</c> otherwise.</returns>
|
||||
public virtual bool TryValidateModel(
|
||||
object model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
return TryValidateModel(model, prefix: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the specified <paramref name="model"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="model">The model to validate.</param>
|
||||
/// <param name="prefix">The key to use when looking up information in <see cref="ModelState"/>.
|
||||
/// </param>
|
||||
/// <returns><c>true</c> if the <see cref="ModelState"/> is valid;<c>false</c> otherwise.</returns>
|
||||
public virtual bool TryValidateModel(
|
||||
object model,
|
||||
string prefix)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
ObjectValidator.Validate(
|
||||
PageContext,
|
||||
validationState: null,
|
||||
prefix: prefix ?? string.Empty,
|
||||
model: model);
|
||||
return ModelState.IsValid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,21 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq.Expressions;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Internal;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
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;
|
||||
|
||||
|
|
@ -21,6 +26,9 @@ 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>
|
||||
|
|
@ -106,68 +114,405 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// </summary>
|
||||
public HttpResponse Response => HttpContext?.Response;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="AspNetCore.Routing.RouteData"/> for the executing action.
|
||||
/// </summary>
|
||||
public RouteData RouteData => PageContext.RouteData;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ModelStateDictionary"/>.
|
||||
/// </summary>
|
||||
public ModelStateDictionary ModelState => PageContext.ModelState;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ClaimsPrincipal"/> for user associated with the executing action.
|
||||
/// </summary>
|
||||
public ClaimsPrincipal User => HttpContext?.User;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ITempDataDictionary"/> from the <see cref="PageContext"/>.
|
||||
/// </summary>
|
||||
/// <remarks>Returns null if <see cref="PageContext"/> is null.</remarks>
|
||||
public ITempDataDictionary TempData => PageContext?.TempData;
|
||||
|
||||
private IObjectModelValidator ObjectValidator
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_objectValidator == null)
|
||||
{
|
||||
_objectValidator = HttpContext?.RequestServices?.GetRequiredService<IObjectModelValidator>();
|
||||
}
|
||||
|
||||
return _objectValidator;
|
||||
}
|
||||
}
|
||||
|
||||
private IModelMetadataProvider MetadataProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_metadataProvider == null)
|
||||
{
|
||||
_metadataProvider = HttpContext?.RequestServices?.GetRequiredService<IModelMetadataProvider>();
|
||||
}
|
||||
|
||||
return _metadataProvider;
|
||||
}
|
||||
}
|
||||
|
||||
private IModelBinderFactory ModelBinderFactory
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_modelBinderFactory == null)
|
||||
{
|
||||
_modelBinderFactory = HttpContext?.RequestServices?.GetRequiredService<IModelBinderFactory>();
|
||||
}
|
||||
|
||||
return _modelBinderFactory;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ViewDataDictionary"/>.
|
||||
/// </summary>
|
||||
public ViewDataDictionary ViewData => PageContext?.ViewData;
|
||||
|
||||
/// <summary>
|
||||
/// Binds the model with the specified <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The model type.</typeparam>
|
||||
/// <param name="name">The model name.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns the bound model.</returns>
|
||||
protected internal Task<TModel> BindAsync<TModel>(string name)
|
||||
{
|
||||
return Binder.BindModelAsync<TModel>(PageContext, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Binds the model with the specified <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The model type.</typeparam>
|
||||
/// <param name="name">The model name.</param>
|
||||
/// <param name="default">The default model value.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns the bound model.</returns>
|
||||
protected internal Task<TModel> BindAsync<TModel>(TModel @default, string name)
|
||||
{
|
||||
return Binder.BindModelAsync(PageContext, @default, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the pageModel's current
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="PageModel"/>'s current
|
||||
/// <see cref="IValueProvider"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
protected internal Task<bool> TryUpdateModelAsync<TModel>(TModel model)
|
||||
where TModel : class
|
||||
{
|
||||
return Binder.TryUpdateModelAsync(PageContext, model);
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
return TryUpdateModelAsync(model, name: string.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the pageModel's current
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="PageModel"/>'s current
|
||||
/// <see cref="IValueProvider"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="name">The model name.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
protected internal Task<bool> TryUpdateModelAsync<TModel>(TModel model, string name)
|
||||
protected internal async Task<bool> TryUpdateModelAsync<TModel>(TModel model, string name)
|
||||
where TModel : class
|
||||
{
|
||||
return Binder.TryUpdateModelAsync(PageContext, model, name);
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(PageContext, PageContext.ValueProviderFactories);
|
||||
return await TryUpdateModelAsync(model, name, valueProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="name">The name to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
protected internal Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string name,
|
||||
IValueProvider valueProvider)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(name));
|
||||
}
|
||||
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
name,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="PageModel"/>'s current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="name">The name to use when looking up values in the current <see cref="IValueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
|
||||
/// 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>
|
||||
protected internal async Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string name,
|
||||
params Expression<Func<TModel, object>>[] includeExpressions)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (includeExpressions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(includeExpressions));
|
||||
}
|
||||
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(PageContext, PageContext.ValueProviderFactories);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
name,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
includeExpressions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="PageModel"/>'s current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="name">The name to use when looking up values in the current <see cref="IValueProvider"/>.
|
||||
/// </param>
|
||||
/// <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>
|
||||
protected internal async Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string name,
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(PageContext, PageContext.ValueProviderFactories);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
name,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="name">The name to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <param name="includeExpressions"> <see cref="Expression"/>(s) which represent top-level properties
|
||||
/// 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>
|
||||
protected internal Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string name,
|
||||
IValueProvider valueProvider,
|
||||
params Expression<Func<TModel, object>>[] includeExpressions)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
if (includeExpressions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(includeExpressions));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
name,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
includeExpressions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="TModel">The type of the model object.</typeparam>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="name">The name to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <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>
|
||||
protected internal Task<bool> TryUpdateModelAsync<TModel>(
|
||||
TModel model,
|
||||
string name,
|
||||
IValueProvider valueProvider,
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
where TModel : class
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
name,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
propertyFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using values from the <see cref="PageModel"/>'s current
|
||||
/// <see cref="IValueProvider"/> and a <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="modelType">The type of model instance to update.</param>
|
||||
/// <param name="name">The name to use when looking up values in the current <see cref="IValueProvider"/>.
|
||||
/// </param>
|
||||
/// <returns>A <see cref="Task"/> that on completion returns <c>true</c> if the update is successful.</returns>
|
||||
protected internal async Task<bool> TryUpdateModelAsync(
|
||||
object model,
|
||||
Type modelType,
|
||||
string name)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (modelType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelType));
|
||||
}
|
||||
|
||||
var valueProvider = await CompositeValueProvider.CreateAsync(PageContext, PageContext.ValueProviderFactories);
|
||||
return await ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
modelType,
|
||||
name,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the specified <paramref name="model"/> instance using the <paramref name="valueProvider"/> and a
|
||||
/// <paramref name="name"/>.
|
||||
/// </summary>
|
||||
/// <param name="model">The model instance to update.</param>
|
||||
/// <param name="modelType">The type of model instance to update.</param>
|
||||
/// <param name="name">The name to use when looking up values in the <paramref name="valueProvider"/>.
|
||||
/// </param>
|
||||
/// <param name="valueProvider">The <see cref="IValueProvider"/> used for looking up values.</param>
|
||||
/// <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>
|
||||
protected internal Task<bool> TryUpdateModelAsync(
|
||||
object model,
|
||||
Type modelType,
|
||||
string name,
|
||||
IValueProvider valueProvider,
|
||||
Func<ModelMetadata, bool> propertyFilter)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
if (modelType == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(modelType));
|
||||
}
|
||||
|
||||
if (valueProvider == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(valueProvider));
|
||||
}
|
||||
|
||||
if (propertyFilter == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(propertyFilter));
|
||||
}
|
||||
|
||||
return ModelBindingHelper.TryUpdateModelAsync(
|
||||
model,
|
||||
modelType,
|
||||
name,
|
||||
PageContext,
|
||||
MetadataProvider,
|
||||
ModelBinderFactory,
|
||||
valueProvider,
|
||||
ObjectValidator,
|
||||
propertyFilter);
|
||||
}
|
||||
|
||||
#region Factory methods
|
||||
|
|
@ -1176,5 +1521,45 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
return new PageViewResult(Page);
|
||||
}
|
||||
#endregion Factory methods
|
||||
|
||||
/// <summary>
|
||||
/// Validates the specified <paramref name="model"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="model">The model to validate.</param>
|
||||
/// <returns><c>true</c> if the <see cref="ModelState"/> is valid; <c>false</c> otherwise.</returns>
|
||||
public virtual bool TryValidateModel(
|
||||
object model)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
return TryValidateModel(model, name: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the specified <paramref name="model"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="model">The model to validate.</param>
|
||||
/// <param name="name">The key to use when looking up information in <see cref="ModelState"/>.
|
||||
/// </param>
|
||||
/// <returns><c>true</c> if the <see cref="ModelState"/> is valid;<c>false</c> otherwise.</returns>
|
||||
public virtual bool TryValidateModel(
|
||||
object model,
|
||||
string name)
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(model));
|
||||
}
|
||||
|
||||
ObjectValidator.Validate(
|
||||
PageContext,
|
||||
validationState: null,
|
||||
prefix: name ?? string.Empty,
|
||||
model: model);
|
||||
return ModelState.IsValid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||
{
|
||||
public class RazorPageModelTest : IClassFixture<MvcTestFixture<RazorPagesWebSite.Startup>>
|
||||
{
|
||||
public RazorPageModelTest(MvcTestFixture<RazorPagesWebSite.Startup> fixture)
|
||||
{
|
||||
Client = fixture.Client;
|
||||
}
|
||||
|
||||
public HttpClient Client { get; }
|
||||
|
||||
[Fact]
|
||||
public async Task Page_TryUpdateModelAsync_Success()
|
||||
{
|
||||
// Arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "Pages/TryUpdateModel/10")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Name", "Overriden"),
|
||||
new KeyValuePair<string, string>("Age", "25"),
|
||||
})
|
||||
};
|
||||
|
||||
await AddAntiforgeryHeaders(request);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
Assert.Contains("Updated: True", content);
|
||||
Assert.Contains("Name = Overriden", content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Page_TryValidateModel_Success()
|
||||
{
|
||||
// Arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "Pages/TryValidateModel/10")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Name", "Foo"),
|
||||
new KeyValuePair<string, string>("Age", "25"),
|
||||
})
|
||||
};
|
||||
|
||||
await AddAntiforgeryHeaders(request);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
Assert.Contains("Validation: success", content.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Page_TryValidateModel_TooLong()
|
||||
{
|
||||
// Arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "Pages/TryValidateModel/10")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Name", "Foo"),
|
||||
new KeyValuePair<string, string>("Age", "200"),
|
||||
})
|
||||
};
|
||||
|
||||
await AddAntiforgeryHeaders(request);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
Assert.Contains("Validation: fail", content);
|
||||
Assert.Contains("The field Age must be between 0 and 99.", content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PageModel_TryUpdateModelAsync_Success()
|
||||
{
|
||||
// Arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "Pages/TryUpdateModelPageModel/10")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Name", "Overriden"),
|
||||
new KeyValuePair<string, string>("Age", "25"),
|
||||
})
|
||||
};
|
||||
|
||||
await AddAntiforgeryHeaders(request);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
Assert.Contains("Updated: True", content);
|
||||
Assert.Contains("Name = Overriden", content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PageModel_TryValidateModel_Success()
|
||||
{
|
||||
// Arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "Pages/TryValidateModelPageModel/10")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Name", "Foo"),
|
||||
new KeyValuePair<string, string>("Age", "25"),
|
||||
})
|
||||
};
|
||||
|
||||
await AddAntiforgeryHeaders(request);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
Assert.Contains("Validation: success", content.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PageModel_TryValidateModel_TooLong()
|
||||
{
|
||||
// Arrange
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, "Pages/TryValidateModelPageModel/10")
|
||||
{
|
||||
Content = new FormUrlEncodedContent(new KeyValuePair<string, string>[]
|
||||
{
|
||||
new KeyValuePair<string, string>("Name", "Foo"),
|
||||
new KeyValuePair<string, string>("Age", "200"),
|
||||
})
|
||||
};
|
||||
|
||||
await AddAntiforgeryHeaders(request);
|
||||
|
||||
// Act
|
||||
var response = await Client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
var content = await response.Content.ReadAsStringAsync();
|
||||
|
||||
Assert.Contains("Validation: fail", content);
|
||||
Assert.Contains("The field Age must be between 0 and 99.", content);
|
||||
}
|
||||
|
||||
private async Task AddAntiforgeryHeaders(HttpRequestMessage request)
|
||||
{
|
||||
var getResponse = await Client.GetAsync(request.RequestUri);
|
||||
Assert.Equal(HttpStatusCode.OK, getResponse.StatusCode);
|
||||
var getResponseBody = await getResponse.Content.ReadAsStringAsync();
|
||||
var formToken = AntiforgeryTestHelper.RetrieveAntiforgeryToken(getResponseBody, "");
|
||||
var cookie = AntiforgeryTestHelper.RetrieveAntiforgeryCookie(getResponse);
|
||||
|
||||
request.Headers.Add("Cookie", cookie.Key + "=" + cookie.Value);
|
||||
request.Headers.Add("RequestVerificationToken", formToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1463,31 +1463,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
Assert.Same(urlHelper, pageModel.Url);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModel_InvokesBindOnPageArgumentBinder()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
var binder = new TestPageArgumentBinder();
|
||||
httpContext.RequestServices = new ServiceCollection()
|
||||
.AddSingleton<PageArgumentBinder>(binder)
|
||||
.BuildServiceProvider();
|
||||
var pageContext = new PageContext
|
||||
{
|
||||
HttpContext = httpContext,
|
||||
};
|
||||
var pageModel = new TestPageModel
|
||||
{
|
||||
PageContext = pageContext,
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = await pageModel.BindAsync<Guid>("test-name");
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Redirect_ReturnsARedirectResult()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
@page "{id:int}"
|
||||
@using RazorPagesWebSite
|
||||
|
||||
@functions
|
||||
{
|
||||
public UserModel UserModel { get; set; }
|
||||
|
||||
[FromRoute]
|
||||
public int Id { get; set; }
|
||||
|
||||
public async Task OnPost()
|
||||
{
|
||||
var user = new UserModel();
|
||||
|
||||
Updated = await TryUpdateModelAsync(user);
|
||||
UserModel = user;
|
||||
}
|
||||
|
||||
public bool Updated { get; set; }
|
||||
}
|
||||
|
||||
@Html.ValidationSummary()
|
||||
<form action="">
|
||||
@Html.AntiForgeryToken()
|
||||
</form>
|
||||
Updated: @Updated
|
||||
Name = @UserModel?.Name
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace RazorPagesWebSite.Pages
|
||||
{
|
||||
public class TryUpdateModelPageModel : PageModel
|
||||
{
|
||||
public UserModel UserModel { get; set; }
|
||||
|
||||
public bool Updated { get; set; }
|
||||
|
||||
public async Task OnPost()
|
||||
{
|
||||
var user = new UserModel();
|
||||
Updated = await TryUpdateModelAsync(user);
|
||||
UserModel = user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
@page "{id:int}"
|
||||
@using RazorPagesWebSite.Pages
|
||||
@model TryUpdateModelPageModel
|
||||
|
||||
@Html.ValidationSummary()
|
||||
<form action="">
|
||||
@Html.AntiForgeryToken()
|
||||
</form>
|
||||
Updated: @Model.Updated
|
||||
Name = @Model.UserModel?.Name
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
@page "{id:int}"
|
||||
@using RazorPagesWebSite
|
||||
|
||||
@functions
|
||||
{
|
||||
[ModelBinder]
|
||||
public UserModel UserModel { get; set; }
|
||||
|
||||
[FromRoute]
|
||||
public int Id { get; set; }
|
||||
|
||||
public void OnPost(UserModel user)
|
||||
{
|
||||
Valid = TryValidateModel(user);
|
||||
|
||||
UserModel = user;
|
||||
}
|
||||
|
||||
public bool Valid { get; set; }
|
||||
}
|
||||
|
||||
@Html.ValidationSummary()
|
||||
<form action="">
|
||||
@Html.AntiForgeryToken()
|
||||
</form>
|
||||
Validation: @(Valid ? "success" : "fail!" )
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
|
||||
namespace RazorPagesWebSite.Pages
|
||||
{
|
||||
public class TryValidateModelPageModel : PageModel
|
||||
{
|
||||
[ModelBinder]
|
||||
public UserModel UserModel { get; set; }
|
||||
|
||||
public bool Validate { get; set; }
|
||||
|
||||
public void OnPost(UserModel user)
|
||||
{
|
||||
Validate = TryValidateModel(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
@page "{id:int}"
|
||||
@using RazorPagesWebSite.Pages
|
||||
@model TryValidateModelPageModel
|
||||
|
||||
@Html.ValidationSummary()
|
||||
<form action="">
|
||||
@Html.AntiForgeryToken()
|
||||
</form>
|
||||
Validation: @(Model.Validate ? "success" : "fail!" )
|
||||
Loading…
Reference in New Issue