[Fixes #7609] ApiBehaviorApplicationModelProvider overwrites existing BindingInfo in entirety when inferring binding sources
This commit is contained in:
parent
49c653ed0b
commit
418aac57f4
|
|
@ -155,10 +155,9 @@ namespace Microsoft.AspNetCore.Mvc.Internal
|
||||||
if (bindingSource == null)
|
if (bindingSource == null)
|
||||||
{
|
{
|
||||||
bindingSource = InferBindingSourceForParameter(parameter);
|
bindingSource = InferBindingSourceForParameter(parameter);
|
||||||
parameter.BindingInfo = new BindingInfo
|
|
||||||
{
|
parameter.BindingInfo = parameter.BindingInfo ?? new BindingInfo();
|
||||||
BindingSource = bindingSource,
|
parameter.BindingInfo.BindingSource = bindingSource;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using System.ComponentModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
using Microsoft.AspNetCore.Mvc.ApplicationModels;
|
||||||
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
||||||
|
|
@ -457,12 +458,13 @@ Environment.NewLine + "int b";
|
||||||
Assert.Equal(expected, ex.Message);
|
Assert.Equal(expected, ex.Message);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "https://github.com/aspnet/Mvc/issues/7609")]
|
[Fact]
|
||||||
public void OnProvidersExecuting_PreservesBindingInfo_WhenInferringBindingSource()
|
public void OnProvidersExecuting_PreservesBindingInfo_WhenInferringFor_ParameterWithModelBinder_AndExplicitName()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var actionName = nameof(ParameterBindingController.ModelBinderAttribute);
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
var context = GetContext(typeof(ParameterBindingController));
|
var actionName = nameof(ModelBinderOnParameterController.ModelBinderAttributeWithExplicitModelName);
|
||||||
|
var context = GetContext(typeof(ModelBinderOnParameterController), modelMetadataProvider);
|
||||||
var provider = GetProvider();
|
var provider = GetProvider();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -479,6 +481,263 @@ Environment.NewLine + "int b";
|
||||||
Assert.Equal("top", bindingInfo.BinderModelName);
|
Assert.Equal("top", bindingInfo.BinderModelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OnProvidersExecuting_PreservesBindingInfo_WhenInferringFor_ParameterWithModelBinderType()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ModelBinderOnParameterController.ModelBinderType);
|
||||||
|
var context = GetContext(typeof(ModelBinderOnParameterController), 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.Custom, bindingInfo.BindingSource);
|
||||||
|
Assert.Null(bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void OnProvidersExecuting_PreservesBindingInfo_WhenInferringFor_ParameterWithModelBinderType_AndExplicitModelName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ModelBinderOnParameterController.ModelBinderTypeWithExplicitModelName);
|
||||||
|
var context = GetContext(typeof(ModelBinderOnParameterController), 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.Custom, bindingInfo.BindingSource);
|
||||||
|
Assert.Equal("foo", bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForFromQueryParameter_WithDefaultName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromQuery);
|
||||||
|
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_ForFromQueryParameter_WithCustomName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromQueryWithCustomName);
|
||||||
|
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("top", bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForFromQueryParameterOnComplexType_WithDefaultName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromQueryOnComplexType);
|
||||||
|
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(string.Empty, bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForFromQueryParameterOnComplexType_WithCustomName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromQueryOnComplexTypeWithCustomName);
|
||||||
|
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("gps", bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForFromRouteParameter_WithDefaultName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromRoute);
|
||||||
|
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.Path, bindingInfo.BindingSource);
|
||||||
|
Assert.Null(bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForFromRouteParameter_WithCustomName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromRouteWithCustomName);
|
||||||
|
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.Path, bindingInfo.BindingSource);
|
||||||
|
Assert.Equal("top", bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForFromRouteParameterOnComplexType_WithDefaultName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromRouteOnComplexType);
|
||||||
|
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.Path, bindingInfo.BindingSource);
|
||||||
|
Assert.Equal(string.Empty, bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForFromRouteParameterOnComplexType_WithCustomName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.FromRouteOnComplexTypeWithCustomName);
|
||||||
|
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.Path, bindingInfo.BindingSource);
|
||||||
|
Assert.Equal("gps", bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void PreservesBindingSourceInference_ForParameterWithRequestPredicateAndPropertyFilterProvider()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expectedPredicate = CustomRequestPredicateAndPropertyFilterProviderAttribute.RequestPredicateStatic;
|
||||||
|
var expectedPropertyFilter = CustomRequestPredicateAndPropertyFilterProviderAttribute.PropertyFilterStatic;
|
||||||
|
var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
|
||||||
|
var actionName = nameof(ParameterBindingController.ParameterWithRequestPredicateProvider);
|
||||||
|
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.Same(expectedPredicate, bindingInfo.RequestPredicate);
|
||||||
|
Assert.Same(expectedPropertyFilter, bindingInfo.PropertyFilterProvider.PropertyFilter);
|
||||||
|
Assert.Null(bindingInfo.BinderModelName);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void InferParameterBindingSources_SetsCorrectBindingSourceForComplexTypesWithCancellationToken()
|
public void InferParameterBindingSources_SetsCorrectBindingSourceForComplexTypesWithCancellationToken()
|
||||||
{
|
{
|
||||||
|
|
@ -749,6 +1008,57 @@ 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")]
|
||||||
|
public IActionResult FromQuery([FromQuery] int value) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromquery-and-customname")]
|
||||||
|
public IActionResult FromQueryWithCustomName([FromQuery(Name = "top")] int value) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromquery-on-complextype")]
|
||||||
|
public IActionResult FromQueryOnComplexType([FromQuery] GpsCoordinates gpsCoordinates) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromquery-on-complextype-and-customname")]
|
||||||
|
public IActionResult FromQueryOnComplexTypeWithCustomName([FromQuery(Name = "gps")] GpsCoordinates gpsCoordinates) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromroute")]
|
||||||
|
public IActionResult FromRoute([FromRoute] int value) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromroute-and-customname")]
|
||||||
|
public IActionResult FromRouteWithCustomName([FromRoute(Name = "top")] int value) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromroute-on-complextype")]
|
||||||
|
public IActionResult FromRouteOnComplexType([FromRoute] GpsCoordinates gpsCoordinates) => null;
|
||||||
|
|
||||||
|
[HttpGet("parameter-with-fromroute-on-complextype-and-customname")]
|
||||||
|
public IActionResult FromRouteOnComplexTypeWithCustomName([FromRoute(Name = "gps")] GpsCoordinates gpsCoordinates) => null;
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult ParameterWithRequestPredicateProvider([CustomRequestPredicateAndPropertyFilterProvider] int value) => null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CustomRequestPredicateAndPropertyFilterProviderAttribute : Attribute, IRequestPredicateProvider, IPropertyFilterProvider
|
||||||
|
{
|
||||||
|
public static Func<ActionContext, bool> RequestPredicateStatic => (c) => true;
|
||||||
|
public static Func<ModelMetadata, bool> PropertyFilterStatic => (c) => true;
|
||||||
|
|
||||||
|
public Func<ActionContext, bool> RequestPredicate => RequestPredicateStatic;
|
||||||
|
|
||||||
|
public Func<ModelMetadata, bool> PropertyFilter => PropertyFilterStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]/[action]")]
|
||||||
|
private class ModelBinderOnParameterController
|
||||||
|
{
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult ModelBinderAttributeWithExplicitModelName([ModelBinder(Name = "top")] int value) => null;
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult ModelBinderType([ModelBinder(typeof(TestModelBinder))] string name) => null;
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public IActionResult ModelBinderTypeWithExplicitModelName([ModelBinder(typeof(TestModelBinder), Name = "foo")] string name) => null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[ApiController]
|
[ApiController]
|
||||||
|
|
@ -837,5 +1147,19 @@ Environment.NewLine + "int b";
|
||||||
[HttpGet("test")]
|
[HttpGet("test")]
|
||||||
public IActionResult Action([ModelBinder(typeof(object))] Car car) => null;
|
public IActionResult Action([ModelBinder(typeof(object))] Car car) => null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class GpsCoordinates
|
||||||
|
{
|
||||||
|
public long Latitude { get; set; }
|
||||||
|
public long Longitude { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestModelBinder : IModelBinder
|
||||||
|
{
|
||||||
|
public Task BindModelAsync(ModelBindingContext bindingContext)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -173,5 +173,35 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
|
||||||
Assert.Null(result.Name);
|
Assert.Null(result.Name);
|
||||||
Assert.Null(result.Email);
|
Assert.Null(result.Email);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ActionsWithApiBehavior_InferModelBinderType()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "From TestModelBinder: Hello!";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.GetAsync("/contact/ActionWithInferredModelBinderType?foo=Hello!");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
var result = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ActionsWithApiBehavior_InferModelBinderTypeWithExplicitModelName()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var expected = "From TestModelBinder: Hello!";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await Client.GetAsync("/contact/ActionWithInferredModelBinderTypeWithExplicitModelName?bar=Hello!");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||||
|
var result = await response.Content.ReadAsStringAsync();
|
||||||
|
Assert.Equal(expected, result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BasicWebSite.Models;
|
using BasicWebSite.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
|
|
||||||
namespace BasicWebSite
|
namespace BasicWebSite
|
||||||
{
|
{
|
||||||
|
|
@ -72,5 +73,34 @@ namespace BasicWebSite
|
||||||
{
|
{
|
||||||
return contact;
|
return contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("[action]")]
|
||||||
|
public ActionResult<string> ActionWithInferredModelBinderType(
|
||||||
|
[ModelBinder(typeof(TestModelBinder))] string foo)
|
||||||
|
{
|
||||||
|
return foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("[action]")]
|
||||||
|
public ActionResult<string> ActionWithInferredModelBinderTypeWithExplicitModelName(
|
||||||
|
[ModelBinder(typeof(TestModelBinder), Name = "bar")] string foo)
|
||||||
|
{
|
||||||
|
return foo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestModelBinder : IModelBinder
|
||||||
|
{
|
||||||
|
public Task BindModelAsync(ModelBindingContext bindingContext)
|
||||||
|
{
|
||||||
|
var val = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
|
||||||
|
if (val == null)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
bindingContext.Result = ModelBindingResult.Success("From TestModelBinder: " + val);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue