From e7fe635dab5aca53eb950a1f668e7d5cc26d1f28 Mon Sep 17 00:00:00 2001 From: Kiran Challa Date: Wed, 5 Oct 2016 13:39:30 -0700 Subject: [PATCH] Modified FormCollectionModelBinderProvider to throw when binding for FormCollection model type. [Fixes #4895] No parameterless Constructor defined --- .../FormCollectionModelBinderProvider.cs | 15 ++++- .../Properties/Resources.Designer.cs | 16 ++++++ .../Resources.resx | 57 ++++++++++--------- .../FormCollectionModelBinderProviderTest.cs | 21 +++++++ 4 files changed, 81 insertions(+), 28 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinderProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinderProvider.cs index f87bcd352d..2e884815f9 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinderProvider.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/ModelBinding/Binders/FormCollectionModelBinderProvider.cs @@ -2,7 +2,9 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Reflection; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Core; namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { @@ -19,7 +21,18 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders throw new ArgumentNullException(nameof(context)); } - if (context.Metadata.ModelType == typeof(IFormCollection)) + var modelType = context.Metadata.ModelType; + + if (typeof(FormCollection).GetTypeInfo().IsAssignableFrom(modelType)) + { + throw new InvalidOperationException( + Resources.FormatFormCollectionModelBinder_CannotBindToFormCollection( + typeof(FormCollectionModelBinder).FullName, + modelType.FullName, + typeof(IFormCollection).FullName)); + } + + if (modelType == typeof(IFormCollection)) { return new FormCollectionModelBinder(); } diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs b/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs index 0669d0049d..6964666fbb 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Properties/Resources.Designer.cs @@ -1322,6 +1322,22 @@ namespace Microsoft.AspNetCore.Mvc.Core return string.Format(CultureInfo.CurrentCulture, GetString("AuthorizeFilter_AuthorizationPolicyCannotBeCreated"), p0, p1); } + /// + /// The '{0}' cannot bind to a model of type '{1}'. Change the model type to '{2}' instead. + /// + internal static string FormCollectionModelBinder_CannotBindToFormCollection + { + get { return GetString("FormCollectionModelBinder_CannotBindToFormCollection"); } + } + + /// + /// The '{0}' cannot bind to a model of type '{1}'. Change the model type to '{2}' instead. + /// + internal static string FormatFormCollectionModelBinder_CannotBindToFormCollection(object p0, object p1, object p2) + { + return string.Format(CultureInfo.CurrentCulture, GetString("FormCollectionModelBinder_CannotBindToFormCollection"), p0, p1, p2); + } + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx b/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx index 197ad6f2e2..a054806f71 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx +++ b/src/Microsoft.AspNetCore.Mvc.Core/Resources.resx @@ -1,17 +1,17 @@  - @@ -373,4 +373,7 @@ An {0} cannot be created without a valid instance of {1}. + + The '{0}' cannot bind to a model of type '{1}'. Change the model type to '{2}' instead. + \ No newline at end of file diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormCollectionModelBinderProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormCollectionModelBinderProviderTest.cs index 908721752f..8562af3410 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormCollectionModelBinderProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/ModelBinding/Binders/FormCollectionModelBinderProviderTest.cs @@ -12,6 +12,22 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders { [Theory] [InlineData(typeof(FormCollection))] + [InlineData(typeof(DerviedFormCollection))] + public void Create_ThrowsException_ForFormCollectionModelType(Type modelType) + { + // Arrange + var provider = new FormCollectionModelBinderProvider(); + var context = new TestModelBinderProviderContext(modelType); + + // Act & Assert + var exception = Assert.Throws(() => provider.GetBinder(context)); + + Assert.Equal( + $"The '{typeof(FormCollectionModelBinder).FullName}' cannot bind to a model of type '{modelType.FullName}'. Change the model type to '{typeof(IFormCollection).FullName}' instead.", + exception.Message); + } + + [Theory] [InlineData(typeof(TestClass))] [InlineData(typeof(IList))] [InlineData(typeof(int[]))] @@ -45,5 +61,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding.Binders private class TestClass { } + + private class DerviedFormCollection : FormCollection + { + public DerviedFormCollection() : base(fields: null, files: null) { } + } } }