Mvc 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. commit 5e20c313d9416712d870bcecc4af023f9feae9cc
  2. Author: kishanAnem <[email protected]>
  3. Date: Tue Jun 26 20:43:46 2018 +0200
  4. Array or List in query string does not get parsed #7712 (#7967)
  5. - exclude collections when detecting complex types in `ApiBehaviorApplicationModelProvider`
  6. - add test cases
  7. diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ApiBehaviorApplicationModelProvider.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ApiBehaviorApplicationModelProvider.cs
  8. index 9d86de29e5e..1661eefc038 100644
  9. --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ApiBehaviorApplicationModelProvider.cs
  10. +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ApiBehaviorApplicationModelProvider.cs
  11. @@ -193,7 +193,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
  12. var metadata = _modelMetadataProvider.GetMetadataForProperty(
  13. controllerModel.ControllerType,
  14. property.PropertyInfo.Name);
  15. - if (metadata.IsComplexType)
  16. + if (metadata.IsComplexType && !metadata.IsCollectionType)
  17. {
  18. property.BindingInfo.BinderModelName = string.Empty;
  19. }
  20. @@ -254,9 +254,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
  21. private bool IsComplexTypeParameter(ParameterModel parameter)
  22. {
  23. // No need for information from attributes on the parameter. Just use its type.
  24. - return _modelMetadataProvider
  25. - .GetMetadataForType(parameter.ParameterInfo.ParameterType)
  26. - .IsComplexType;
  27. + var metadata = _modelMetadataProvider
  28. + .GetMetadataForType(parameter.ParameterInfo.ParameterType);
  29. + return metadata.IsComplexType && !metadata.IsCollectionType;
  30. }
  31. }
  32. }
  33. diff --git a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ApiBehaviorApplicationModelProviderTest.cs b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ApiBehaviorApplicationModelProviderTest.cs
  34. index a90dbc2943f..5b4b210d1a0 100644
  35. --- a/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ApiBehaviorApplicationModelProviderTest.cs
  36. +++ b/test/Microsoft.AspNetCore.Mvc.Core.Test/Internal/ApiBehaviorApplicationModelProviderTest.cs
  37. @@ -2,6 +2,7 @@
  38. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
  39. using System;
  40. +using System.Collections.Generic;
  41. using System.ComponentModel;
  42. using System.Linq;
  43. using System.Reflection;
  44. @@ -619,6 +620,75 @@ Environment.NewLine + "int b";
  45. Assert.Equal("gps", bindingInfo.BinderModelName);
  46. }
  47. + [Fact]
  48. + public void PreservesBindingSourceInference_ForFromQueryParameterOnCollectionType()
  49. + {
  50. + // Arrange
  51. + var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
  52. + var actionName = nameof(ParameterBindingController.FromQueryOnCollectionType);
  53. + var context = GetContext(typeof(ParameterBindingController), modelMetadataProvider);
  54. + var provider = GetProvider();
  55. +
  56. + // Act
  57. + provider.OnProvidersExecuting(context);
  58. +
  59. + // Assert
  60. + var controller = Assert.Single(context.Result.Controllers);
  61. + var action = Assert.Single(controller.Actions, a => a.ActionName == actionName);
  62. + var parameter = Assert.Single(action.Parameters);
  63. +
  64. + var bindingInfo = parameter.BindingInfo;
  65. + Assert.NotNull(bindingInfo);
  66. + Assert.Same(BindingSource.Query, bindingInfo.BindingSource);
  67. + Assert.Null(bindingInfo.BinderModelName);
  68. + }
  69. +
  70. + [Fact]
  71. + public void PreservesBindingSourceInference_ForFromQueryOnArrayType()
  72. + {
  73. + // Arrange
  74. + var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
  75. + var actionName = nameof(ParameterBindingController.FromQueryOnArrayType);
  76. + var context = GetContext(typeof(ParameterBindingController), modelMetadataProvider);
  77. + var provider = GetProvider();
  78. +
  79. + // Act
  80. + provider.OnProvidersExecuting(context);
  81. +
  82. + // Assert
  83. + var controller = Assert.Single(context.Result.Controllers);
  84. + var action = Assert.Single(controller.Actions, a => a.ActionName == actionName);
  85. + var parameter = Assert.Single(action.Parameters);
  86. +
  87. + var bindingInfo = parameter.BindingInfo;
  88. + Assert.NotNull(bindingInfo);
  89. + Assert.Same(BindingSource.Query, bindingInfo.BindingSource);
  90. + Assert.Null(bindingInfo.BinderModelName);
  91. + }
  92. +
  93. + [Fact]
  94. + public void PreservesBindingSourceInference_FromQueryOnArrayTypeWithCustomName()
  95. + {
  96. + // Arrange
  97. + var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
  98. + var actionName = nameof(ParameterBindingController.FromQueryOnArrayTypeWithCustomName);
  99. + var context = GetContext(typeof(ParameterBindingController), modelMetadataProvider);
  100. + var provider = GetProvider();
  101. +
  102. + // Act
  103. + provider.OnProvidersExecuting(context);
  104. +
  105. + // Assert
  106. + var controller = Assert.Single(context.Result.Controllers);
  107. + var action = Assert.Single(controller.Actions, a => a.ActionName == actionName);
  108. + var parameter = Assert.Single(action.Parameters);
  109. +
  110. + var bindingInfo = parameter.BindingInfo;
  111. + Assert.NotNull(bindingInfo);
  112. + Assert.Same(BindingSource.Query, bindingInfo.BindingSource);
  113. + Assert.Equal("ids", bindingInfo.BinderModelName);
  114. + }
  115. +
  116. [Fact]
  117. public void PreservesBindingSourceInference_ForFromRouteParameter_WithDefaultName()
  118. {
  119. @@ -794,6 +864,22 @@ Environment.NewLine + "int b";
  120. Assert.Equal(string.Empty, property.BindingInfo.BinderModelName);
  121. }
  122. + [Fact]
  123. + public void InferBoundPropertyModelPrefixes_SetsModelPrefix_ForCollectionTypeFromValueProvider()
  124. + {
  125. + // Arrange
  126. + var controller = GetControllerModel(typeof(ControllerWithBoundCollectionProperty));
  127. +
  128. + var provider = GetProvider();
  129. +
  130. + // Act
  131. + provider.InferBoundPropertyModelPrefixes(controller);
  132. +
  133. + // Assert
  134. + var property = Assert.Single(controller.ControllerProperties);
  135. + Assert.Null(property.BindingInfo.BinderModelName);
  136. + }
  137. +
  138. [Fact]
  139. public void InferParameterModelPrefixes_SetsModelPrefix_ForComplexTypeFromValueProvider()
  140. {
  141. @@ -1008,7 +1094,7 @@ Environment.NewLine + "int b";
  142. [HttpGet("parameter-with-model-binder-attribute")]
  143. public IActionResult ModelBinderAttribute([ModelBinder(Name = "top")] int value) => null;
  144. -
  145. +
  146. [HttpGet("parameter-with-fromquery")]
  147. public IActionResult FromQuery([FromQuery] int value) => null;
  148. @@ -1021,6 +1107,15 @@ Environment.NewLine + "int b";
  149. [HttpGet("parameter-with-fromquery-on-complextype-and-customname")]
  150. public IActionResult FromQueryOnComplexTypeWithCustomName([FromQuery(Name = "gps")] GpsCoordinates gpsCoordinates) => null;
  151. + [HttpGet("parameter-with-fromquery-on-collection-type")]
  152. + public IActionResult FromQueryOnCollectionType([FromQuery] ICollection<int> value) => null;
  153. +
  154. + [HttpGet("parameter-with-fromquery-on-array-type")]
  155. + public IActionResult FromQueryOnArrayType([FromQuery] int[] value) => null;
  156. +
  157. + [HttpGet("parameter-with-fromquery-on-array-type-customname")]
  158. + public IActionResult FromQueryOnArrayTypeWithCustomName([FromQuery(Name = "ids")] int[] value) => null;
  159. +
  160. [HttpGet("parameter-with-fromroute")]
  161. public IActionResult FromRoute([FromRoute] int value) => null;
  162. @@ -1118,6 +1213,15 @@ Environment.NewLine + "int b";
  163. public IActionResult SomeAction([FromQuery] TestModel test) => null;
  164. }
  165. + [ApiController]
  166. + private class ControllerWithBoundCollectionProperty
  167. + {
  168. + [FromQuery]
  169. + public List<int> TestProperty { get; set; }
  170. +
  171. + public IActionResult SomeAction([FromQuery] List<int> test) => null;
  172. + }
  173. +
  174. private class Car { }
  175. [ApiController]