Remove remaining `CompatibilitySwitch<T>` properties
- #4866 3 of 3 - other than ignored parameters and properties, no vestige remains of alternate behaviours - also remove `AllowAreas` use outside src/Mvc - left the `IEnumerable<ICompatibilitySwitch>` implementations to avoid `breakingchanges.netcore.json` churn - made the implementations more consistent - left one `ConfigureCompatibilityOptions<MvcOptions>` subclass: `MvcOptionsConfigureCompatibilityOptions` - note `AllowShortCircuitingValidationWhenNoValidatorsArePresent` default now applies to `TryValidateModel(...)` etc. nits: - updated `CompatibilityVersion` doc comments - "currently unused" -> "currently ignored" in doc comments from part 2 - took a few VS suggestions - VS seems to have cleaned up some trailing whitespace in files I had opened but didn't manually change
This commit is contained in:
parent
db0c347c23
commit
f113a20dfd
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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 Microsoft.AspNetCore.Authorization;
|
||||
|
||||
using System;
|
||||
|
|
@ -192,7 +192,6 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
var additionalParts = GetAdditionalParts();
|
||||
var mvcBuilder = services
|
||||
.AddMvc()
|
||||
.AddRazorPagesOptions(o => o.AllowAreas = true)
|
||||
.ConfigureApplicationPartManager(apm =>
|
||||
{
|
||||
foreach (var part in additionalParts)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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 Microsoft.AspNetCore.Authorization;
|
||||
|
||||
using System;
|
||||
|
|
@ -193,7 +193,6 @@ namespace Microsoft.AspNetCore.Authentication
|
|||
var additionalParts = GetAdditionalParts();
|
||||
var mvcBuilder = services
|
||||
.AddMvc()
|
||||
.AddRazorPagesOptions(o => o.AllowAreas = true)
|
||||
.ConfigureApplicationPartManager(apm =>
|
||||
{
|
||||
foreach (var part in additionalParts)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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;
|
||||
|
|
@ -37,7 +37,6 @@ namespace Microsoft.AspNetCore.Identity.UI
|
|||
name = name ?? throw new ArgumentNullException(nameof(name));
|
||||
options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
|
||||
options.AllowAreas = true;
|
||||
options.Conventions.AuthorizeAreaFolder(IdentityUIDefaultAreaName, "/Account/Manage");
|
||||
options.Conventions.AuthorizeAreaPage(IdentityUIDefaultAreaName, "/Account/Logout");
|
||||
var convention = new IdentityPageModelConvention<TUser>();
|
||||
|
|
|
|||
|
|
@ -7,8 +7,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
{
|
||||
/// <summary>
|
||||
/// Defines the set of policies that determine how the model binding system interprets exceptions
|
||||
/// thrown by an <see cref="IInputFormatter"/>. Applications should set
|
||||
/// <c>MvcOptions.InputFormatterExceptionPolicy</c> to configure this setting.
|
||||
/// thrown by an <see cref="IInputFormatter"/>. <seealso cref="IInputFormatterExceptionPolicy"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
|
|
@ -25,12 +24,12 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
/// The policy associated with <see cref="InputFormatterExceptionPolicy.AllExceptions"/> treats
|
||||
/// all such categories of problems as model state errors, and usually will be reported to the client as
|
||||
/// an HTTP 400. This was the only policy supported by model binding in ASP.NET Core MVC 1.0, 1.1, and 2.0
|
||||
/// and is still the default for historical reasons.
|
||||
/// and is still the default for historical reasons.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The policy associated with <see cref="InputFormatterExceptionPolicy.MalformedInputExceptions"/>
|
||||
/// treats only <see cref="InputFormatterException"/> and its subclasses as model state errors. This means that
|
||||
/// exceptions that are not related to the content of the HTTP request (such as a disconnect) will be rethrown,
|
||||
/// exceptions that are not related to the content of the HTTP request (such as a disconnect) will be re-thrown,
|
||||
/// which by default would cause an HTTP 500 response, unless there is exception-handling middleware enabled.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
|
|
@ -44,7 +43,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
|
||||
/// <summary>
|
||||
/// This value indicates that only <see cref="InputFormatterException"/> and subclasses will be treated
|
||||
/// as model state errors. All other exceptions types will be rethrown and can be handled by a higher
|
||||
/// as model state errors. All other exceptions types will be re-thrown and can be handled by a higher
|
||||
/// level exception handler, such as exception-handling middleware.
|
||||
/// </summary>
|
||||
MalformedInputExceptions = 1,
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
/// constraints.</param>
|
||||
/// <param name="modelMetadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
|
||||
/// <param name="mapper">The <see cref="IActionResultTypeMapper"/>.</param>
|
||||
/// <remarks>The <paramref name="mapper"/> parameter is currently unused.</remarks>
|
||||
/// <remarks>The <paramref name="mapper"/> parameter is currently ignored.</remarks>
|
||||
[Obsolete("This constructor is obsolete and will be removed in a future release.")]
|
||||
public DefaultApiDescriptionProvider(
|
||||
IOptions<MvcOptions> optionsAccessor,
|
||||
|
|
@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.Mvc.ApiExplorer
|
|||
/// <param name="modelMetadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
|
||||
/// <param name="mapper">The <see cref="IActionResultTypeMapper"/>.</param>
|
||||
/// <param name="routeOptions">The accessor for <see cref="RouteOptions"/>.</param>
|
||||
/// <remarks>The <paramref name="mapper"/> parameter is currently unused.</remarks>
|
||||
/// <remarks>The <paramref name="mapper"/> parameter is currently ignored.</remarks>
|
||||
public DefaultApiDescriptionProvider(
|
||||
IOptions<MvcOptions> optionsAccessor,
|
||||
IInlineConstraintResolver constraintResolver,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </summary>
|
||||
public class ApiBehaviorOptions : IEnumerable<ICompatibilitySwitch>
|
||||
{
|
||||
private readonly ICompatibilitySwitch[] _switches = Array.Empty<ICompatibilitySwitch>();
|
||||
private readonly IReadOnlyList<ICompatibilitySwitch> _switches = Array.Empty<ICompatibilitySwitch>();
|
||||
private Func<ActionContext, IActionResult> _invalidModelStateResponseFactory;
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -84,10 +84,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </summary>
|
||||
public IDictionary<int, ClientErrorData> ClientErrorMapping { get; } = new Dictionary<int, ClientErrorData>();
|
||||
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<ICompatibilitySwitch>)_switches).GetEnumerator();
|
||||
}
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator() => _switches.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,14 +52,8 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// ASP.NET Core MVC 2.1.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ASP.NET Core MVC 2.1 introduced compatibility switches for the following:
|
||||
/// <list type="bullet">
|
||||
/// <item><description><see cref="MvcOptions.InputFormatterExceptionPolicy"/></description></item>
|
||||
/// <item><description><see cref="MvcOptions.SuppressBindingUndefinedValueToEnumType"/></description></item>
|
||||
/// <item><description><c>MvcJsonOptions.AllowInputFormatterExceptionMessages</c></description></item>
|
||||
/// <item><description><c>RazorPagesOptions.AllowAreas</c></description></item>
|
||||
/// <item><description><c>RazorPagesOptions.AllowMappingHeadRequestsToGetHandler</c></description></item>
|
||||
/// </list>
|
||||
/// ASP.NET Core MVC 2.1 introduced a compatibility switch for
|
||||
/// <c>MvcJsonOptions.AllowInputFormatterExceptionMessages</c>. This is now a regular property.
|
||||
/// </remarks>
|
||||
[Obsolete("This " + nameof(CompatibilityVersion) + " value is obsolete. The recommended alternatives are " +
|
||||
nameof(Version_3_0) + " or later.")]
|
||||
|
|
@ -73,15 +67,10 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// ASP.NET Core MVC 2.2 introduced compatibility switches for the following:
|
||||
/// <list type="bullet">
|
||||
/// <item><description><c>ApiBehaviorOptions.SuppressMapClientErrors</c></description></item>
|
||||
/// <item><description><c>MvcDataAnnotationsLocalizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes</c></description></item>
|
||||
/// <item><description><see cref="MvcOptions.EnableEndpointRouting" /></description></item>
|
||||
/// <item><description><see cref="MvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent"/></description></item>
|
||||
/// <item><description><see cref="MvcOptions.MaxValidationDepth" /></description></item>
|
||||
/// <item><description><c>RazorPagesOptions.AllowDefaultHandlingForOptionsRequests</c></description></item>
|
||||
/// <item><description><c>RazorViewEngineOptions.AllowRecompilingViewsOnFileChange</c></description></item>
|
||||
/// <item><description><c>MvcViewOptions.AllowRenderingMaxLengthAttribute</c></description></item>
|
||||
/// <item><description><c>MvcXmlOptions.AllowRfc7807CompliantProblemDetailsFormat</c></description></item>
|
||||
/// </list>
|
||||
/// All of the above are now regular properties.
|
||||
/// </remarks>
|
||||
[Obsolete("This " + nameof(CompatibilityVersion) + " value is obsolete. The recommended alternatives are " +
|
||||
nameof(Version_3_0) + " or later.")]
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
|
@ -21,12 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
|
|||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
[nameof(MvcOptions.InputFormatterExceptionPolicy)] = InputFormatterExceptionPolicy.MalformedInputExceptions,
|
||||
[nameof(MvcOptions.SuppressBindingUndefinedValueToEnumType)] = true,
|
||||
[nameof(MvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent)] = true,
|
||||
};
|
||||
return new Dictionary<string, object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,13 +192,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
|
||||
private bool ShouldHandleException(IInputFormatter formatter)
|
||||
{
|
||||
var policy = _options.InputFormatterExceptionPolicy;
|
||||
|
||||
// Any explicit policy on the formatters takes precedence over the global policy on MvcOptions
|
||||
if (formatter is IInputFormatterExceptionPolicy exceptionPolicy)
|
||||
{
|
||||
policy = exceptionPolicy.ExceptionPolicy;
|
||||
}
|
||||
// Any explicit policy on the formatters overrides the default.
|
||||
var policy = (formatter as IInputFormatterExceptionPolicy)?.ExceptionPolicy ??
|
||||
InputFormatterExceptionPolicy.MalformedInputExceptions;
|
||||
|
||||
return policy == InputFormatterExceptionPolicy.AllExceptions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
/// </summary>
|
||||
public class EnumTypeModelBinder : SimpleTypeModelBinder
|
||||
{
|
||||
private readonly bool _suppressBindingUndefinedValueToEnumType;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="EnumTypeModelBinder"/>.
|
||||
/// </summary>
|
||||
|
|
@ -22,6 +20,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
/// </param>
|
||||
/// <param name="modelType">The model type.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>,</param>
|
||||
/// <remarks>
|
||||
/// The <paramref name="suppressBindingUndefinedValueToEnumType"/> parameter is currently ignored.
|
||||
/// </remarks>
|
||||
public EnumTypeModelBinder(
|
||||
bool suppressBindingUndefinedValueToEnumType,
|
||||
Type modelType,
|
||||
|
|
@ -37,8 +38,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
{
|
||||
throw new ArgumentNullException(nameof(loggerFactory));
|
||||
}
|
||||
|
||||
_suppressBindingUndefinedValueToEnumType = suppressBindingUndefinedValueToEnumType;
|
||||
}
|
||||
|
||||
protected override void CheckModel(
|
||||
|
|
@ -46,23 +45,20 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
ValueProviderResult valueProviderResult,
|
||||
object model)
|
||||
{
|
||||
if (model == null || !_suppressBindingUndefinedValueToEnumType)
|
||||
if (model == null)
|
||||
{
|
||||
base.CheckModel(bindingContext, valueProviderResult, model);
|
||||
}
|
||||
else if (IsDefinedInEnum(model, bindingContext))
|
||||
{
|
||||
bindingContext.Result = ModelBindingResult.Success(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsDefinedInEnum(model, bindingContext))
|
||||
{
|
||||
bindingContext.Result = ModelBindingResult.Success(model);
|
||||
}
|
||||
else
|
||||
{
|
||||
bindingContext.ModelState.TryAddModelError(
|
||||
bindingContext.ModelName,
|
||||
bindingContext.ModelMetadata.ModelBindingMessageProvider.ValueIsInvalidAccessor(
|
||||
valueProviderResult.ToString()));
|
||||
}
|
||||
bindingContext.ModelState.TryAddModelError(
|
||||
bindingContext.ModelName,
|
||||
bindingContext.ModelMetadata.ModelBindingMessageProvider.ValueIsInvalidAccessor(
|
||||
valueProviderResult.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -70,14 +66,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
{
|
||||
var modelType = bindingContext.ModelMetadata.UnderlyingOrModelType;
|
||||
|
||||
// Check if the converted value is indeed defined on the enum as EnumTypeConverter
|
||||
// Check if the converted value is indeed defined on the enum as EnumTypeConverter
|
||||
// converts value to the backing type (ex: integer) and does not check if the value is defined on the enum.
|
||||
if (bindingContext.ModelMetadata.IsFlagsEnum)
|
||||
{
|
||||
// Enum.IsDefined does not work with combined flag enum values.
|
||||
// From EnumDataTypeAttribute.cs in CoreFX.
|
||||
// Examples:
|
||||
//
|
||||
//
|
||||
// [Flags]
|
||||
// enum FlagsEnum { Value1 = 1, Value2 = 2, Value4 = 4 }
|
||||
//
|
||||
|
|
@ -87,7 +83,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
//
|
||||
// Invalid Scenarios:
|
||||
// 1. valueProviderResult="2,10", model=12, underlying=12, converted=12
|
||||
//
|
||||
//
|
||||
var underlying = Convert.ChangeType(
|
||||
model,
|
||||
Enum.GetUnderlyingType(modelType),
|
||||
|
|
|
|||
|
|
@ -12,15 +12,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
/// </summary>
|
||||
public class EnumTypeModelBinderProvider : IModelBinderProvider
|
||||
{
|
||||
private readonly MvcOptions _options;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="EnumTypeModelBinderProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="options">The <see cref="MvcOptions"/>.</param>
|
||||
/// <remarks>The <paramref name="options"/> parameter is currently ignored.</remarks>
|
||||
public EnumTypeModelBinderProvider(MvcOptions options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
|
@ -35,7 +33,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
{
|
||||
var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>();
|
||||
return new EnumTypeModelBinder(
|
||||
_options.SuppressBindingUndefinedValueToEnumType,
|
||||
suppressBindingUndefinedValueToEnumType: true,
|
||||
context.Metadata.UnderlyingOrModelType,
|
||||
loggerFactory);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
/// <param name="validator">The <see cref="IObjectModelValidator"/>.</param>
|
||||
/// <param name="mvcOptions">The <see cref="MvcOptions"/> accessor.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
/// <remarks>The <paramref name="mvcOptions"/> parameter is currently unused.</remarks>
|
||||
/// <remarks>The <paramref name="mvcOptions"/> parameter is currently ignored.</remarks>
|
||||
public ParameterBinder(
|
||||
IModelMetadataProvider modelMetadataProvider,
|
||||
IModelBinderFactory modelBinderFactory,
|
||||
|
|
|
|||
|
|
@ -42,8 +42,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation
|
|||
validationState)
|
||||
{
|
||||
MaxValidationDepth = _mvcOptions.MaxValidationDepth,
|
||||
AllowShortCircuitingValidationWhenNoValidatorsArePresent =
|
||||
_mvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent,
|
||||
};
|
||||
|
||||
return visitor;
|
||||
|
|
|
|||
|
|
@ -107,7 +107,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation
|
|||
/// Gets or sets a value that determines if <see cref="ValidationVisitor"/> can short circuit validation when a model
|
||||
/// does not have any associated validators.
|
||||
/// </summary>
|
||||
public bool AllowShortCircuitingValidationWhenNoValidatorsArePresent { get; set; }
|
||||
/// <value>The default value is <see langword="true"/>.</value>
|
||||
/// <remarks>This property is currently ignored.</remarks>
|
||||
public bool AllowShortCircuitingValidationWhenNoValidatorsArePresent { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Validates a object.
|
||||
|
|
@ -266,9 +268,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation
|
|||
}
|
||||
// If the metadata indicates that no validators exist AND the aggregate state for the key says that the model graph
|
||||
// is not invalid (i.e. is one of Unvalidated, Valid, or Skipped) we can safely mark the graph as valid.
|
||||
else if (
|
||||
AllowShortCircuitingValidationWhenNoValidatorsArePresent &&
|
||||
metadata.HasValidators == false &&
|
||||
else if (metadata.HasValidators == false &&
|
||||
ModelState.GetFieldValidationState(key) != ModelValidationState.Invalid)
|
||||
{
|
||||
// No validators will be created for this graph of objects. Mark it as valid if it wasn't previously validated.
|
||||
|
|
|
|||
|
|
@ -19,12 +19,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </summary>
|
||||
public class MvcOptions : IEnumerable<ICompatibilitySwitch>
|
||||
{
|
||||
// See CompatibilitySwitch.cs for guide on how to implement these.
|
||||
private readonly CompatibilitySwitch<InputFormatterExceptionPolicy> _inputFormatterExceptionPolicy;
|
||||
private readonly CompatibilitySwitch<bool> _suppressBindingUndefinedValueToEnumType;
|
||||
private readonly CompatibilitySwitch<bool> _allowShortCircuitingValidationWhenNoValidatorsArePresent;
|
||||
|
||||
private readonly ICompatibilitySwitch[] _switches;
|
||||
private readonly IReadOnlyList<ICompatibilitySwitch> _switches = Array.Empty<ICompatibilitySwitch>();
|
||||
private int _maxModelStateErrors = ModelStateDictionary.DefaultMaxAllowedErrors;
|
||||
private int? _maxValidationDepth = 32;
|
||||
|
||||
|
|
@ -44,17 +39,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
ModelMetadataDetailsProviders = new List<IMetadataDetailsProvider>();
|
||||
ModelValidatorProviders = new List<IModelValidatorProvider>();
|
||||
ValueProviderFactories = new List<IValueProviderFactory>();
|
||||
|
||||
_inputFormatterExceptionPolicy = new CompatibilitySwitch<InputFormatterExceptionPolicy>(nameof(InputFormatterExceptionPolicy), InputFormatterExceptionPolicy.AllExceptions);
|
||||
_suppressBindingUndefinedValueToEnumType = new CompatibilitySwitch<bool>(nameof(SuppressBindingUndefinedValueToEnumType));
|
||||
_allowShortCircuitingValidationWhenNoValidatorsArePresent = new CompatibilitySwitch<bool>(nameof(AllowShortCircuitingValidationWhenNoValidatorsArePresent));
|
||||
|
||||
_switches = new ICompatibilitySwitch[]
|
||||
{
|
||||
_inputFormatterExceptionPolicy,
|
||||
_suppressBindingUndefinedValueToEnumType,
|
||||
_allowShortCircuitingValidationWhenNoValidatorsArePresent,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -102,36 +86,11 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </summary>
|
||||
public FormatterMappings FormatterMappings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value which determines how the model binding system interprets exceptions thrown by an <see cref="IInputFormatter"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see cref="InputFormatterExceptionPolicy.MalformedInputExceptions"/>.
|
||||
/// </value>
|
||||
public InputFormatterExceptionPolicy InputFormatterExceptionPolicy
|
||||
{
|
||||
get => _inputFormatterExceptionPolicy.Value;
|
||||
set => _inputFormatterExceptionPolicy.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of <see cref="IInputFormatter"/>s that are used by this application.
|
||||
/// </summary>
|
||||
public FormatterCollection<IInputFormatter> InputFormatters { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the model binding system will bind undefined values to
|
||||
/// enum types.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see langword="true"/>.
|
||||
/// </value>
|
||||
public bool SuppressBindingUndefinedValueToEnumType
|
||||
{
|
||||
get => _suppressBindingUndefinedValueToEnumType.Value;
|
||||
set => _suppressBindingUndefinedValueToEnumType.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the flag to buffer the request body in input formatters. Default is <c>false</c>.
|
||||
/// </summary>
|
||||
|
|
@ -250,30 +209,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines if <see cref="ValidationVisitor"/>
|
||||
/// can short-circuit validation when a model does not have any associated validators.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see langword="true"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// When <see cref="ModelMetadata.HasValidators"/> is <see langword="true"/>, that is, it is determined
|
||||
/// that a model or any of it's properties or collection elements cannot have any validators,
|
||||
/// <see cref="ValidationVisitor"/> can short-circuit validation for the model and mark the object
|
||||
/// graph as valid. Setting this property to <see langword="true"/>, allows <see cref="ValidationVisitor"/> to
|
||||
/// perform this optimization.
|
||||
/// </remarks>
|
||||
public bool AllowShortCircuitingValidationWhenNoValidatorsArePresent
|
||||
{
|
||||
get => _allowShortCircuitingValidationWhenNoValidatorsArePresent.Value;
|
||||
set => _allowShortCircuitingValidationWhenNoValidatorsArePresent.Value = value;
|
||||
}
|
||||
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<ICompatibilitySwitch>)_switches).GetEnumerator();
|
||||
}
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator() => _switches.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,5 +102,25 @@
|
|||
"TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Void set_AllowValidatingTopLevelNodes(System.Boolean value)",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public Microsoft.AspNetCore.Mvc.Formatters.InputFormatterExceptionPolicy get_InputFormatterExceptionPolicy()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Boolean get_SuppressBindingUndefinedValueToEnumType()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Void set_InputFormatterExceptionPolicy(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterExceptionPolicy value)",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.MvcOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Void set_SuppressBindingUndefinedValueToEnumType(System.Boolean value)",
|
||||
"Kind": "Removal"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -27,9 +27,6 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
<IConfigureOptions<MvcDataAnnotationsLocalizationOptions>,
|
||||
MvcDataAnnotationsLocalizationOptionsSetup>());
|
||||
}
|
||||
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IPostConfigureOptions<MvcDataAnnotationsLocalizationOptions>, MvcDataAnnotationsLocalizationConfigureCompatibilityOptions>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -184,16 +184,9 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
var namesAndValues = new Dictionary<string, string>();
|
||||
|
||||
IStringLocalizer enumLocalizer = null;
|
||||
if (_localizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes)
|
||||
if (_stringLocalizerFactory != null && _localizationOptions.DataAnnotationLocalizerProvider != null)
|
||||
{
|
||||
if (_stringLocalizerFactory != null && _localizationOptions.DataAnnotationLocalizerProvider != null)
|
||||
{
|
||||
enumLocalizer = _localizationOptions.DataAnnotationLocalizerProvider(underlyingType, _stringLocalizerFactory);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
enumLocalizer = _stringLocalizerFactory?.Create(underlyingType);
|
||||
enumLocalizer = _localizationOptions.DataAnnotationLocalizerProvider(underlyingType, _stringLocalizerFactory);
|
||||
}
|
||||
|
||||
var enumFields = Enum.GetNames(underlyingType)
|
||||
|
|
|
|||
|
|
@ -1,32 +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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
internal class MvcDataAnnotationsLocalizationConfigureCompatibilityOptions : ConfigureCompatibilityOptions<MvcDataAnnotationsLocalizationOptions>
|
||||
{
|
||||
public MvcDataAnnotationsLocalizationConfigureCompatibilityOptions(
|
||||
ILoggerFactory loggerFactory,
|
||||
IOptions<MvcCompatibilityOptions> compatibilityOptions)
|
||||
: base(loggerFactory, compatibilityOptions)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IReadOnlyDictionary<string, object> DefaultValues
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
[nameof(MvcDataAnnotationsLocalizationOptions.AllowDataAnnotationsLocalizationForEnumDisplayAttributes)] = true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,42 +14,14 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
/// </summary>
|
||||
public class MvcDataAnnotationsLocalizationOptions : IEnumerable<ICompatibilitySwitch>
|
||||
{
|
||||
private readonly CompatibilitySwitch<bool> _allowDataAnnotationsLocalizationForEnumDisplayAttributes;
|
||||
private readonly ICompatibilitySwitch[] _switches;
|
||||
private readonly IReadOnlyList<ICompatibilitySwitch> _switches = Array.Empty<ICompatibilitySwitch>();
|
||||
|
||||
/// <summary>
|
||||
/// The delegate to invoke for creating <see cref="IStringLocalizer"/>.
|
||||
/// </summary>
|
||||
public Func<Type, IStringLocalizerFactory, IStringLocalizer> DataAnnotationLocalizerProvider;
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of the <see cref="MvcDataAnnotationsLocalizationOptions"/> class.
|
||||
/// </summary>
|
||||
public MvcDataAnnotationsLocalizationOptions()
|
||||
{
|
||||
_allowDataAnnotationsLocalizationForEnumDisplayAttributes = new CompatibilitySwitch<bool>(nameof(AllowDataAnnotationsLocalizationForEnumDisplayAttributes));
|
||||
|
||||
_switches = new ICompatibilitySwitch[]
|
||||
{
|
||||
_allowDataAnnotationsLocalizationForEnumDisplayAttributes
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines if <see cref="DataAnnotationLocalizerProvider"/> should be used while localizing <see cref="Enum"/> types.
|
||||
/// If set to <c>true</c> <see cref="DataAnnotationLocalizerProvider"/> will be used in localizing <see cref="Enum"/> types.
|
||||
/// If set to <c>false</c> the localization will search for values in resource files for the <see cref="Enum"/>.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see langword="true"/>.
|
||||
/// </value>
|
||||
public bool AllowDataAnnotationsLocalizationForEnumDisplayAttributes
|
||||
{
|
||||
get => _allowDataAnnotationsLocalizationForEnumDisplayAttributes.Value;
|
||||
set => _allowDataAnnotationsLocalizationForEnumDisplayAttributes.Value = value;
|
||||
}
|
||||
|
||||
public IEnumerator<ICompatibilitySwitch> GetEnumerator() => ((IEnumerable<ICompatibilitySwitch>)_switches).GetEnumerator();
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator() => _switches.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
|
||||
SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationJsonPatch);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override InputFormatterExceptionPolicy ExceptionPolicy
|
||||
{
|
||||
|
|
@ -180,4 +180,4 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
return base.CanRead(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </summary>
|
||||
public class MvcJsonOptions : IEnumerable<ICompatibilitySwitch>
|
||||
{
|
||||
private readonly ICompatibilitySwitch[] _switches = Array.Empty<ICompatibilitySwitch>();
|
||||
private readonly IReadOnlyList<ICompatibilitySwitch> _switches = Array.Empty<ICompatibilitySwitch>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a flag to determine whether error messages from JSON deserialization by the
|
||||
|
|
@ -38,10 +38,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </summary>
|
||||
public JsonSerializerSettings SerializerSettings { get; } = JsonSerializerSettingsProvider.CreateSerializerSettings();
|
||||
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<ICompatibilitySwitch>)_switches).GetEnumerator();
|
||||
}
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator() => _switches.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,9 +119,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
{
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, XmlDataContractSerializerMvcOptionsSetup>());
|
||||
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IPostConfigureOptions<MvcXmlOptions>, MvcXmlOptionsConfigureCompatibilityOptions>());
|
||||
}
|
||||
|
||||
// Internal for testing.
|
||||
|
|
@ -129,9 +126,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
{
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, XmlSerializerMvcOptionsSetup>());
|
||||
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IPostConfigureOptions<MvcXmlOptions>, MvcXmlOptionsConfigureCompatibilityOptions>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,9 +120,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
{
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, XmlDataContractSerializerMvcOptionsSetup>());
|
||||
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IPostConfigureOptions<MvcXmlOptions>, MvcXmlOptionsConfigureCompatibilityOptions>());
|
||||
}
|
||||
|
||||
// Internal for testing.
|
||||
|
|
@ -130,9 +127,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
{
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, XmlSerializerMvcOptionsSetup>());
|
||||
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IPostConfigureOptions<MvcXmlOptions>, MvcXmlOptionsConfigureCompatibilityOptions>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters.Xml;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
internal sealed class MvcXmlOptionsConfigureCompatibilityOptions : ConfigureCompatibilityOptions<MvcXmlOptions>
|
||||
{
|
||||
public MvcXmlOptionsConfigureCompatibilityOptions(
|
||||
ILoggerFactory loggerFactory,
|
||||
IOptions<MvcCompatibilityOptions> compatibilityOptions)
|
||||
: base(loggerFactory, compatibilityOptions)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IReadOnlyDictionary<string, object> DefaultValues
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
[nameof(MvcXmlOptions.AllowRfc7807CompliantProblemDetailsFormat)] = true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -18,19 +18,14 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
/// </summary>
|
||||
internal sealed class XmlDataContractSerializerMvcOptionsSetup : IConfigureOptions<MvcOptions>
|
||||
{
|
||||
private readonly MvcXmlOptions _xmlOptions;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="XmlDataContractSerializerMvcOptionsSetup"/>.
|
||||
/// </summary>
|
||||
/// <param name="xmlOptions"><see cref="MvcXmlOptions"/>.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
public XmlDataContractSerializerMvcOptionsSetup(
|
||||
IOptions<MvcXmlOptions> xmlOptions,
|
||||
ILoggerFactory loggerFactory)
|
||||
public XmlDataContractSerializerMvcOptionsSetup(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_xmlOptions = xmlOptions?.Value ?? throw new ArgumentNullException(nameof(xmlOptions));
|
||||
_loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
|
||||
}
|
||||
|
||||
|
|
@ -43,11 +38,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
options.ModelMetadataDetailsProviders.Add(new DataMemberRequiredBindingMetadataProvider());
|
||||
|
||||
var inputFormatter = new XmlDataContractSerializerInputFormatter(options);
|
||||
inputFormatter.WrapperProviderFactories.Add(new ProblemDetailsWrapperProviderFactory(_xmlOptions));
|
||||
inputFormatter.WrapperProviderFactories.Add(new ProblemDetailsWrapperProviderFactory());
|
||||
options.InputFormatters.Add(inputFormatter);
|
||||
|
||||
var outputFormatter = new XmlDataContractSerializerOutputFormatter(_loggerFactory);
|
||||
outputFormatter.WrapperProviderFactories.Add(new ProblemDetailsWrapperProviderFactory(_xmlOptions));
|
||||
outputFormatter.WrapperProviderFactories.Add(new ProblemDetailsWrapperProviderFactory());
|
||||
options.OutputFormatters.Add(outputFormatter);
|
||||
|
||||
// Do not override any user mapping
|
||||
|
|
|
|||
|
|
@ -16,19 +16,14 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
/// </summary>
|
||||
internal sealed class XmlSerializerMvcOptionsSetup : IConfigureOptions<MvcOptions>
|
||||
{
|
||||
private readonly MvcXmlOptions _xmlOptions;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="XmlSerializerMvcOptionsSetup"/>.
|
||||
/// </summary>
|
||||
/// <param name="xmlOptions"><see cref="MvcXmlOptions"/>.</param>
|
||||
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
|
||||
public XmlSerializerMvcOptionsSetup(
|
||||
IOptions<MvcXmlOptions> xmlOptions,
|
||||
ILoggerFactory loggerFactory)
|
||||
public XmlSerializerMvcOptionsSetup(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_xmlOptions = xmlOptions?.Value ?? throw new ArgumentNullException(nameof(xmlOptions));
|
||||
_loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
|
||||
}
|
||||
|
||||
|
|
@ -49,11 +44,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
}
|
||||
|
||||
var inputFormatter = new XmlSerializerInputFormatter(options);
|
||||
inputFormatter.WrapperProviderFactories.Add(new ProblemDetailsWrapperProviderFactory(_xmlOptions));
|
||||
inputFormatter.WrapperProviderFactories.Add(new ProblemDetailsWrapperProviderFactory());
|
||||
options.InputFormatters.Add(inputFormatter);
|
||||
|
||||
var outputFormatter = new XmlSerializerOutputFormatter(_loggerFactory);
|
||||
outputFormatter.WrapperProviderFactories.Add(new ProblemDetailsWrapperProviderFactory(_xmlOptions));
|
||||
outputFormatter.WrapperProviderFactories.Add(new ProblemDetailsWrapperProviderFactory());
|
||||
options.OutputFormatters.Add(outputFormatter);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// 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.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
|
|
@ -10,39 +11,13 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
|
|||
/// <summary>
|
||||
/// Provides configuration for XML formatters.
|
||||
/// </summary>
|
||||
/// <remarks>This class is currently empty.</remarks>
|
||||
public class MvcXmlOptions : IEnumerable<ICompatibilitySwitch>
|
||||
{
|
||||
private readonly CompatibilitySwitch<bool> _allowRfc7807CompliantProblemDetailsFormat;
|
||||
private readonly IReadOnlyList<ICompatibilitySwitch> _switches;
|
||||
private readonly IReadOnlyList<ICompatibilitySwitch> _switches = Array.Empty<ICompatibilitySwitch>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="MvcXmlOptions"/>.
|
||||
/// </summary>
|
||||
public MvcXmlOptions()
|
||||
{
|
||||
_allowRfc7807CompliantProblemDetailsFormat = new CompatibilitySwitch<bool>(nameof(AllowRfc7807CompliantProblemDetailsFormat));
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator() => _switches.GetEnumerator();
|
||||
|
||||
_switches = new ICompatibilitySwitch[]
|
||||
{
|
||||
_allowRfc7807CompliantProblemDetailsFormat,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value inidicating whether <see cref="ProblemDetails"/> and <see cref="ValidationProblemDetails"/>
|
||||
/// are serialized in a format compliant with the RFC 7807 specification (https://tools.ietf.org/html/rfc7807).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see langword="true"/>.
|
||||
/// </value>
|
||||
public bool AllowRfc7807CompliantProblemDetailsFormat
|
||||
{
|
||||
get => _allowRfc7807CompliantProblemDetailsFormat.Value;
|
||||
set => _allowRfc7807CompliantProblemDetailsFormat.Value = value;
|
||||
}
|
||||
|
||||
public IEnumerator<ICompatibilitySwitch> GetEnumerator() => _switches.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,41 +7,16 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
|
|||
{
|
||||
internal class ProblemDetailsWrapperProviderFactory : IWrapperProviderFactory
|
||||
{
|
||||
private readonly MvcXmlOptions _options;
|
||||
|
||||
public ProblemDetailsWrapperProviderFactory(MvcXmlOptions options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public IWrapperProvider GetProvider(WrapperProviderContext context)
|
||||
{
|
||||
if (context.DeclaredType == typeof(ProblemDetails))
|
||||
{
|
||||
if (_options.AllowRfc7807CompliantProblemDetailsFormat)
|
||||
{
|
||||
return new WrapperProvider(typeof(ProblemDetailsWrapper), p => new ProblemDetailsWrapper((ProblemDetails)p));
|
||||
}
|
||||
else
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
return new WrapperProvider(typeof(ProblemDetails21Wrapper), p => new ProblemDetails21Wrapper((ProblemDetails)p));
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
return new WrapperProvider(typeof(ProblemDetailsWrapper), p => new ProblemDetailsWrapper((ProblemDetails)p));
|
||||
}
|
||||
|
||||
if (context.DeclaredType == typeof(ValidationProblemDetails))
|
||||
{
|
||||
if (_options.AllowRfc7807CompliantProblemDetailsFormat)
|
||||
{
|
||||
return new WrapperProvider(typeof(ValidationProblemDetailsWrapper), p => new ValidationProblemDetailsWrapper((ValidationProblemDetails)p));
|
||||
}
|
||||
else
|
||||
{
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
return new WrapperProvider(typeof(ValidationProblemDetails21Wrapper), p => new ValidationProblemDetails21Wrapper((ValidationProblemDetails)p));
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
return new WrapperProvider(typeof(ValidationProblemDetailsWrapper), p => new ValidationProblemDetailsWrapper((ValidationProblemDetails)p));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
@ -62,4 +37,4 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
|
|||
public object Wrap(object original) => WrapDelegate(original);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
|
||||
// When RootDirectory and AreaRootDirectory overlap (e.g. RootDirectory = '/', AreaRootDirectory = '/Areas'), we
|
||||
// only want to allow a page to be associated with the area route.
|
||||
if (_pagesOptions.AllowAreas && relativePath.StartsWith(areaRootDirectory, StringComparison.OrdinalIgnoreCase))
|
||||
if (relativePath.StartsWith(areaRootDirectory, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
routeModel = _routeModelFactory.CreateAreaRouteModel(relativePath, routeTemplate);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,10 +179,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
pageModel.Filters.Add(_pageHandlerResultFilter);
|
||||
}
|
||||
|
||||
if (_razorPagesOptions.AllowDefaultHandlingForOptionsRequests)
|
||||
{
|
||||
pageModel.Filters.Add(_handleOptionsRequestsFilter);
|
||||
}
|
||||
pageModel.Filters.Add(_handleOptionsRequestsFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using Microsoft.AspNetCore.Mvc.Abstractions;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNetCore.Mvc.Filters;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
|
||||
|
|
@ -82,8 +81,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
// Options
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<RazorViewEngineOptions>, RazorPagesRazorViewEngineOptionsSetup>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IPostConfigureOptions<RazorPagesOptions>, RazorPagesOptionsConfigureCompatibilityOptions>());
|
||||
|
||||
// Action description and invocation
|
||||
services.TryAddEnumerable(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||
{
|
||||
|
|
@ -13,20 +12,6 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
{
|
||||
private const string Handler = "handler";
|
||||
|
||||
private readonly IOptions<RazorPagesOptions> _options;
|
||||
|
||||
public DefaultPageHandlerMethodSelector(IOptions<RazorPagesOptions> options)
|
||||
{
|
||||
if (options == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(options));
|
||||
}
|
||||
|
||||
_options = options;
|
||||
}
|
||||
|
||||
private bool AllowFuzzyHttpMethodMatching => _options?.Value.AllowMappingHeadRequestsToGetHandler ?? false;
|
||||
|
||||
public HandlerMethodDescriptor Select(PageContext context)
|
||||
{
|
||||
var handlers = SelectHandlers(context);
|
||||
|
|
@ -113,7 +98,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
}
|
||||
|
||||
// Step 1a: do fuzzy HTTP method matching if needed.
|
||||
if (candidates.Count == 0 && AllowFuzzyHttpMethodMatching)
|
||||
if (candidates.Count == 0)
|
||||
{
|
||||
var fuzzyHttpMethod = GetFuzzyMatchHttpMethod(context);
|
||||
if (fuzzyHttpMethod != null)
|
||||
|
|
|
|||
|
|
@ -14,27 +14,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
/// </summary>
|
||||
public class RazorPagesOptions : IEnumerable<ICompatibilitySwitch>
|
||||
{
|
||||
private readonly CompatibilitySwitch<bool> _allowAreas;
|
||||
private readonly CompatibilitySwitch<bool> _allowMappingHeadRequestsToGetHandler;
|
||||
private readonly CompatibilitySwitch<bool> _allowsDefaultHandlingForOptionsRequests;
|
||||
private readonly ICompatibilitySwitch[] _switches;
|
||||
|
||||
private readonly IReadOnlyList<ICompatibilitySwitch> _switches = Array.Empty<ICompatibilitySwitch>();
|
||||
private string _root = "/Pages";
|
||||
|
||||
public RazorPagesOptions()
|
||||
{
|
||||
_allowAreas = new CompatibilitySwitch<bool>(nameof(AllowAreas));
|
||||
_allowMappingHeadRequestsToGetHandler = new CompatibilitySwitch<bool>(nameof(AllowMappingHeadRequestsToGetHandler));
|
||||
_allowsDefaultHandlingForOptionsRequests = new CompatibilitySwitch<bool>(nameof(AllowDefaultHandlingForOptionsRequests));
|
||||
|
||||
_switches = new ICompatibilitySwitch[]
|
||||
{
|
||||
_allowAreas,
|
||||
_allowMappingHeadRequestsToGetHandler,
|
||||
_allowsDefaultHandlingForOptionsRequests,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a collection of <see cref="IPageConvention"/> instances that are applied during
|
||||
/// route and page model construction.
|
||||
|
|
@ -64,70 +46,7 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines if areas are enabled for Razor Pages.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see langword="true"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// When enabled, any Razor Page under the directory structure <c>/Area/AreaName/Pages/</c>
|
||||
/// will be associated with an area with the name <c>AreaName</c>.
|
||||
/// </remarks>
|
||||
public bool AllowAreas
|
||||
{
|
||||
get => _allowAreas.Value;
|
||||
set => _allowAreas.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines if HTTP method matching for Razor Pages handler methods will use
|
||||
/// fuzzy matching.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see langword="true"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// When enabled, Razor Pages handler methods will be more flexible in which HTTP methods will be accepted
|
||||
/// by GET and POST handler methods. This allows a GET handler methods to accept the HEAD HTTP methods in
|
||||
/// addition to GET. A more specific handler method can still be defined to accept HEAD, and the most
|
||||
/// specific handler will be invoked.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This setting reduces the number of handler methods that must be written to correctly respond to typical
|
||||
/// web traffic including requests from internet infrastructure such as web crawlers.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public bool AllowMappingHeadRequestsToGetHandler
|
||||
{
|
||||
get => _allowMappingHeadRequestsToGetHandler.Value;
|
||||
set => _allowMappingHeadRequestsToGetHandler.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that determines if HTTP requests with the OPTIONS method are handled by default, if
|
||||
/// no handler is available.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see langword="true"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// Razor Pages uses the current request's HTTP method to select a handler method. When no handler is available or selected,
|
||||
/// the page is immediately executed. This may cause runtime errors if the page relies on the handler method to execute
|
||||
/// and initialize some state. This setting attempts to avoid this class of error for HTTP <c>OPTIONS</c> requests by
|
||||
/// returning a <c>200 OK</c> response.
|
||||
/// </remarks>
|
||||
public bool AllowDefaultHandlingForOptionsRequests
|
||||
{
|
||||
get => _allowsDefaultHandlingForOptionsRequests.Value;
|
||||
set => _allowsDefaultHandlingForOptionsRequests.Value = value;
|
||||
}
|
||||
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<ICompatibilitySwitch>)_switches).GetEnumerator();
|
||||
}
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator() => _switches.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,33 +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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages
|
||||
{
|
||||
internal class RazorPagesOptionsConfigureCompatibilityOptions : ConfigureCompatibilityOptions<RazorPagesOptions>
|
||||
{
|
||||
public RazorPagesOptionsConfigureCompatibilityOptions(
|
||||
ILoggerFactory loggerFactory,
|
||||
IOptions<MvcCompatibilityOptions> compatibilityOptions)
|
||||
: base(loggerFactory, compatibilityOptions)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IReadOnlyDictionary<string, object> DefaultValues
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
[nameof(RazorPagesOptions.AllowAreas)] = true,
|
||||
[nameof(RazorPagesOptions.AllowMappingHeadRequestsToGetHandler)] = true,
|
||||
[nameof(RazorPagesOptions.AllowDefaultHandlingForOptionsRequests)] = true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,5 +27,25 @@
|
|||
{
|
||||
"TypeId": "public static class Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageDirectiveFeature",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Boolean get_AllowAreas()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Boolean get_AllowMappingHeadRequestsToGetHandler()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Void set_AllowAreas(System.Boolean value)",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Void set_AllowMappingHeadRequestsToGetHandler(System.Boolean value)",
|
||||
"Kind": "Removal"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
|||
|
|
@ -95,17 +95,24 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
|
||||
// Underscores are fine characters in id's.
|
||||
IdAttributeDotReplacement = optionsAccessor.Value.HtmlHelperOptions.IdAttributeDotReplacement;
|
||||
|
||||
AllowRenderingMaxLengthAttribute = optionsAccessor.Value.AllowRenderingMaxLengthAttribute;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether the maxlength attribute should be rendered for compatible HTML input elements,
|
||||
/// when they're bound to models marked with either
|
||||
/// <see cref="StringLengthAttribute"/> or <see cref="MaxLengthAttribute"/> attributes.
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether the <c>maxlength</c> attribute should be rendered for
|
||||
/// compatible HTML input elements, when they're bound to models marked with either
|
||||
/// <see cref="StringLengthAttribute"/> or <see cref="MaxLengthAttribute"/> attributes.
|
||||
/// </summary>
|
||||
/// <remarks>If both attributes are specified, the one with the smaller value will be used for the rendered `maxlength` attribute.</remarks>
|
||||
protected bool AllowRenderingMaxLengthAttribute { get; }
|
||||
/// <value>The default value is <see langword="true"/>.</value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// If both attributes are specified, the one with the smaller value will be used for the rendered
|
||||
/// <c>maxlength</c> attribute.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This property is currently ignored.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
protected bool AllowRenderingMaxLengthAttribute { get; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string IdAttributeDotReplacement { get; }
|
||||
|
|
@ -737,11 +744,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
}
|
||||
|
||||
AddPlaceholderAttribute(viewContext.ViewData, tagBuilder, modelExplorer, expression);
|
||||
if (AllowRenderingMaxLengthAttribute)
|
||||
{
|
||||
AddMaxLengthAttribute(viewContext.ViewData, tagBuilder, modelExplorer, expression);
|
||||
}
|
||||
|
||||
AddMaxLengthAttribute(viewContext.ViewData, tagBuilder, modelExplorer, expression);
|
||||
AddValidationAttributes(viewContext, tagBuilder, modelExplorer, expression);
|
||||
|
||||
// If there are any errors for a named field, we add this CSS attribute.
|
||||
|
|
@ -1257,7 +1260,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
AddPlaceholderAttribute(viewContext.ViewData, tagBuilder, modelExplorer, expression);
|
||||
}
|
||||
|
||||
if (AllowRenderingMaxLengthAttribute && _maxLengthInputTypes.Contains(suppliedTypeString))
|
||||
if (_maxLengthInputTypes.Contains(suppliedTypeString))
|
||||
{
|
||||
AddMaxLengthAttribute(viewContext.ViewData, tagBuilder, modelExplorer, expression);
|
||||
}
|
||||
|
|
@ -1397,7 +1400,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a maxlength attribute to the <paramref name="tagBuilder" />.
|
||||
/// Adds a <c>maxlength</c> attribute to the <paramref name="tagBuilder" />.
|
||||
/// </summary>
|
||||
/// <param name="viewData">A <see cref="ViewDataDictionary"/> instance for the current scope.</param>
|
||||
/// <param name="tagBuilder">A <see cref="TagBuilder"/> instance.</param>
|
||||
|
|
@ -1552,8 +1555,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
}
|
||||
|
||||
// Second check the Eval() call returned a collection of SelectListItems.
|
||||
var selectList = value as IEnumerable<SelectListItem>;
|
||||
if (selectList == null)
|
||||
if (!(value is IEnumerable<SelectListItem> selectList))
|
||||
{
|
||||
throw new InvalidOperationException(Resources.FormatHtmlHelper_WrongSelectDataType(
|
||||
expression,
|
||||
|
|
@ -1606,8 +1608,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
IEnumerable<SelectListItem> selectList,
|
||||
ICollection<string> currentValues)
|
||||
{
|
||||
var itemsList = selectList as IList<SelectListItem>;
|
||||
if (itemsList == null)
|
||||
if (!(selectList is IList<SelectListItem> itemsList))
|
||||
{
|
||||
itemsList = selectList.ToList();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,8 +143,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcViewOptions>, MvcViewOptionsSetup>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IPostConfigureOptions<MvcViewOptions>, MvcViewOptionsConfigureCompatibilityOptions>());
|
||||
services.TryAddEnumerable(
|
||||
ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, TempDataMvcOptionsSetup>());
|
||||
|
||||
|
|
|
|||
|
|
@ -85,10 +85,6 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
List<LifecycleProperty> results = null;
|
||||
|
||||
var propertyHelpers = PropertyHelper.GetVisibleProperties(type: type);
|
||||
var prefix = viewOptions.SuppressTempDataAttributePrefix ?
|
||||
string.Empty :
|
||||
"TempDataProperty-";
|
||||
|
||||
for (var i = 0; i < propertyHelpers.Length; i++)
|
||||
{
|
||||
var propertyHelper = propertyHelpers[i];
|
||||
|
|
@ -105,7 +101,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
var key = tempDataAttribute.Key;
|
||||
if (string.IsNullOrEmpty(key))
|
||||
{
|
||||
key = prefix + property.Name;
|
||||
key = property.Name;
|
||||
}
|
||||
|
||||
results.Add(new LifecycleProperty(property, key));
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||
|
|
@ -17,22 +16,9 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
/// </summary>
|
||||
public class MvcViewOptions : IEnumerable<ICompatibilitySwitch>
|
||||
{
|
||||
private readonly CompatibilitySwitch<bool> _suppressTempDataAttributePrefix;
|
||||
private readonly CompatibilitySwitch<bool> _allowRenderingMaxLengthAttribute;
|
||||
private readonly ICompatibilitySwitch[] _switches;
|
||||
private readonly IReadOnlyList<ICompatibilitySwitch> _switches = Array.Empty<ICompatibilitySwitch>();
|
||||
private HtmlHelperOptions _htmlHelperOptions = new HtmlHelperOptions();
|
||||
|
||||
public MvcViewOptions()
|
||||
{
|
||||
_suppressTempDataAttributePrefix = new CompatibilitySwitch<bool>(nameof(SuppressTempDataAttributePrefix));
|
||||
_allowRenderingMaxLengthAttribute = new CompatibilitySwitch<bool>(nameof(AllowRenderingMaxLengthAttribute));
|
||||
_switches = new[]
|
||||
{
|
||||
_suppressTempDataAttributePrefix,
|
||||
_allowRenderingMaxLengthAttribute
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets programmatic configuration for the HTML helpers and <see cref="Rendering.ViewContext"/>.
|
||||
/// </summary>
|
||||
|
|
@ -50,45 +36,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Gets or sets a value that determines if the <see cref="ITempDataDictionary"/> keys for
|
||||
/// properties annotated with <see cref="TempDataAttribute"/> include the prefix <c>TempDataProperty-</c>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// When <see cref="TempDataAttribute.Key"/> is not specified, the lookup key for properties annotated
|
||||
/// with <see cref="TempDataAttribute"/> is derived from the property name. In releases prior to ASP.NET Core 2.1,
|
||||
/// the calculated key was the property name prefixed by the value <c>TempDataProperty-</c>.
|
||||
/// e.g. <c>TempDataProperty-SuccessMessage</c>. When this option is <c>true</c>, the calculated key for the property is
|
||||
/// the property name e.g. <c>SuccessMessage</c>.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see langword="true"/>.
|
||||
/// </value>
|
||||
public bool SuppressTempDataAttributePrefix
|
||||
{
|
||||
get => _suppressTempDataAttributePrefix.Value;
|
||||
set => _suppressTempDataAttributePrefix.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value that indicates whether the maxlength attribute should be rendered for compatible HTML elements,
|
||||
/// when they're bound to models marked with either
|
||||
/// <see cref="StringLengthAttribute"/> or <see cref="MaxLengthAttribute"/> attributes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The default value is <see langword="true"/>.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// If both attributes are specified, the one with the smaller value will be used for the rendered `maxlength` attribute.
|
||||
/// </remarks>
|
||||
public bool AllowRenderingMaxLengthAttribute
|
||||
{
|
||||
get => _allowRenderingMaxLengthAttribute.Value;
|
||||
set => _allowRenderingMaxLengthAttribute.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list <see cref="IViewEngine"/>s used by this application.
|
||||
/// </summary>
|
||||
|
|
@ -100,10 +47,7 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
public IList<IClientModelValidatorProvider> ClientModelValidatorProviders { get; } =
|
||||
new List<IClientModelValidatorProvider>();
|
||||
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<ICompatibilitySwitch>)_switches).GetEnumerator();
|
||||
}
|
||||
IEnumerator<ICompatibilitySwitch> IEnumerable<ICompatibilitySwitch>.GetEnumerator() => _switches.GetEnumerator();
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => _switches.GetEnumerator();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +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.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
||||
{
|
||||
internal class MvcViewOptionsConfigureCompatibilityOptions : ConfigureCompatibilityOptions<MvcViewOptions>
|
||||
{
|
||||
public MvcViewOptionsConfigureCompatibilityOptions(
|
||||
ILoggerFactory loggerFactory,
|
||||
IOptions<MvcCompatibilityOptions> compatibilityOptions)
|
||||
: base(loggerFactory, compatibilityOptions)
|
||||
{
|
||||
}
|
||||
|
||||
protected override IReadOnlyDictionary<string, object> DefaultValues
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Dictionary<string, object>
|
||||
{
|
||||
[nameof(MvcViewOptions.SuppressTempDataAttributePrefix)] = true,
|
||||
[nameof(MvcViewOptions.AllowRenderingMaxLengthAttribute)] = true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -68,5 +68,15 @@
|
|||
"TypeId": "public class Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor : Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor, Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor<Microsoft.AspNetCore.Mvc.ViewResult>",
|
||||
"MemberId": "public .ctor(Microsoft.Extensions.Options.IOptions<Microsoft.AspNetCore.Mvc.MvcViewOptions> viewOptions, Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory writerFactory, Microsoft.AspNetCore.Mvc.ViewEngines.ICompositeViewEngine viewEngine, Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionaryFactory tempDataFactory, System.Diagnostics.DiagnosticSource diagnosticSource, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider modelMetadataProvider)",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.MvcViewOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Boolean get_SuppressTempDataAttributePrefix()",
|
||||
"Kind": "Removal"
|
||||
},
|
||||
{
|
||||
"TypeId": "public class Microsoft.AspNetCore.Mvc.MvcViewOptions : System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch>",
|
||||
"MemberId": "public System.Void set_SuppressTempDataAttributePrefix(System.Boolean value)",
|
||||
"Kind": "Removal"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
|
|
|||
|
|
@ -195,11 +195,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
}
|
||||
|
||||
// Throwing InputFormatterException
|
||||
[Theory]
|
||||
[InlineData(InputFormatterExceptionPolicy.AllExceptions)]
|
||||
[InlineData(InputFormatterExceptionPolicy.MalformedInputExceptions)]
|
||||
public async Task BindModel_CustomFormatter_ThrowingInputFormatterException_AddsErrorToModelState(
|
||||
InputFormatterExceptionPolicy inputFormatterExceptionPolicy)
|
||||
[Fact]
|
||||
public async Task BindModel_CustomFormatter_ThrowingInputFormatterException_AddsErrorToModelState()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
|
@ -215,12 +212,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
{
|
||||
throw new InputFormatterException("Bad input!!", expectedFormatException);
|
||||
});
|
||||
var binder = CreateBinder(
|
||||
new[] { formatter },
|
||||
new MvcOptions()
|
||||
{
|
||||
InputFormatterExceptionPolicy = inputFormatterExceptionPolicy
|
||||
});
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions());
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -237,16 +229,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
Assert.Null(entry.Value.Errors[0].Exception);
|
||||
}
|
||||
|
||||
public static TheoryData<IInputFormatter, InputFormatterExceptionPolicy> BuiltInFormattersThrowingInputFormatterException
|
||||
public static TheoryData<IInputFormatter> BuiltInFormattersThrowingInputFormatterException
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<IInputFormatter, InputFormatterExceptionPolicy>()
|
||||
return new TheoryData<IInputFormatter>()
|
||||
{
|
||||
{ new XmlSerializerInputFormatter(new MvcOptions()), InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new XmlSerializerInputFormatter(new MvcOptions()), InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new XmlDataContractSerializerInputFormatter(new MvcOptions()), InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new XmlDataContractSerializerInputFormatter(new MvcOptions()), InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new XmlSerializerInputFormatter(new MvcOptions()) },
|
||||
{ new XmlDataContractSerializerInputFormatter(new MvcOptions()) },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -254,8 +244,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
[Theory]
|
||||
[MemberData(nameof(BuiltInFormattersThrowingInputFormatterException))]
|
||||
public async Task BindModel_BuiltInXmlInputFormatters_ThrowingInputFormatterException_AddsErrorToModelState(
|
||||
IInputFormatter formatter,
|
||||
InputFormatterExceptionPolicy inputFormatterExceptionPolicy)
|
||||
IInputFormatter formatter)
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
|
@ -266,10 +255,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
metadataProvider.ForType<Person>().BindingDetails(d => d.BindingSource = BindingSource.Body);
|
||||
|
||||
var bindingContext = GetBindingContext(typeof(Person), httpContext, metadataProvider);
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions()
|
||||
{
|
||||
InputFormatterExceptionPolicy = inputFormatterExceptionPolicy
|
||||
});
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions());
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -286,11 +272,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
Assert.Null(entry.Value.Errors[0].Exception);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(InputFormatterExceptionPolicy.AllExceptions)]
|
||||
[InlineData(InputFormatterExceptionPolicy.MalformedInputExceptions)]
|
||||
public async Task BindModel_BuiltInJsonInputFormatter_ThrowingInputFormatterException_AddsErrorToModelState(
|
||||
InputFormatterExceptionPolicy inputFormatterExceptionPolicy)
|
||||
[Fact]
|
||||
public async Task BindModel_BuiltInJsonInputFormatter_ThrowingInputFormatterException_AddsErrorToModelState()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
|
@ -303,10 +286,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
var bindingContext = GetBindingContext(typeof(Person), httpContext, metadataProvider);
|
||||
var binder = CreateBinder(
|
||||
new[] { new TestableJsonInputFormatter(throwNonInputFormatterException: false) },
|
||||
new MvcOptions()
|
||||
{
|
||||
InputFormatterExceptionPolicy = inputFormatterExceptionPolicy
|
||||
});
|
||||
new MvcOptions());
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -321,25 +301,21 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
Assert.NotEmpty(entry.Value.Errors[0].ErrorMessage);
|
||||
}
|
||||
|
||||
public static TheoryData<IInputFormatter, InputFormatterExceptionPolicy> DerivedFormattersThrowingInputFormatterException
|
||||
public static TheoryData<IInputFormatter> DerivedFormattersThrowingInputFormatterException
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<IInputFormatter, InputFormatterExceptionPolicy>()
|
||||
return new TheoryData<IInputFormatter>()
|
||||
{
|
||||
{ new DerivedXmlSerializerInputFormatter(throwNonInputFormatterException: false), InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new DerivedXmlSerializerInputFormatter(throwNonInputFormatterException: false), InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new DerivedXmlDataContractSerializerInputFormatter(throwNonInputFormatterException: false), InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new DerivedXmlDataContractSerializerInputFormatter(throwNonInputFormatterException: false), InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new DerivedXmlSerializerInputFormatter(throwNonInputFormatterException: false) },
|
||||
{ new DerivedXmlDataContractSerializerInputFormatter(throwNonInputFormatterException: false) },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(DerivedFormattersThrowingInputFormatterException))]
|
||||
public async Task BindModel_DerivedXmlInputFormatters_AddsErrorToModelState_(
|
||||
IInputFormatter formatter,
|
||||
InputFormatterExceptionPolicy inputFormatterExceptionPolicy)
|
||||
public async Task BindModel_DerivedXmlInputFormatters_AddsErrorToModelState(IInputFormatter formatter)
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
|
@ -350,10 +326,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
metadataProvider.ForType<Person>().BindingDetails(d => d.BindingSource = BindingSource.Body);
|
||||
|
||||
var bindingContext = GetBindingContext(typeof(Person), httpContext, metadataProvider);
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions()
|
||||
{
|
||||
InputFormatterExceptionPolicy = inputFormatterExceptionPolicy
|
||||
});
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions());
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -370,11 +343,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
Assert.Null(entry.Value.Errors[0].Exception);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(InputFormatterExceptionPolicy.AllExceptions)]
|
||||
[InlineData(InputFormatterExceptionPolicy.MalformedInputExceptions)]
|
||||
public async Task BindModel_DerivedJsonInputFormatter_AddsErrorToModelState(
|
||||
InputFormatterExceptionPolicy inputFormatterExceptionPolicy)
|
||||
[Fact]
|
||||
public async Task BindModel_DerivedJsonInputFormatter_AddsErrorToModelState()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
|
@ -387,10 +357,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
var bindingContext = GetBindingContext(typeof(Person), httpContext, metadataProvider);
|
||||
var binder = CreateBinder(
|
||||
new[] { new DerivedJsonInputFormatter(throwNonInputFormatterException: false) },
|
||||
new MvcOptions()
|
||||
{
|
||||
InputFormatterExceptionPolicy = inputFormatterExceptionPolicy
|
||||
});
|
||||
new MvcOptions());
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -407,18 +374,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
}
|
||||
|
||||
// Throwing Non-InputFormatterException
|
||||
public static TheoryData<IInputFormatter, string, InputFormatterExceptionPolicy> BuiltInFormattersThrowingNonInputFormatterException
|
||||
public static TheoryData<IInputFormatter, string> BuiltInFormattersThrowingNonInputFormatterException
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<IInputFormatter, string, InputFormatterExceptionPolicy>()
|
||||
return new TheoryData<IInputFormatter, string>()
|
||||
{
|
||||
{ new TestableXmlSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml", InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new TestableXmlSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml", InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new TestableXmlDataContractSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml", InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new TestableXmlDataContractSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml", InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new TestableJsonInputFormatter(throwNonInputFormatterException: true), "text/json", InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new TestableJsonInputFormatter(throwNonInputFormatterException: true), "text/json", InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new TestableXmlSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml" },
|
||||
{ new TestableXmlDataContractSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml" },
|
||||
{ new TestableJsonInputFormatter(throwNonInputFormatterException: true), "text/json" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -427,8 +391,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
[MemberData(nameof(BuiltInFormattersThrowingNonInputFormatterException))]
|
||||
public async Task BindModel_BuiltInInputFormatters_ThrowingNonInputFormatterException_Throws(
|
||||
IInputFormatter formatter,
|
||||
string contentType,
|
||||
InputFormatterExceptionPolicy inputFormatterExceptionPolicy)
|
||||
string contentType)
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
|
@ -439,28 +402,22 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
metadataProvider.ForType<Person>().BindingDetails(d => d.BindingSource = BindingSource.Body);
|
||||
|
||||
var bindingContext = GetBindingContext(typeof(Person), httpContext, metadataProvider);
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions()
|
||||
{
|
||||
InputFormatterExceptionPolicy = inputFormatterExceptionPolicy
|
||||
});
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions());
|
||||
|
||||
// Act & Assert
|
||||
var exception = await Assert.ThrowsAsync<IOException>(() => binder.BindModelAsync(bindingContext));
|
||||
Assert.Equal("Unable to read input stream!!", exception.Message);
|
||||
}
|
||||
|
||||
public static TheoryData<IInputFormatter, string, InputFormatterExceptionPolicy> DerivedInputFormattersThrowingNonInputFormatterException
|
||||
public static TheoryData<IInputFormatter, string> DerivedInputFormattersThrowingNonInputFormatterException
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<IInputFormatter, string, InputFormatterExceptionPolicy>()
|
||||
return new TheoryData<IInputFormatter, string>()
|
||||
{
|
||||
{ new DerivedXmlSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml", InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new DerivedXmlSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml", InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new DerivedXmlDataContractSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml", InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new DerivedXmlDataContractSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml", InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new DerivedJsonInputFormatter(throwNonInputFormatterException: true), "text/json", InputFormatterExceptionPolicy.AllExceptions },
|
||||
{ new DerivedJsonInputFormatter(throwNonInputFormatterException: true), "text/json", InputFormatterExceptionPolicy.MalformedInputExceptions },
|
||||
{ new DerivedXmlSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml" },
|
||||
{ new DerivedXmlDataContractSerializerInputFormatter(throwNonInputFormatterException: true), "text/xml" },
|
||||
{ new DerivedJsonInputFormatter(throwNonInputFormatterException: true), "text/json" },
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -469,8 +426,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
[MemberData(nameof(DerivedInputFormattersThrowingNonInputFormatterException))]
|
||||
public async Task BindModel_DerivedXmlInputFormatters_ThrowingNonInputFormattingException_AddsErrorToModelState(
|
||||
IInputFormatter formatter,
|
||||
string contentType,
|
||||
InputFormatterExceptionPolicy inputFormatterExceptionPolicy)
|
||||
string contentType)
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
|
|
@ -481,10 +437,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
metadataProvider.ForType<Person>().BindingDetails(d => d.BindingSource = BindingSource.Body);
|
||||
|
||||
var bindingContext = GetBindingContext(typeof(Person), httpContext, metadataProvider);
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions()
|
||||
{
|
||||
InputFormatterExceptionPolicy = inputFormatterExceptionPolicy
|
||||
});
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions());
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -517,12 +470,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
{
|
||||
throw new IOException("Unable to read input stream!!");
|
||||
});
|
||||
var binder = CreateBinder(
|
||||
new[] { formatter },
|
||||
new MvcOptions()
|
||||
{
|
||||
InputFormatterExceptionPolicy = InputFormatterExceptionPolicy.MalformedInputExceptions
|
||||
});
|
||||
var binder = CreateBinder(new[] { formatter }, new MvcOptions());
|
||||
|
||||
// Act
|
||||
var exception = await Assert.ThrowsAsync<IOException>(
|
||||
|
|
@ -530,44 +478,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
Assert.Equal("Unable to read input stream!!", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindModel_CustomFormatter_ThrowingNonInputFormatterException_AddsErrorToModelState()
|
||||
{
|
||||
// Arrange
|
||||
var httpContext = new DefaultHttpContext();
|
||||
httpContext.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes("Bad data!"));
|
||||
httpContext.Request.ContentType = "text/xyz";
|
||||
|
||||
var metadataProvider = new TestModelMetadataProvider();
|
||||
metadataProvider.ForType<Person>().BindingDetails(d => d.BindingSource = BindingSource.Body);
|
||||
|
||||
var bindingContext = GetBindingContext(typeof(Person), httpContext, metadataProvider);
|
||||
var formatter = new XyzFormatter((inputFormatterContext, encoding) =>
|
||||
{
|
||||
throw new IOException("Unable to read input stream!!");
|
||||
});
|
||||
var binder = CreateBinder(
|
||||
new[] { formatter },
|
||||
new MvcOptions()
|
||||
{
|
||||
InputFormatterExceptionPolicy = InputFormatterExceptionPolicy.AllExceptions
|
||||
});
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.False(bindingContext.Result.IsModelSet);
|
||||
Assert.Null(bindingContext.Result.Model);
|
||||
|
||||
// Key is the empty string because this was a top-level binding.
|
||||
var entry = Assert.Single(bindingContext.ModelState);
|
||||
Assert.Equal(string.Empty, entry.Key);
|
||||
var errorMessage = Assert.Single(entry.Value.Errors).Exception.Message;
|
||||
Assert.Equal("Unable to read input stream!!", errorMessage);
|
||||
Assert.IsType<IOException>(entry.Value.Errors[0].Exception);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NullFormatterError_AddedToModelState()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
bool isBindingRequired)
|
||||
{
|
||||
// Arrange
|
||||
var expectedErrorCount = isBindingRequired ? 1 : 0;
|
||||
var mockValueProvider = new Mock<IValueProvider>();
|
||||
mockValueProvider
|
||||
.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
|
||||
|
|
@ -305,7 +306,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
var bindingContext = new DefaultModelBindingContext
|
||||
{
|
||||
IsTopLevelObject = true,
|
||||
ModelMetadata = GetMetadataForType(typeof(Person)),
|
||||
ModelMetadata = metadata,
|
||||
ModelName = string.Empty,
|
||||
ValueProvider = mockValueProvider.Object,
|
||||
ModelState = new ModelStateDictionary(),
|
||||
|
|
@ -330,7 +331,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
|
||||
// Assert
|
||||
Assert.True(bindingContext.Result.IsModelSet);
|
||||
Assert.Equal(0, bindingContext.ModelState.ErrorCount);
|
||||
Assert.Equal(expectedErrorCount, bindingContext.ModelState.ErrorCount);
|
||||
|
||||
var returnedPerson = Assert.IsType<Person>(bindingContext.Result.Model);
|
||||
Assert.Same(model, returnedPerson);
|
||||
|
|
@ -1115,8 +1116,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
var type = model.GetType();
|
||||
var bindingContext = CreateContext(GetMetadataForType(type), model);
|
||||
var modelState = bindingContext.ModelState;
|
||||
var metadata = GetMetadataForType(type);
|
||||
|
||||
var propertyMetadata = bindingContext.ModelMetadata.Properties[propertyName];
|
||||
var result = ModelBindingResult.Success(new Simple { Name = "Hanna" });
|
||||
|
||||
|
|
@ -1160,8 +1159,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
// Arrange
|
||||
var model = new Person();
|
||||
var bindingContext = CreateContext(GetMetadataForType(model.GetType()), model);
|
||||
|
||||
var metadata = GetMetadataForType(typeof(Person));
|
||||
var propertyMetadata = bindingContext.ModelMetadata.Properties[nameof(model.DateOfBirth)];
|
||||
|
||||
var result = ModelBindingResult.Success(new DateTime(2001, 1, 1));
|
||||
|
|
@ -1186,8 +1183,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
};
|
||||
|
||||
var bindingContext = CreateContext(GetMetadataForType(model.GetType()), model);
|
||||
|
||||
var metadata = GetMetadataForType(typeof(Person));
|
||||
var propertyMetadata = bindingContext.ModelMetadata.Properties[nameof(model.DateOfDeath)];
|
||||
|
||||
var result = ModelBindingResult.Success(new DateTime(1800, 1, 1));
|
||||
|
|
@ -1210,8 +1205,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
|
|||
var model = new ModelWhosePropertySetterThrows();
|
||||
var bindingContext = CreateContext(GetMetadataForType(model.GetType()), model);
|
||||
bindingContext.ModelName = "foo";
|
||||
|
||||
var metadata = GetMetadataForType(typeof(ModelWhosePropertySetterThrows));
|
||||
var propertyMetadata = bindingContext.ModelMetadata.Properties[nameof(model.NameNoAttribute)];
|
||||
|
||||
var result = ModelBindingResult.Success(model: null);
|
||||
|
|
|
|||
|
|
@ -12,21 +12,12 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
public class EnumTypeModelBinderTest
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(true, typeof(IntEnum?))]
|
||||
[InlineData(true, typeof(FlagsEnum?))]
|
||||
[InlineData(false, typeof(IntEnum?))]
|
||||
[InlineData(false, typeof(FlagsEnum?))]
|
||||
public async Task BindModel_SetsModel_ForEmptyValue_AndNullableEnumTypes(
|
||||
bool suppressBindingUndefinedValueToEnumType,
|
||||
Type modelType)
|
||||
[InlineData(typeof(IntEnum?))]
|
||||
[InlineData(typeof(FlagsEnum?))]
|
||||
public async Task BindModel_SetsModel_ForEmptyValue_AndNullableEnumTypes(Type modelType)
|
||||
{
|
||||
// Arrange
|
||||
var binderInfo = GetBinderAndContext(
|
||||
modelType,
|
||||
suppressBindingUndefinedValueToEnumType,
|
||||
valueProviderValue: "");
|
||||
var bindingContext = binderInfo.Item1;
|
||||
var binder = binderInfo.Item2;
|
||||
var (bindingContext, binder) = GetBinderAndContext(modelType, valueProviderValue: "");
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -37,22 +28,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, typeof(IntEnum))]
|
||||
[InlineData(true, typeof(FlagsEnum))]
|
||||
[InlineData(false, typeof(IntEnum))]
|
||||
[InlineData(false, typeof(FlagsEnum))]
|
||||
public async Task BindModel_AddsErrorToModelState_ForEmptyValue_AndNonNullableEnumTypes(
|
||||
bool suppressBindingUndefinedValueToEnumType,
|
||||
Type modelType)
|
||||
[InlineData(typeof(IntEnum))]
|
||||
[InlineData(typeof(FlagsEnum))]
|
||||
public async Task BindModel_AddsErrorToModelState_ForEmptyValue_AndNonNullableEnumTypes(Type modelType)
|
||||
{
|
||||
// Arrange
|
||||
var message = "The value '' is invalid.";
|
||||
var binderInfo = GetBinderAndContext(
|
||||
modelType,
|
||||
suppressBindingUndefinedValueToEnumType,
|
||||
valueProviderValue: "");
|
||||
var bindingContext = binderInfo.Item1;
|
||||
var binder = binderInfo.Item2;
|
||||
var (bindingContext, binder) = GetBinderAndContext(modelType, valueProviderValue: "");
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -66,22 +48,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, "Value1")]
|
||||
[InlineData(true, "1")]
|
||||
[InlineData(false, "Value1")]
|
||||
[InlineData(false, "1")]
|
||||
public async Task BindModel_BindsEnumModels_ForValuesInArray(
|
||||
bool suppressBindingUndefinedValueToEnumType,
|
||||
string enumValue)
|
||||
[InlineData("Value1")]
|
||||
[InlineData("1")]
|
||||
public async Task BindModel_BindsEnumModels_ForValuesInArray(string enumValue)
|
||||
{
|
||||
// Arrange
|
||||
var modelType = typeof(IntEnum);
|
||||
var binderInfo = GetBinderAndContext(
|
||||
var (bindingContext, binder) = GetBinderAndContext(
|
||||
modelType,
|
||||
suppressBindingUndefinedValueToEnumType,
|
||||
valueProviderValue: new object[] { enumValue });
|
||||
var bindingContext = binderInfo.Item1;
|
||||
var binder = binderInfo.Item2;
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -93,26 +68,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1", true)]
|
||||
[InlineData("8, 1", true)]
|
||||
[InlineData("Value2, Value8", true)]
|
||||
[InlineData("value8,value4,value2,value1", true)]
|
||||
[InlineData("1", false)]
|
||||
[InlineData("8, 1", false)]
|
||||
[InlineData("Value2, Value8", false)]
|
||||
[InlineData("value8,value4,value2,value1", false)]
|
||||
public async Task BindModel_BindsTo_NonNullableFlagsEnumType(string flagsEnumValue, bool suppressBindingUndefinedValueToEnumType)
|
||||
[InlineData("1")]
|
||||
[InlineData("8, 1")]
|
||||
[InlineData("Value2, Value8")]
|
||||
[InlineData("value8,value4,value2,value1")]
|
||||
public async Task BindModel_BindsTo_NonNullableFlagsEnumType(string flagsEnumValue)
|
||||
{
|
||||
// Arrange
|
||||
var modelType = typeof(FlagsEnum);
|
||||
var enumConverter = TypeDescriptor.GetConverter(modelType);
|
||||
var expected = enumConverter.ConvertFrom(flagsEnumValue).ToString();
|
||||
var binderInfo = GetBinderAndContext(
|
||||
var (bindingContext, binder) = GetBinderAndContext(
|
||||
modelType,
|
||||
suppressBindingUndefinedValueToEnumType,
|
||||
valueProviderValue: new object[] { flagsEnumValue });
|
||||
var bindingContext = binderInfo.Item1;
|
||||
var binder = binderInfo.Item2;
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -124,26 +92,19 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("1", true)]
|
||||
[InlineData("8, 1", true)]
|
||||
[InlineData("Value2, Value8", true)]
|
||||
[InlineData("value8,value4,value2,value1", true)]
|
||||
[InlineData("1", false)]
|
||||
[InlineData("8, 1", false)]
|
||||
[InlineData("Value2, Value8", false)]
|
||||
[InlineData("value8,value4,value2,value1", false)]
|
||||
public async Task BindModel_BindsTo_NullableFlagsEnumType(string flagsEnumValue, bool suppressBindingUndefinedValueToEnumType)
|
||||
[InlineData("1")]
|
||||
[InlineData("8, 1")]
|
||||
[InlineData("Value2, Value8")]
|
||||
[InlineData("value8,value4,value2,value1")]
|
||||
public async Task BindModel_BindsTo_NullableFlagsEnumType(string flagsEnumValue)
|
||||
{
|
||||
// Arrange
|
||||
var modelType = typeof(FlagsEnum?);
|
||||
var enumConverter = TypeDescriptor.GetConverter(GetUnderlyingType(modelType));
|
||||
var expected = enumConverter.ConvertFrom(flagsEnumValue).ToString();
|
||||
var binderInfo = GetBinderAndContext(
|
||||
var (bindingContext, binder) = GetBinderAndContext(
|
||||
modelType,
|
||||
suppressBindingUndefinedValueToEnumType,
|
||||
valueProviderValue: new object[] { flagsEnumValue });
|
||||
var bindingContext = binderInfo.Item1;
|
||||
var binder = binderInfo.Item2;
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -154,36 +115,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
Assert.Equal(expected, boundModel.ToString());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(FlagsEnum), "Value10")]
|
||||
[InlineData(typeof(FlagsEnum), "Value1, Value10")]
|
||||
[InlineData(typeof(FlagsEnum), "value10, value1")]
|
||||
[InlineData(typeof(FlagsEnum?), "Value10")]
|
||||
[InlineData(typeof(FlagsEnum?), "Value1, Value10")]
|
||||
[InlineData(typeof(FlagsEnum?), "value10, value1")]
|
||||
public async Task BindModel_AddsErrorToModelState_ForInvalidEnumValues_IsNotValidMessage(Type modelType, string suppliedValue)
|
||||
{
|
||||
// Arrange
|
||||
var message = $"The value '{suppliedValue}' is not valid.";
|
||||
var binderInfo = GetBinderAndContext(
|
||||
modelType,
|
||||
suppressBindingUndefinedValueToEnumType: false,
|
||||
valueProviderValue: new object[] { suppliedValue });
|
||||
var bindingContext = binderInfo.Item1;
|
||||
var binder = binderInfo.Item2;
|
||||
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.False(bindingContext.Result.IsModelSet);
|
||||
Assert.Null(bindingContext.Result.Model);
|
||||
Assert.False(bindingContext.ModelState.IsValid);
|
||||
var error = Assert.Single(bindingContext.ModelState["theModelName"].Errors);
|
||||
Assert.Equal(message, error.ErrorMessage);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(IntEnum), "")]
|
||||
[InlineData(typeof(IntEnum), "3")]
|
||||
|
|
@ -206,12 +137,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{
|
||||
// Arrange
|
||||
var message = $"The value '{suppliedValue}' is invalid.";
|
||||
var binderInfo = GetBinderAndContext(
|
||||
var (bindingContext, binder) = GetBinderAndContext(
|
||||
modelType,
|
||||
suppressBindingUndefinedValueToEnumType: true,
|
||||
valueProviderValue: new object[] { suppliedValue });
|
||||
var bindingContext = binderInfo.Item1;
|
||||
var binder = binderInfo.Item2;
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
|
@ -224,49 +152,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
Assert.Equal(message, error.ErrorMessage);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(typeof(IntEnum), "3", 3)]
|
||||
[InlineData(typeof(FlagsEnum), "19", 19)]
|
||||
[InlineData(typeof(FlagsEnum), "0", 0)]
|
||||
[InlineData(typeof(FlagsEnum), "1, 16", 17)]
|
||||
// These two values look like big integers but are treated as two separate enum values that are
|
||||
// or'd together.
|
||||
[InlineData(typeof(FlagsEnum), "32,015", 47)]
|
||||
[InlineData(typeof(FlagsEnum), "32,128", 160)]
|
||||
[InlineData(typeof(IntEnum?), "3", 3)]
|
||||
[InlineData(typeof(FlagsEnum?), "19", 19)]
|
||||
[InlineData(typeof(FlagsEnum?), "0", 0)]
|
||||
[InlineData(typeof(FlagsEnum?), "1, 16", 17)]
|
||||
// These two values look like big integers but are treated as two separate enum values that are
|
||||
// or'd together.
|
||||
[InlineData(typeof(FlagsEnum?), "32,015", 47)]
|
||||
[InlineData(typeof(FlagsEnum?), "32,128", 160)]
|
||||
public async Task BindModel_AllowsBindingUndefinedValues_ToEnumTypes(
|
||||
Type modelType,
|
||||
string suppliedValue,
|
||||
long expected)
|
||||
{
|
||||
// Arrange
|
||||
var binderProviderContext = new TestModelBinderProviderContext(modelType);
|
||||
var binderInfo = GetBinderAndContext(
|
||||
modelType,
|
||||
suppressBindingUndefinedValueToEnumType: false,
|
||||
valueProviderValue: new object[] { suppliedValue });
|
||||
var bindingContext = binderInfo.Item1;
|
||||
var binder = binderInfo.Item2;
|
||||
|
||||
// Act
|
||||
await binder.BindModelAsync(bindingContext);
|
||||
|
||||
// Assert
|
||||
Assert.True(bindingContext.Result.IsModelSet);
|
||||
Assert.IsType(GetUnderlyingType(modelType), bindingContext.Result.Model);
|
||||
Assert.Equal(expected, Convert.ToInt64(bindingContext.Result.Model));
|
||||
}
|
||||
|
||||
private static (DefaultModelBindingContext, IModelBinder) GetBinderAndContext(
|
||||
Type modelType,
|
||||
bool suppressBindingUndefinedValueToEnumType,
|
||||
object valueProviderValue)
|
||||
{
|
||||
var binderProviderContext = new TestModelBinderProviderContext(modelType);
|
||||
|
|
@ -281,10 +168,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
|||
{ modelName, valueProviderValue }
|
||||
}
|
||||
};
|
||||
var binderProvider = new EnumTypeModelBinderProvider(new MvcOptions
|
||||
{
|
||||
SuppressBindingUndefinedValueToEnumType = suppressBindingUndefinedValueToEnumType
|
||||
});
|
||||
|
||||
var binderProvider = new EnumTypeModelBinderProvider(new MvcOptions());
|
||||
|
||||
var binder = binderProvider.GetBinder(binderProviderContext);
|
||||
return (bindingContext, binder);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Validation
|
|||
{
|
||||
public class DefaultObjectValidatorTests
|
||||
{
|
||||
private readonly MvcOptions _options = new MvcOptions { AllowShortCircuitingValidationWhenNoValidatorsArePresent = true };
|
||||
private readonly MvcOptions _options = new MvcOptions();
|
||||
|
||||
private ModelMetadataProvider MetadataProvider { get; } = TestModelMetadataProvider.CreateDefaultProvider();
|
||||
|
||||
|
|
|
|||
|
|
@ -275,53 +275,6 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
Assert.Equal("DisplayNameAttributeValue", context.DisplayMetadata.DisplayName());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateDisplayMetadata_DisplayNameAttribute_OnEnum_CompatSwitchWorks()
|
||||
{
|
||||
// Arrange
|
||||
var unsharedLocalizer = new Mock<IStringLocalizer>(MockBehavior.Strict);
|
||||
unsharedLocalizer
|
||||
.Setup(s => s["DisplayNameValue"])
|
||||
.Returns(new LocalizedString("DisplaynameValue", "didn't use shared"));
|
||||
|
||||
var sharedLocalizer = new Mock<IStringLocalizer>(MockBehavior.Strict);
|
||||
sharedLocalizer
|
||||
.Setup(s => s["DisplayNameValue"])
|
||||
.Returns(() => new LocalizedString("DisplayNameValue", "used shared"));
|
||||
|
||||
var stringLocalizerFactoryMock = new Mock<IStringLocalizerFactory>(MockBehavior.Strict);
|
||||
stringLocalizerFactoryMock
|
||||
.Setup(s => s.Create(typeof(TestEnum)))
|
||||
.Returns(() => unsharedLocalizer.Object);
|
||||
stringLocalizerFactoryMock
|
||||
.Setup(s => s.Create(typeof(EmptyClass)))
|
||||
.Returns(() => sharedLocalizer.Object);
|
||||
|
||||
var localizationOptions = Options.Create(new MvcDataAnnotationsLocalizationOptions());
|
||||
localizationOptions.Value.AllowDataAnnotationsLocalizationForEnumDisplayAttributes = false;
|
||||
localizationOptions.Value.DataAnnotationLocalizerProvider = (type, stringLocalizerFactory) =>
|
||||
{
|
||||
return stringLocalizerFactory.Create(typeof(EmptyClass));
|
||||
};
|
||||
|
||||
var provider = new DataAnnotationsMetadataProvider(
|
||||
localizationOptions,
|
||||
stringLocalizerFactory: stringLocalizerFactoryMock.Object);
|
||||
|
||||
var displayName = new DisplayNameAttribute("DisplayNameValue");
|
||||
|
||||
var attributes = new Attribute[] { displayName };
|
||||
var key = ModelMetadataIdentity.ForType(typeof(TestEnum));
|
||||
var context = new DisplayMetadataProviderContext(key, GetModelAttributes(attributes));
|
||||
|
||||
// Act
|
||||
provider.CreateDisplayMetadata(context);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(context.DisplayMetadata.EnumGroupedDisplayNamesAndValues,
|
||||
(e) => Assert.Equal("didn't use shared", e.Key.Name));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateDisplayMetadata_DisplayNameAttribute_OnEnum_CompatShimOn()
|
||||
{
|
||||
|
|
@ -337,7 +290,6 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
.Returns(() => sharedLocalizer.Object);
|
||||
|
||||
var localizationOptions = Options.Create(new MvcDataAnnotationsLocalizationOptions());
|
||||
localizationOptions.Value.AllowDataAnnotationsLocalizationForEnumDisplayAttributes = true;
|
||||
localizationOptions.Value.DataAnnotationLocalizerProvider = (type, stringLocalizerFactory) =>
|
||||
{
|
||||
return stringLocalizerFactory.Create(typeof(EmptyClass));
|
||||
|
|
@ -1269,7 +1221,7 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
new RequiredAttribute(),
|
||||
new StringLengthAttribute(5)
|
||||
};
|
||||
|
||||
|
||||
Assert.Equal(expected, actual: context.ValidationMetadata.ValidatorMetadata);
|
||||
}
|
||||
|
||||
|
|
@ -1580,7 +1532,7 @@ namespace Microsoft.AspNetCore.Mvc.DataAnnotations
|
|||
|
||||
private class FooCompositeValidationAttribute : ValidationProviderAttribute
|
||||
{
|
||||
private IEnumerable<ValidationAttribute> _attributes;
|
||||
private readonly IEnumerable<ValidationAttribute> _attributes;
|
||||
|
||||
public FooCompositeValidationAttribute(IEnumerable<ValidationAttribute> attributes)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -725,35 +725,6 @@ namespace Microsoft.AspNetCore.Mvc.Formatters
|
|||
treatEmptyInputAsDefaultValue: treatEmptyInputAsDefaultValue);
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetModelStateErrorMessages(ModelStateDictionary modelStateDictionary)
|
||||
{
|
||||
var allErrorMessages = new List<string>();
|
||||
foreach (var keyModelStatePair in modelStateDictionary)
|
||||
{
|
||||
var key = keyModelStatePair.Key;
|
||||
var errors = keyModelStatePair.Value.Errors;
|
||||
if (errors != null && errors.Count > 0)
|
||||
{
|
||||
foreach (var modelError in errors)
|
||||
{
|
||||
if (string.IsNullOrEmpty(modelError.ErrorMessage))
|
||||
{
|
||||
if (modelError.Exception != null)
|
||||
{
|
||||
allErrorMessages.Add(modelError.Exception.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
allErrorMessages.Add(modelError.ErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allErrorMessages;
|
||||
}
|
||||
|
||||
private sealed class User
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters.Xml;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -15,7 +14,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public void AddsFormatterMapping()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new XmlDataContractSerializerMvcOptionsSetup(Options.Options.Create(new MvcXmlOptions()), NullLoggerFactory.Instance);
|
||||
var optionsSetup = new XmlDataContractSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
|
||||
// Act
|
||||
|
|
@ -30,7 +29,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public void DoesNotOverrideExistingMapping()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new XmlDataContractSerializerMvcOptionsSetup(Options.Options.Create(new MvcXmlOptions()), NullLoggerFactory.Instance);
|
||||
var optionsSetup = new XmlDataContractSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat("xml", "text/xml");
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public void AddsInputFormatter()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new XmlDataContractSerializerMvcOptionsSetup(Options.Options.Create(new MvcXmlOptions()), NullLoggerFactory.Instance);
|
||||
var optionsSetup = new XmlDataContractSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
|
||||
// Act
|
||||
|
|
@ -60,7 +59,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public void AddsOutputFormatter()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new XmlDataContractSerializerMvcOptionsSetup(Options.Options.Create(new MvcXmlOptions()), NullLoggerFactory.Instance);
|
||||
var optionsSetup = new XmlDataContractSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters.Xml;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -16,7 +14,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public void AddsFormatterMapping()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new XmlSerializerMvcOptionsSetup(Options.Options.Create(new MvcXmlOptions()), NullLoggerFactory.Instance);
|
||||
var optionsSetup = new XmlSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
|
||||
// Act
|
||||
|
|
@ -31,7 +29,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public void DoesNotOverrideExistingMapping()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new XmlSerializerMvcOptionsSetup(Options.Options.Create(new MvcXmlOptions()), NullLoggerFactory.Instance);
|
||||
var optionsSetup = new XmlSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat("xml", "text/xml");
|
||||
|
||||
|
|
@ -47,7 +45,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public void AddsInputFormatter()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new XmlSerializerMvcOptionsSetup(Options.Options.Create(new MvcXmlOptions()), NullLoggerFactory.Instance);
|
||||
var optionsSetup = new XmlSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
|
||||
// Act
|
||||
|
|
@ -61,7 +59,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
public void AddsOutputFormatter()
|
||||
{
|
||||
// Arrange
|
||||
var optionsSetup = new XmlSerializerMvcOptionsSetup(Options.Options.Create(new MvcXmlOptions()), NullLoggerFactory.Instance);
|
||||
var optionsSetup = new XmlSerializerMvcOptionsSetup(NullLoggerFactory.Instance);
|
||||
var options = new MvcOptions();
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
|
|||
public void GetProvider_ReturnsNull_IfTypeDoesNotMatch()
|
||||
{
|
||||
// Arrange
|
||||
var xmlOptions = new MvcXmlOptions();
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory(xmlOptions);
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory();
|
||||
var context = new WrapperProviderContext(typeof(SerializableError), isSerialization: true);
|
||||
|
||||
// Act
|
||||
|
|
@ -26,8 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
|
|||
public void GetProvider_ReturnsWrapper_ForProblemDetails()
|
||||
{
|
||||
// Arrange
|
||||
var xmlOptions = new MvcXmlOptions { AllowRfc7807CompliantProblemDetailsFormat = true };
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory(xmlOptions);
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory();
|
||||
var instance = new ProblemDetails();
|
||||
var context = new WrapperProviderContext(instance.GetType(), isSerialization: true);
|
||||
|
||||
|
|
@ -40,32 +38,11 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
|
|||
Assert.Same(instance, wrapper.ProblemDetails);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetProvider_Returns21CompatibleWrapper_ForProblemDetails()
|
||||
{
|
||||
// Arrange
|
||||
var xmlOptions = new MvcXmlOptions();
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory(xmlOptions);
|
||||
var instance = new ProblemDetails();
|
||||
var context = new WrapperProviderContext(instance.GetType(), isSerialization: true);
|
||||
|
||||
// Act
|
||||
var provider = providerFactory.GetProvider(context);
|
||||
|
||||
// Assert
|
||||
var result = provider.Wrap(instance);
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var wrapper = Assert.IsType<ProblemDetails21Wrapper>(result);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
Assert.Same(instance, wrapper.ProblemDetails);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetProvider_ReturnsWrapper_ForValidationProblemDetails()
|
||||
{
|
||||
// Arrange
|
||||
var xmlOptions = new MvcXmlOptions { AllowRfc7807CompliantProblemDetailsFormat = true };
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory(xmlOptions);
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory();
|
||||
var instance = new ValidationProblemDetails();
|
||||
var context = new WrapperProviderContext(instance.GetType(), isSerialization: true);
|
||||
|
||||
|
|
@ -78,32 +55,11 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Xml
|
|||
Assert.Same(instance, wrapper.ProblemDetails);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetProvider_Returns21CompatibleWrapper_ForValidationProblemDetails()
|
||||
{
|
||||
// Arrange
|
||||
var xmlOptions = new MvcXmlOptions();
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory(xmlOptions);
|
||||
var instance = new ValidationProblemDetails();
|
||||
var context = new WrapperProviderContext(instance.GetType(), isSerialization: true);
|
||||
|
||||
// Act
|
||||
var provider = providerFactory.GetProvider(context);
|
||||
|
||||
// Assert
|
||||
var result = provider.Wrap(instance);
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
var wrapper = Assert.IsType<ValidationProblemDetails21Wrapper>(result);
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
Assert.Same(instance, wrapper.ProblemDetails);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetProvider_ReturnsNull_ForCustomProblemDetails()
|
||||
{
|
||||
// Arrange
|
||||
var xmlOptions = new MvcXmlOptions();
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory(xmlOptions);
|
||||
var providerFactory = new ProblemDetailsWrapperProviderFactory();
|
||||
var instance = new CustomProblemDetails();
|
||||
var context = new WrapperProviderContext(instance.GetType(), isSerialization: true);
|
||||
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
return new DefaultObjectValidator(
|
||||
metadataProvider,
|
||||
GetModelValidatorProviders(options),
|
||||
options?.Value ?? new MvcOptions { AllowShortCircuitingValidationWhenNoValidatorsArePresent = true });
|
||||
options?.Value ?? new MvcOptions());
|
||||
}
|
||||
|
||||
private static IList<IModelValidatorProvider> GetModelValidatorProviders(IOptions<MvcOptions> options)
|
||||
|
|
@ -195,8 +195,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
|||
serviceCollection
|
||||
.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>()
|
||||
.AddSingleton<ILoggerFactory>(NullLoggerFactory.Instance)
|
||||
.AddTransient<ILogger<DefaultAuthorizationService>, Logger<DefaultAuthorizationService>>()
|
||||
.Configure<MvcOptions>(options => options.AllowShortCircuitingValidationWhenNoValidatorsArePresent = true);
|
||||
.AddTransient<ILogger<DefaultAuthorizationService>, Logger<DefaultAuthorizationService>>();
|
||||
|
||||
if (updateOptions != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
{
|
||||
var defaultProvider = new DefaultPageApplicationModelProvider(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
Options.Create(new RazorPagesOptions { AllowDefaultHandlingForOptionsRequests = true }));
|
||||
Options.Create(new RazorPagesOptions()));
|
||||
|
||||
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
|
|
|||
|
|
@ -137,7 +137,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
|
||||
var options = new RazorPagesOptions
|
||||
{
|
||||
AllowAreas = true,
|
||||
// Setting this value should not affect area page lookup.
|
||||
RootDirectory = "/Files",
|
||||
};
|
||||
|
|
@ -213,44 +212,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_DoesNotAddsModelsForAreaPages_IfFeatureIsDisabled()
|
||||
{
|
||||
// Arrange
|
||||
var descriptors = new[]
|
||||
{
|
||||
CreateVersion_2_0_Descriptor("/Pages/About.cshtml"),
|
||||
CreateVersion_2_0_Descriptor("/Areas/Accounts/Pages/Home.cshtml"),
|
||||
};
|
||||
|
||||
var options = new RazorPagesOptions { AllowAreas = false };
|
||||
|
||||
var provider = CreateProvider(options: options, descriptors: descriptors);
|
||||
var context = new PageRouteModelProviderContext();
|
||||
|
||||
// Act
|
||||
provider.OnProvidersExecuting(context);
|
||||
|
||||
// Assert
|
||||
Assert.Collection(
|
||||
context.RouteModels,
|
||||
result =>
|
||||
{
|
||||
Assert.Equal("/Pages/About.cshtml", result.RelativePath);
|
||||
Assert.Equal("/About", result.ViewEnginePath);
|
||||
Assert.Collection(
|
||||
result.Selectors,
|
||||
selector => Assert.Equal("About", selector.AttributeRouteModel.Template));
|
||||
Assert.Collection(
|
||||
result.RouteValues.OrderBy(k => k.Key),
|
||||
kvp =>
|
||||
{
|
||||
Assert.Equal("page", kvp.Key);
|
||||
Assert.Equal("/About", kvp.Value);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_DoesNotAddAreaAndNonAreaRoutesForAPage()
|
||||
{
|
||||
|
|
@ -265,7 +226,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
|
||||
var options = new RazorPagesOptions
|
||||
{
|
||||
AllowAreas = true,
|
||||
RootDirectory = "/",
|
||||
};
|
||||
|
||||
|
|
@ -637,4 +597,4 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1036,24 +1036,6 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
public void OnGetUser() { }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PopulateFilters_With21CompatBehavior_DoesNotAddDisallowOptionsRequestsPageFilter()
|
||||
{
|
||||
// Arrange
|
||||
var provider = new DefaultPageApplicationModelProvider(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
Options.Create(new RazorPagesOptions()));
|
||||
|
||||
var typeInfo = typeof(object).GetTypeInfo();
|
||||
var pageModel = new PageApplicationModel(new PageActionDescriptor(), typeInfo, typeInfo.GetCustomAttributes(inherit: true));
|
||||
|
||||
// Act
|
||||
provider.PopulateFilters(pageModel);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(pageModel.Filters);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PopulateFilters_AddsDisallowOptionsRequestsPageFilter()
|
||||
{
|
||||
|
|
@ -1189,7 +1171,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
{
|
||||
return new DefaultPageApplicationModelProvider(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
Options.Create(new RazorPagesOptions { AllowDefaultHandlingForOptionsRequests = true }));
|
||||
Options.Create(new RazorPagesOptions()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ namespace Microsoft.AspNetCore.Mvc.Filters
|
|||
{
|
||||
var defaultProvider = new DefaultPageApplicationModelProvider(
|
||||
TestModelMetadataProvider.CreateDefaultProvider(),
|
||||
Options.Create(new RazorPagesOptions { AllowDefaultHandlingForOptionsRequests = true }));
|
||||
Options.Create(new RazorPagesOptions()));
|
||||
|
||||
var context = new PageApplicationModelProviderContext(new PageActionDescriptor(), typeInfo);
|
||||
defaultProvider.OnProvidersExecuting(context);
|
||||
|
|
|
|||
|
|
@ -80,17 +80,17 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
|
|||
filter.Properties,
|
||||
property =>
|
||||
{
|
||||
Assert.Equal("TempDataProperty-Test2", property.Key);
|
||||
Assert.Equal("Test2", property.Key);
|
||||
Assert.Equal(type.GetProperty(nameof(TestPageModel_OneTempDataProperty.Test2)), property.PropertyInfo);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_SetsKeyPrefixToEmptyString_IfCompatSwitchIsSet()
|
||||
public void OnProvidersExecuting_SetsKeyPrefixToEmptyString()
|
||||
{
|
||||
// Arrange
|
||||
var type = typeof(TestPageModel_OneTempDataProperty);
|
||||
var options = Options.Create(new MvcViewOptions { SuppressTempDataAttributePrefix = true });
|
||||
var options = Options.Create(new MvcViewOptions());
|
||||
var provider = new TempDataFilterPageApplicationModelProvider(options);
|
||||
var context = CreateProviderContext(type);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,55 +6,12 @@ using System.Collections.Generic;
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Routing;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
||||
{
|
||||
public class DefaultPageHandlerMethodSelectorTest
|
||||
{
|
||||
[Fact]
|
||||
public void LegacyBehavior_Select_ReturnsNull_WhenNoHandlerMatchesHttpMethod()
|
||||
{
|
||||
// Arrange
|
||||
var descriptor1 = new HandlerMethodDescriptor
|
||||
{
|
||||
HttpMethod = "GET"
|
||||
};
|
||||
|
||||
var descriptor2 = new HandlerMethodDescriptor
|
||||
{
|
||||
HttpMethod = "POST"
|
||||
};
|
||||
|
||||
var pageContext = new PageContext
|
||||
{
|
||||
ActionDescriptor = new CompiledPageActionDescriptor
|
||||
{
|
||||
HandlerMethods = new List<HandlerMethodDescriptor>()
|
||||
{
|
||||
descriptor1,
|
||||
descriptor2,
|
||||
},
|
||||
},
|
||||
RouteData = new RouteData(),
|
||||
HttpContext = new DefaultHttpContext
|
||||
{
|
||||
Request =
|
||||
{
|
||||
Method = "PUT"
|
||||
},
|
||||
},
|
||||
};
|
||||
var selector = CreateSelector(legacyBehavior: true);
|
||||
|
||||
// Act
|
||||
var actual = selector.Select(pageContext);
|
||||
|
||||
// Assert
|
||||
Assert.Null(actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NewBehavior_Select_ReturnsFuzzyMatchForHead_WhenNoHeadHandlerDefined()
|
||||
{
|
||||
|
|
@ -780,13 +737,9 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure
|
|||
{
|
||||
}
|
||||
|
||||
private static DefaultPageHandlerMethodSelector CreateSelector(bool legacyBehavior = false)
|
||||
private static DefaultPageHandlerMethodSelector CreateSelector()
|
||||
{
|
||||
var options = Options.Create(new RazorPagesOptions()
|
||||
{
|
||||
AllowMappingHeadRequestsToGetHandler = !legacyBehavior
|
||||
});
|
||||
return new DefaultPageHandlerMethodSelector(options);
|
||||
return new DefaultPageHandlerMethodSelector();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,92 +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.
|
||||
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters;
|
||||
using Microsoft.AspNetCore.Mvc.Formatters.Xml;
|
||||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNetCore.Mvc.IntegrationTest
|
||||
{
|
||||
// Integration tests for compatibility switches. These tests verify which compatibility
|
||||
// values apply to each supported version.
|
||||
//
|
||||
// If you add a new compatibility switch, make sure to update ALL of these tests. Each test
|
||||
// here should include verification for all of the switches.
|
||||
public class CompatibilitySwitchIntegrationTest
|
||||
{
|
||||
[Fact]
|
||||
public void CompatibilitySwitches_Version_3_0()
|
||||
{
|
||||
// Arrange
|
||||
var serviceCollection = new ServiceCollection();
|
||||
AddHostingServices(serviceCollection);
|
||||
serviceCollection
|
||||
.AddMvc()
|
||||
.AddXmlDataContractSerializerFormatters()
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
|
||||
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
|
||||
// Act
|
||||
var mvcOptions = services.GetRequiredService<IOptions<MvcOptions>>().Value;
|
||||
var jsonOptions = services.GetRequiredService<IOptions<MvcJsonOptions>>().Value;
|
||||
var razorPagesOptions = services.GetRequiredService<IOptions<RazorPagesOptions>>().Value;
|
||||
var apiBehaviorOptions = services.GetRequiredService<IOptions<ApiBehaviorOptions>>().Value;
|
||||
var razorViewEngineOptions = services.GetRequiredService<IOptions<RazorViewEngineOptions>>().Value;
|
||||
var xmlOptions = services.GetRequiredService<IOptions<MvcXmlOptions>>().Value;
|
||||
|
||||
// Assert
|
||||
Assert.True(mvcOptions.SuppressBindingUndefinedValueToEnumType);
|
||||
Assert.Equal(InputFormatterExceptionPolicy.MalformedInputExceptions, mvcOptions.InputFormatterExceptionPolicy);
|
||||
Assert.True(razorPagesOptions.AllowAreas);
|
||||
Assert.True(razorPagesOptions.AllowDefaultHandlingForOptionsRequests);
|
||||
Assert.True(xmlOptions.AllowRfc7807CompliantProblemDetailsFormat);
|
||||
Assert.True(mvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CompatibilitySwitches_Version_Latest()
|
||||
{
|
||||
// Arrange
|
||||
var serviceCollection = new ServiceCollection();
|
||||
AddHostingServices(serviceCollection);
|
||||
serviceCollection
|
||||
.AddMvc()
|
||||
.AddXmlDataContractSerializerFormatters()
|
||||
.SetCompatibilityVersion(CompatibilityVersion.Latest);
|
||||
|
||||
var services = serviceCollection.BuildServiceProvider();
|
||||
|
||||
// Act
|
||||
var mvcOptions = services.GetRequiredService<IOptions<MvcOptions>>().Value;
|
||||
var jsonOptions = services.GetRequiredService<IOptions<MvcJsonOptions>>().Value;
|
||||
var razorPagesOptions = services.GetRequiredService<IOptions<RazorPagesOptions>>().Value;
|
||||
var apiBehaviorOptions = services.GetRequiredService<IOptions<ApiBehaviorOptions>>().Value;
|
||||
var razorViewEngineOptions = services.GetRequiredService<IOptions<RazorViewEngineOptions>>().Value;
|
||||
var xmlOptions = services.GetRequiredService<IOptions<MvcXmlOptions>>().Value;
|
||||
|
||||
// Assert
|
||||
Assert.True(mvcOptions.SuppressBindingUndefinedValueToEnumType);
|
||||
Assert.Equal(InputFormatterExceptionPolicy.MalformedInputExceptions, mvcOptions.InputFormatterExceptionPolicy);
|
||||
Assert.True(razorPagesOptions.AllowAreas);
|
||||
Assert.True(razorPagesOptions.AllowDefaultHandlingForOptionsRequests);
|
||||
Assert.True(xmlOptions.AllowRfc7807CompliantProblemDetailsFormat);
|
||||
Assert.True(mvcOptions.AllowShortCircuitingValidationWhenNoValidatorsArePresent);
|
||||
}
|
||||
|
||||
// This just does the minimum needed to be able to resolve these options.
|
||||
private static void AddHostingServices(IServiceCollection serviceCollection)
|
||||
{
|
||||
serviceCollection.AddSingleton(Mock.Of<IHostingEnvironment>());
|
||||
serviceCollection.AddLogging();
|
||||
serviceCollection.AddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,6 @@ using Microsoft.AspNetCore.Mvc.Infrastructure;
|
|||
using Microsoft.AspNetCore.Mvc.Razor;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.Compilation;
|
||||
using Microsoft.AspNetCore.Mvc.Razor.TagHelpers;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure;
|
||||
using Microsoft.AspNetCore.Mvc.TagHelpers;
|
||||
using Microsoft.AspNetCore.Mvc.ViewComponents;
|
||||
|
|
@ -382,13 +381,6 @@ namespace Microsoft.AspNetCore.Mvc
|
|||
typeof(MvcCoreMvcOptionsSetup),
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(IPostConfigureOptions<RazorPagesOptions>),
|
||||
new[]
|
||||
{
|
||||
typeof(RazorPagesOptionsConfigureCompatibilityOptions),
|
||||
}
|
||||
},
|
||||
{
|
||||
typeof(IActionConstraintProvider),
|
||||
new Type[]
|
||||
|
|
|
|||
|
|
@ -212,7 +212,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
|
||||
// Assert
|
||||
var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength");
|
||||
Assert.Equal(expectedValue, Int32.Parse(attribute.Value));
|
||||
Assert.Equal(expectedValue, int.Parse(attribute.Value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -236,7 +236,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
|
||||
// Assert
|
||||
var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength");
|
||||
Assert.Equal(expectedValue, Int32.Parse(attribute.Value));
|
||||
Assert.Equal(expectedValue, int.Parse(attribute.Value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -260,7 +260,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
|
||||
// Assert
|
||||
var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength");
|
||||
Assert.Equal(expectedValue, Int32.Parse(attribute.Value));
|
||||
Assert.Equal(expectedValue, int.Parse(attribute.Value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -282,7 +282,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
|
||||
// Assert
|
||||
var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength");
|
||||
Assert.Equal(Math.Min(ModelWithMaxLengthMetadata.MaxLengthAttributeValue, ModelWithMaxLengthMetadata.StringLengthAttributeValue), Int32.Parse(attribute.Value));
|
||||
Assert.Equal(Math.Min(ModelWithMaxLengthMetadata.MaxLengthAttributeValue, ModelWithMaxLengthMetadata.StringLengthAttributeValue), int.Parse(attribute.Value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -328,7 +328,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
|
||||
// Assert
|
||||
var attribute = Assert.Single(tagBuilder.Attributes, a => a.Key == "maxlength");
|
||||
Assert.Equal(expectedValue, Int32.Parse(attribute.Value));
|
||||
Assert.Equal(expectedValue, int.Parse(attribute.Value));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -923,7 +923,7 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures
|
|||
private static IHtmlGenerator GetGenerator(IModelMetadataProvider metadataProvider)
|
||||
{
|
||||
var mvcViewOptionsAccessor = new Mock<IOptions<MvcViewOptions>>();
|
||||
mvcViewOptionsAccessor.SetupGet(accessor => accessor.Value).Returns(new MvcViewOptions() { AllowRenderingMaxLengthAttribute = true });
|
||||
mvcViewOptionsAccessor.SetupGet(accessor => accessor.Value).Returns(new MvcViewOptions());
|
||||
|
||||
var htmlEncoder = Mock.Of<HtmlEncoder>();
|
||||
var antiforgery = new Mock<IAntiforgery>();
|
||||
|
|
|
|||
|
|
@ -85,15 +85,15 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Filters
|
|||
Assert.NotNull(filter);
|
||||
var property = Assert.Single(filter.TempDataProperties);
|
||||
Assert.Same(expected, property.PropertyInfo);
|
||||
Assert.Equal("TempDataProperty-Test2", property.Key);
|
||||
Assert.Equal("Test2", property.Key);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_SetsKeyPrefixToEmptyString_IfCompatSwitchIsSet()
|
||||
public void OnProvidersExecuting_SetsKeyPrefixToEmptyString()
|
||||
{
|
||||
// Arrange
|
||||
var expected = typeof(TestController_OneTempDataProperty).GetProperty(nameof(TestController_OneTempDataProperty.Test2));
|
||||
var options = Options.Create(new MvcViewOptions { SuppressTempDataAttributePrefix = true });
|
||||
var options = Options.Create(new MvcViewOptions());
|
||||
var type = typeof(TestController_OneTempDataProperty);
|
||||
var provider = new TempDataApplicationModelProvider(options);
|
||||
var context = GetContext(type);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ namespace RazorPagesWebSite
|
|||
.AddCookieTempDataProvider()
|
||||
.AddRazorPagesOptions(options =>
|
||||
{
|
||||
options.AllowAreas = true;
|
||||
options.Conventions.AuthorizePage("/Conventions/Auth");
|
||||
options.Conventions.AuthorizeFolder("/Conventions/AuthFolder");
|
||||
options.Conventions.AuthorizeAreaFolder("Accounts", "/RequiresAuth");
|
||||
|
|
|
|||
Loading…
Reference in New Issue