diff --git a/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs b/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs
index c49c27f454..aee3edea86 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/CompatibilityVersion.cs
@@ -48,6 +48,14 @@ namespace Microsoft.AspNetCore.Mvc
/// Sets the default value of settings on to match the behavior of
/// ASP.NET Core MVC 2.1.
///
+ ///
+ /// ASP.NET Core MVC 2.1 introduces compatibility switches for the following:
+ ///
+ /// -
+ ///
+ ///
+ ///
+ ///
Version_2_1,
///
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/MvcOptionsConfigureCompatibilityOptions.cs b/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/MvcOptionsConfigureCompatibilityOptions.cs
index e722e91935..0121ac86d0 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/MvcOptionsConfigureCompatibilityOptions.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/MvcOptionsConfigureCompatibilityOptions.cs
@@ -25,6 +25,7 @@ namespace Microsoft.AspNetCore.Mvc.Infrastructure
if (Version >= CompatibilityVersion.Version_2_1)
{
+ values[nameof(MvcOptions.SuppressBindingUndefinedValueToEnumType)] = true;
values[nameof(MvcOptions.InputFormatterExceptionModelStatePolicy)] = InputFormatterExceptionModelStatePolicy.MalformedInputExceptions;
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinder.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinder.cs
index 4787e0528e..6348b5f11c 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinder.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinder.cs
@@ -11,9 +11,9 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
///
public class EnumTypeModelBinder : SimpleTypeModelBinder
{
- private readonly bool _allowBindingUndefinedValueToEnumType;
+ private readonly bool _suppressBindingUndefinedValueToEnumType;
- public EnumTypeModelBinder(bool allowBindingUndefinedValueToEnumType, Type modelType)
+ public EnumTypeModelBinder(bool supressBindingUndefinedValueToEnumType, Type modelType)
: base(modelType)
{
if (modelType == null)
@@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
throw new ArgumentNullException(nameof(modelType));
}
- _allowBindingUndefinedValueToEnumType = allowBindingUndefinedValueToEnumType;
+ _suppressBindingUndefinedValueToEnumType = supressBindingUndefinedValueToEnumType;
}
protected override void CheckModel(
@@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
ValueProviderResult valueProviderResult,
object model)
{
- if (model == null || _allowBindingUndefinedValueToEnumType)
+ if (model == null || !_suppressBindingUndefinedValueToEnumType)
{
base.CheckModel(bindingContext, valueProviderResult, model);
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinderProvider.cs
index 5bf700e536..140913a1bb 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinderProvider.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/EnumTypeModelBinderProvider.cs
@@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders
if (context.Metadata.IsEnum)
{
return new EnumTypeModelBinder(
- _options.AllowBindingUndefinedValueToEnumType,
+ _options.SuppressBindingUndefinedValueToEnumType,
context.Metadata.UnderlyingOrModelType);
}
diff --git a/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs b/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs
index b6dab32f73..6ae6d5edcf 100644
--- a/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs
+++ b/src/Microsoft.AspNetCore.Mvc.Core/MvcOptions.cs
@@ -22,8 +22,8 @@ namespace Microsoft.AspNetCore.Mvc
private int _maxModelStateErrors = ModelStateDictionary.DefaultMaxAllowedErrors;
// See CompatibilitySwitch.cs for guide on how to implement these.
- private readonly CompatibilitySwitch _allowBindingUndefinedValueToEnumType;
private readonly CompatibilitySwitch _inputFormatterExceptionModelStatePolicy;
+ private readonly CompatibilitySwitch _suppressBindingUndefinedValueToEnumType;
private readonly CompatibilitySwitch _suppressJsonDeserializationExceptionMessagesInModelState;
private readonly ICompatibilitySwitch[] _switches;
@@ -41,13 +41,13 @@ namespace Microsoft.AspNetCore.Mvc
ModelValidatorProviders = new List();
ValueProviderFactories = new List();
- _allowBindingUndefinedValueToEnumType = new CompatibilitySwitch(nameof(AllowBindingUndefinedValueToEnumType));
_inputFormatterExceptionModelStatePolicy = new CompatibilitySwitch(nameof(InputFormatterExceptionModelStatePolicy), InputFormatterExceptionModelStatePolicy.AllExceptions);
+ _suppressBindingUndefinedValueToEnumType = new CompatibilitySwitch(nameof(SuppressBindingUndefinedValueToEnumType));
_suppressJsonDeserializationExceptionMessagesInModelState = new CompatibilitySwitch(nameof(SuppressJsonDeserializationExceptionMessagesInModelState));
_switches = new ICompatibilitySwitch[]
{
- _allowBindingUndefinedValueToEnumType,
_inputFormatterExceptionModelStatePolicy,
+ _suppressBindingUndefinedValueToEnumType,
_suppressJsonDeserializationExceptionMessagesInModelState,
};
}
@@ -92,6 +92,35 @@ namespace Microsoft.AspNetCore.Mvc
///
public FormatterCollection InputFormatters { get; }
+ ///
+ /// Gets or sets an value indicating whether the model binding system will bind undefined values to
+ /// enum types. The default value of the property is false.
+ ///
+ ///
+ ///
+ /// This property is associated with a compatibility switch and can provide a different behavior depending on
+ /// the configured compatibility version for the application. See for
+ /// guidance and examples of setting the application's compatibility version.
+ ///
+ ///
+ /// Configuring the desired of the value compatibility switch by calling this property's setter will take precedence
+ /// over the value implied by the application's .
+ ///
+ ///
+ /// If the application's compatibility version is set to then
+ /// this setting will have value false if not explicitly configured.
+ ///
+ ///
+ /// If the application's compatibility version is set to or
+ /// higher then this setting will have value true if not explicitly configured.
+ ///
+ ///
+ public bool SuppressBindingUndefinedValueToEnumType
+ {
+ get => _suppressBindingUndefinedValueToEnumType.Value;
+ set => _suppressBindingUndefinedValueToEnumType.Value = value;
+ }
+
///
/// Gets or sets the flag to buffer the request body in input formatters. Default is false.
///
@@ -181,15 +210,6 @@ namespace Microsoft.AspNetCore.Mvc
///
public bool RequireHttpsPermanent { get; set; }
- ///
- /// Gets or sets an indication whether the model binding system will bind undefined values to enumeration types.
- /// by default.
- ///
- public bool AllowBindingUndefinedValueToEnumType
- {
- get => _allowBindingUndefinedValueToEnumType.Value;
- set => _allowBindingUndefinedValueToEnumType.Value = value;
- }
///
/// Gets or sets the option to determine if model binding should convert all exceptions (including ones not related to bad input)
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/EnumTypeModelBinderProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/EnumTypeModelBinderProviderTest.cs
index 70444d731c..017f9a4e48 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/EnumTypeModelBinderProviderTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/EnumTypeModelBinderProviderTest.cs
@@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
public void ReturnsBinder_ForEnumType(Type modelType)
{
// Arrange
- var provider = new EnumTypeModelBinderProvider(new MvcOptions { AllowBindingUndefinedValueToEnumType = true });
+ var provider = new EnumTypeModelBinderProvider(new MvcOptions());
var context = new TestModelBinderProviderContext(modelType);
// Act
@@ -31,7 +31,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
public void ReturnsBinder_ForFlagsEnumType(Type modelType)
{
// Arrange
- var provider = new EnumTypeModelBinderProvider(new MvcOptions { AllowBindingUndefinedValueToEnumType = true });
+ var provider = new EnumTypeModelBinderProvider(new MvcOptions());
var context = new TestModelBinderProviderContext(modelType);
// Act
@@ -48,7 +48,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
public void DoesNotReturnBinder_ForNonEnumTypes(Type modelType)
{
// Arrange
- var provider = new EnumTypeModelBinderProvider(new MvcOptions { AllowBindingUndefinedValueToEnumType = false });
+ var provider = new EnumTypeModelBinderProvider(new MvcOptions());
var context = new TestModelBinderProviderContext(modelType);
// Act
diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/EnumTypeModelBinderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/EnumTypeModelBinderTest.cs
index 2379c0c933..e7c4a2bf2b 100644
--- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/EnumTypeModelBinderTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/EnumTypeModelBinderTest.cs
@@ -5,7 +5,6 @@ using System;
using System.ComponentModel;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
-using Microsoft.Extensions.Options;
using Xunit;
namespace Microsoft.AspNetCore.Mvc.ModelBinding
@@ -18,13 +17,13 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
[InlineData(false, typeof(IntEnum?))]
[InlineData(false, typeof(FlagsEnum?))]
public async Task BindModel_SetsModel_ForEmptyValue_AndNullableEnumTypes(
- bool allowBindingUndefinedValueToEnumType,
+ bool suppressBindingUndefinedValueToEnumType,
Type modelType)
{
// Arrange
var binderInfo = GetBinderAndContext(
modelType,
- allowBindingUndefinedValueToEnumType,
+ suppressBindingUndefinedValueToEnumType,
valueProviderValue: "");
var bindingContext = binderInfo.Item1;
var binder = binderInfo.Item2;
@@ -43,14 +42,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
[InlineData(false, typeof(IntEnum))]
[InlineData(false, typeof(FlagsEnum))]
public async Task BindModel_AddsErrorToModelState_ForEmptyValue_AndNonNullableEnumTypes(
- bool allowBindingUndefinedValueToEnumType,
+ bool suprressBindingUndefinedValueToEnumType,
Type modelType)
{
// Arrange
var message = "The value '' is invalid.";
var binderInfo = GetBinderAndContext(
modelType,
- allowBindingUndefinedValueToEnumType,
+ suprressBindingUndefinedValueToEnumType,
valueProviderValue: "");
var bindingContext = binderInfo.Item1;
var binder = binderInfo.Item2;
@@ -72,14 +71,14 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
[InlineData(false, "Value1")]
[InlineData(false, "1")]
public async Task BindModel_BindsEnumModels_ForValuesInArray(
- bool allowBindingUndefinedValueToEnumType,
+ bool suppressBindingUndefinedValueToEnumType,
string enumValue)
{
// Arrange
var modelType = typeof(IntEnum);
var binderInfo = GetBinderAndContext(
modelType,
- allowBindingUndefinedValueToEnumType,
+ suppressBindingUndefinedValueToEnumType,
valueProviderValue: new object[] { enumValue });
var bindingContext = binderInfo.Item1;
var binder = binderInfo.Item2;
@@ -102,7 +101,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
[InlineData("8, 1", false)]
[InlineData("Value2, Value8", false)]
[InlineData("value8,value4,value2,value1", false)]
- public async Task BindModel_BindsTo_NonNullableFlagsEnumType(string flagsEnumValue, bool allowBindingUndefinedValueToEnumType)
+ public async Task BindModel_BindsTo_NonNullableFlagsEnumType(string flagsEnumValue, bool suppressBindingUndefinedValueToEnumType)
{
// Arrange
var modelType = typeof(FlagsEnum);
@@ -110,7 +109,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
var expected = enumConverter.ConvertFrom(flagsEnumValue).ToString();
var binderInfo = GetBinderAndContext(
modelType,
- allowBindingUndefinedValueToEnumType,
+ suppressBindingUndefinedValueToEnumType,
valueProviderValue: new object[] { flagsEnumValue });
var bindingContext = binderInfo.Item1;
var binder = binderInfo.Item2;
@@ -133,7 +132,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
[InlineData("8, 1", false)]
[InlineData("Value2, Value8", false)]
[InlineData("value8,value4,value2,value1", false)]
- public async Task BindModel_BindsTo_NullableFlagsEnumType(string flagsEnumValue, bool allowBindingUndefinedValueToEnumType)
+ public async Task BindModel_BindsTo_NullableFlagsEnumType(string flagsEnumValue, bool suppressBindingUndefinedValueToEnumType)
{
// Arrange
var modelType = typeof(FlagsEnum?);
@@ -141,7 +140,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
var expected = enumConverter.ConvertFrom(flagsEnumValue).ToString();
var binderInfo = GetBinderAndContext(
modelType,
- allowBindingUndefinedValueToEnumType,
+ suppressBindingUndefinedValueToEnumType,
valueProviderValue: new object[] { flagsEnumValue });
var bindingContext = binderInfo.Item1;
var binder = binderInfo.Item2;
@@ -168,7 +167,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
var message = $"The value '{suppliedValue}' is not valid.";
var binderInfo = GetBinderAndContext(
modelType,
- allowBindingUndefinedValueToEnumType: true,
+ suppressBindingUndefinedValueToEnumType: false,
valueProviderValue: new object[] { suppliedValue });
var bindingContext = binderInfo.Item1;
var binder = binderInfo.Item2;
@@ -209,7 +208,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
var message = $"The value '{suppliedValue}' is invalid.";
var binderInfo = GetBinderAndContext(
modelType,
- allowBindingUndefinedValueToEnumType: false,
+ suppressBindingUndefinedValueToEnumType: true,
valueProviderValue: new object[] { suppliedValue });
var bindingContext = binderInfo.Item1;
var binder = binderInfo.Item2;
@@ -251,7 +250,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
var binderProviderContext = new TestModelBinderProviderContext(modelType);
var binderInfo = GetBinderAndContext(
modelType,
- allowBindingUndefinedValueToEnumType: true,
+ suppressBindingUndefinedValueToEnumType: false,
valueProviderValue: new object[] { suppliedValue });
var bindingContext = binderInfo.Item1;
var binder = binderInfo.Item2;
@@ -267,7 +266,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
private static (DefaultModelBindingContext, IModelBinder) GetBinderAndContext(
Type modelType,
- bool allowBindingUndefinedValueToEnumType,
+ bool suppressBindingUndefinedValueToEnumType,
object valueProviderValue)
{
var binderProviderContext = new TestModelBinderProviderContext(modelType);
@@ -284,7 +283,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
};
var binderProvider = new EnumTypeModelBinderProvider(new MvcOptions
{
- AllowBindingUndefinedValueToEnumType = allowBindingUndefinedValueToEnumType
+ SuppressBindingUndefinedValueToEnumType = suppressBindingUndefinedValueToEnumType
});
var binder = binderProvider.GetBinder(binderProviderContext);
return (bindingContext, binder);
diff --git a/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs b/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs
index 102fd5a316..45dabaf9df 100644
--- a/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs
+++ b/test/Microsoft.AspNetCore.Mvc.Test/IntegrationTest/CompatibilitySwitchIntegrationTest.cs
@@ -30,7 +30,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTest
var mvcOptions = services.GetRequiredService>().Value;
// Assert
- Assert.False(mvcOptions.AllowBindingUndefinedValueToEnumType);
+ Assert.False(mvcOptions.SuppressBindingUndefinedValueToEnumType);
Assert.Equal(InputFormatterExceptionModelStatePolicy.AllExceptions, mvcOptions.InputFormatterExceptionModelStatePolicy);
Assert.False(mvcOptions.SuppressJsonDeserializationExceptionMessagesInModelState); // This name needs to be inverted in #7157
}
@@ -49,7 +49,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTest
var mvcOptions = services.GetRequiredService>().Value;
// Assert
- Assert.True(mvcOptions.AllowBindingUndefinedValueToEnumType);
+ Assert.True(mvcOptions.SuppressBindingUndefinedValueToEnumType);
Assert.Equal(InputFormatterExceptionModelStatePolicy.MalformedInputExceptions, mvcOptions.InputFormatterExceptionModelStatePolicy);
Assert.True(mvcOptions.SuppressJsonDeserializationExceptionMessagesInModelState); // This name needs to be inverted in #7157
}
@@ -68,7 +68,7 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTest
var mvcOptions = services.GetRequiredService>().Value;
// Assert
- Assert.True(mvcOptions.AllowBindingUndefinedValueToEnumType);
+ Assert.True(mvcOptions.SuppressBindingUndefinedValueToEnumType);
Assert.Equal(InputFormatterExceptionModelStatePolicy.MalformedInputExceptions, mvcOptions.InputFormatterExceptionModelStatePolicy);
Assert.True(mvcOptions.SuppressJsonDeserializationExceptionMessagesInModelState); // This name needs to be inverted in #7157
}