- exclude collections when detecting complex types in `ApiBehaviorApplicationModelProvider` - add test cases
This commit is contained in:
parent
f15457c026
commit
e1af5b8b6d
|
|
@ -203,7 +203,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
var metadata = _modelMetadataProvider.GetMetadataForProperty(
|
var metadata = _modelMetadataProvider.GetMetadataForProperty(
|
||||||
controllerModel.ControllerType,
|
controllerModel.ControllerType,
|
||||||
property.PropertyInfo.Name);
|
property.PropertyInfo.Name);
|
||||||
if (metadata.IsComplexType)
|
if (metadata.IsComplexType && !metadata.IsCollectionType)
|
||||||
{
|
{
|
||||||
property.BindingInfo.BinderModelName = string.Empty;
|
property.BindingInfo.BinderModelName = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
@ -278,9 +278,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
private bool IsComplexTypeParameter(ParameterModel parameter)
|
private bool IsComplexTypeParameter(ParameterModel parameter)
|
||||||
{
|
{
|
||||||
// No need for information from attributes on the parameter. Just use its type.
|
// No need for information from attributes on the parameter. Just use its type.
|
||||||
return _modelMetadataProvider
|
var metadata = _modelMetadataProvider
|
||||||
.GetMetadataForType(parameter.ParameterInfo.ParameterType)
|
.GetMetadataForType(parameter.ParameterInfo.ParameterType);
|
||||||
.IsComplexType;
|
return metadata.IsComplexType && !metadata.IsCollectionType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
@ -622,6 +623,75 @@ Environment.NewLine + "int b";
|
||||||
Assert.Equal("gps", bindingInfo.BinderModelName);
|
Assert.Equal("gps", bindingInfo.BinderModelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForFromQueryParameterOnCollectionType()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromQueryOnCollectionType);
|
||||||
|
var context = GetContext(typeof(ParameterBindingController), modelMetadataProvider);
|
||||||
|
var provider = GetProvider();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
provider.OnProvidersExecuting(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var controller = Assert.Single(context.Result.Controllers);
|
||||||
|
var action = Assert.Single(controller.Actions, a => a.ActionName == actionName);
|
||||||
|
var parameter = Assert.Single(action.Parameters);
|
||||||
|
|
||||||
|
var bindingInfo = parameter.BindingInfo;
|
||||||
|
Assert.NotNull(bindingInfo);
|
||||||
|
Assert.Same(BindingSource.Query, bindingInfo.BindingSource);
|
||||||
|
Assert.Null(bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForFromQueryOnArrayType()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromQueryOnArrayType);
|
||||||
|
var context = GetContext(typeof(ParameterBindingController), modelMetadataProvider);
|
||||||
|
var provider = GetProvider();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
provider.OnProvidersExecuting(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var controller = Assert.Single(context.Result.Controllers);
|
||||||
|
var action = Assert.Single(controller.Actions, a => a.ActionName == actionName);
|
||||||
|
var parameter = Assert.Single(action.Parameters);
|
||||||
|
|
||||||
|
var bindingInfo = parameter.BindingInfo;
|
||||||
|
Assert.NotNull(bindingInfo);
|
||||||
|
Assert.Same(BindingSource.Query, bindingInfo.BindingSource);
|
||||||
|
Assert.Null(bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_FromQueryOnArrayTypeWithCustomName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromQueryOnArrayTypeWithCustomName);
|
||||||
|
var context = GetContext(typeof(ParameterBindingController), modelMetadataProvider);
|
||||||
|
var provider = GetProvider();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
provider.OnProvidersExecuting(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var controller = Assert.Single(context.Result.Controllers);
|
||||||
|
var action = Assert.Single(controller.Actions, a => a.ActionName == actionName);
|
||||||
|
var parameter = Assert.Single(action.Parameters);
|
||||||
|
|
||||||
|
var bindingInfo = parameter.BindingInfo;
|
||||||
|
Assert.NotNull(bindingInfo);
|
||||||
|
Assert.Same(BindingSource.Query, bindingInfo.BindingSource);
|
||||||
|
Assert.Equal("ids", bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void PreservesBindingSourceInference_ForFromRouteParameter_WithDefaultName()
|
public void PreservesBindingSourceInference_ForFromRouteParameter_WithDefaultName()
|
||||||
{
|
{
|
||||||
|
|
@ -797,6 +867,22 @@ Environment.NewLine + "int b";
|
||||||
Assert.Equal(string.Empty, property.BindingInfo.BinderModelName);
|
Assert.Equal(string.Empty, property.BindingInfo.BinderModelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void InferBoundPropertyModelPrefixes_SetsModelPrefix_ForCollectionTypeFromValueProvider()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var controller = GetControllerModel(typeof(ControllerWithBoundCollectionProperty));
|
||||||
|
|
||||||
|
var provider = GetProvider();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
provider.InferBoundPropertyModelPrefixes(controller);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var property = Assert.Single(controller.ControllerProperties);
|
||||||
|
Assert.Null(property.BindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void InferParameterModelPrefixes_SetsModelPrefix_ForComplexTypeFromValueProvider()
|
public void InferParameterModelPrefixes_SetsModelPrefix_ForComplexTypeFromValueProvider()
|
||||||
{
|
{
|
||||||
|
|
@ -1124,7 +1210,7 @@ Environment.NewLine + "int b";
|
||||||
|
|
||||||
[HttpGet("parameter-with-model-binder-attribute")]
|
[HttpGet("parameter-with-model-binder-attribute")]
|
||||||
public IActionResult ModelBinderAttribute([ModelBinder(Name = "top")] int value) => null;
|
public IActionResult ModelBinderAttribute([ModelBinder(Name = "top")] int value) => null;
|
||||||
|
|
||||||
[HttpGet("parameter-with-fromquery")]
|
[HttpGet("parameter-with-fromquery")]
|
||||||
public IActionResult FromQuery([FromQuery] int value) => null;
|
public IActionResult FromQuery([FromQuery] int value) => null;
|
||||||
|
|
||||||
|
|
@ -1137,6 +1223,15 @@ Environment.NewLine + "int b";
|
||||||
[HttpGet("parameter-with-fromquery-on-complextype-and-customname")]
|
[HttpGet("parameter-with-fromquery-on-complextype-and-customname")]
|
||||||
public IActionResult FromQueryOnComplexTypeWithCustomName([FromQuery(Name = "gps")] GpsCoordinates gpsCoordinates) => null;
|
public IActionResult FromQueryOnComplexTypeWithCustomName([FromQuery(Name = "gps")] GpsCoordinates gpsCoordinates) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromquery-on-collection-type")]
|
||||||
|
public IActionResult FromQueryOnCollectionType([FromQuery] ICollection<int> value) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromquery-on-array-type")]
|
||||||
|
public IActionResult FromQueryOnArrayType([FromQuery] int[] value) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromquery-on-array-type-customname")]
|
||||||
|
public IActionResult FromQueryOnArrayTypeWithCustomName([FromQuery(Name = "ids")] int[] value) => null;
|
||||||
|
|
||||||
[HttpGet("parameter-with-fromroute")]
|
[HttpGet("parameter-with-fromroute")]
|
||||||
public IActionResult FromRoute([FromRoute] int value) => null;
|
public IActionResult FromRoute([FromRoute] int value) => null;
|
||||||
|
|
||||||
|
|
@ -1234,6 +1329,15 @@ Environment.NewLine + "int b";
|
||||||
public IActionResult SomeAction([FromQuery] TestModel test) => null;
|
public IActionResult SomeAction([FromQuery] TestModel test) => null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
private class ControllerWithBoundCollectionProperty
|
||||||
|
{
|
||||||
|
[FromQuery]
|
||||||
|
public List<int> TestProperty { get; set; }
|
||||||
|
|
||||||
|
public IActionResult SomeAction([FromQuery] List<int> test) => null;
|
||||||
|
}
|
||||||
|
|
||||||
private class Car { }
|
private class Car { }
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue