From 49c653ed0baf829cb91bb51bb575306c9f1ec0fa Mon Sep 17 00:00:00 2001 From: Pranav K Date: Mon, 21 May 2018 18:14:54 -0700 Subject: [PATCH] Infer BindingSource.FormFile for IEnumerable Fixes #7770 --- .../Internal/MvcCoreMvcOptionsSetup.cs | 1 + .../DefaultApplicationModelProviderTest.cs | 53 +++++++++++++++++++ .../MvcOptionsSetupTest.cs | 7 +++ 3 files changed, 61 insertions(+) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs index 21bb72eb27..4cb4f9f3bd 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcCoreMvcOptionsSetup.cs @@ -96,6 +96,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal modelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(IFormFile), BindingSource.FormFile)); modelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(IFormCollection), BindingSource.FormFile)); modelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(IFormFileCollection), BindingSource.FormFile)); + modelMetadataDetailsProviders.Add(new BindingSourceMetadataProvider(typeof(IEnumerable), BindingSource.FormFile)); // Add types to be excluded from Validation modelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Type))); diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/DefaultApplicationModelProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/DefaultApplicationModelProviderTest.cs index 1090cc5868..4af3ea19f5 100644 --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/DefaultApplicationModelProviderTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/DefaultApplicationModelProviderTest.cs @@ -211,6 +211,52 @@ namespace Microsoft.AspNetCore.Mvc.Internal }); } + [Fact] + public void OnProvidersExecuting_InfersFormFileSourceForTypesAssignableFromIEnumerableOfFormFiles() + { + // Arrange + var builder = new TestApplicationModelProvider( + new MvcOptions { AllowValidatingTopLevelNodes = true }, + TestModelMetadataProvider.CreateDefaultProvider()); + var typeInfo = typeof(ModelBinderController).GetTypeInfo(); + + var context = new ApplicationModelProviderContext(new[] { typeInfo }); + + // Act + builder.OnProvidersExecuting(context); + + // Assert + var controllerModel = Assert.Single(context.Result.Controllers); + var action = Assert.Single(controllerModel.Actions, a => a.ActionMethod.Name == nameof(ModelBinderController.FormFilesSequences)); + Assert.Collection( + action.Parameters, + parameter => + { + Assert.Equal("formFileEnumerable", parameter.ParameterName); + Assert.Equal(BindingSource.FormFile, parameter.BindingInfo.BindingSource); + }, + parameter => + { + Assert.Equal("formFileCollection", parameter.ParameterName); + Assert.Equal(BindingSource.FormFile, parameter.BindingInfo.BindingSource); + }, + parameter => + { + Assert.Equal("formFileIList", parameter.ParameterName); + Assert.Equal(BindingSource.FormFile, parameter.BindingInfo.BindingSource); + }, + parameter => + { + Assert.Equal("formFileList", parameter.ParameterName); + Assert.Equal(BindingSource.FormFile, parameter.BindingInfo.BindingSource); + }, + parameter => + { + Assert.Equal("formFileArray", parameter.ParameterName); + Assert.Equal(BindingSource.FormFile, parameter.BindingInfo.BindingSource); + }); + } + [Fact] public void OnProvidersExecuting_AddsBindingSources_ForActionParameters_ReadFromModelMetadata() { @@ -1625,6 +1671,13 @@ namespace Microsoft.AspNetCore.Mvc.Internal public IActionResult PostAction([FromQuery] string fromQuery, IFormFileCollection formFileCollection, string unbound) => null; + public IActionResult FormFilesSequences( + IEnumerable formFileEnumerable, + ICollection formFileCollection, + IList formFileIList, + List formFileList, + IFormFile[] formFileArray) => null; + public IActionResult PostAction1(Guid guid) => null; public IActionResult PostAction2([FromQuery] Guid fromQuery) => null; diff --git a/test/Microsoft.AspNetCore.Mvc.Test/MvcOptionsSetupTest.cs b/test/Microsoft.AspNetCore.Mvc.Test/MvcOptionsSetupTest.cs index eb9f5434a3..e43d50af95 100644 --- a/test/Microsoft.AspNetCore.Mvc.Test/MvcOptionsSetupTest.cs +++ b/test/Microsoft.AspNetCore.Mvc.Test/MvcOptionsSetupTest.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -189,6 +190,12 @@ namespace Microsoft.AspNetCore.Mvc Assert.Equal(BindingSource.FormFile, formFileParameter.BindingSource); }, provider => + { + var formFileParameter = Assert.IsType(provider); + Assert.Equal(typeof(IEnumerable), formFileParameter.Type); + Assert.Equal(BindingSource.FormFile, formFileParameter.BindingSource); + }, + provider => { var excludeFilter = Assert.IsType(provider); Assert.Equal(typeof(Type), excludeFilter.Type);