parent
1da7a89f59
commit
d603735818
|
|
@ -13,7 +13,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FormValueProvider : BindingSourceValueProvider, IEnumerableValueProvider
|
public class FormValueProvider : BindingSourceValueProvider, IEnumerableValueProvider
|
||||||
{
|
{
|
||||||
private readonly CultureInfo _culture;
|
|
||||||
private readonly IFormCollection _values;
|
private readonly IFormCollection _values;
|
||||||
private PrefixContainer _prefixContainer;
|
private PrefixContainer _prefixContainer;
|
||||||
|
|
||||||
|
|
@ -40,10 +39,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
_values = values;
|
_values = values;
|
||||||
_culture = culture;
|
Culture = culture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CultureInfo Culture => _culture;
|
public CultureInfo Culture { get; }
|
||||||
|
|
||||||
protected PrefixContainer PrefixContainer
|
protected PrefixContainer PrefixContainer
|
||||||
{
|
{
|
||||||
|
|
@ -83,6 +82,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
throw new ArgumentNullException(nameof(key));
|
throw new ArgumentNullException(nameof(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key.Length == 0)
|
||||||
|
{
|
||||||
|
// Top level parameters will fall back to an empty prefix when the parameter name does not
|
||||||
|
// appear in any value provider. This would result in the parameter binding to a form parameter
|
||||||
|
// with a empty key (e.g. Request body looks like "=test") which isn't a scenario we want to support.
|
||||||
|
// Return a "None" result in this event.
|
||||||
|
return ValueProviderResult.None;
|
||||||
|
}
|
||||||
|
|
||||||
var values = _values[key];
|
var values = _values[key];
|
||||||
if (values.Count == 0)
|
if (values.Count == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -90,7 +98,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new ValueProviderResult(values, _culture);
|
return new ValueProviderResult(values, Culture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,11 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override ValueProviderResult GetValue(string key)
|
public override ValueProviderResult GetValue(string key)
|
||||||
{
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(key));
|
||||||
|
}
|
||||||
|
|
||||||
if (_values.TryGetValue(key, out var values) && values.Count > 0)
|
if (_values.TryGetValue(key, out var values) && values.Count > 0)
|
||||||
{
|
{
|
||||||
return new ValueProviderResult(values, Culture);
|
return new ValueProviderResult(values, Culture);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class QueryStringValueProvider : BindingSourceValueProvider, IEnumerableValueProvider
|
public class QueryStringValueProvider : BindingSourceValueProvider, IEnumerableValueProvider
|
||||||
{
|
{
|
||||||
private readonly CultureInfo _culture;
|
|
||||||
private readonly IQueryCollection _values;
|
private readonly IQueryCollection _values;
|
||||||
private PrefixContainer _prefixContainer;
|
private PrefixContainer _prefixContainer;
|
||||||
|
|
||||||
|
|
@ -40,10 +39,10 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
_values = values;
|
_values = values;
|
||||||
_culture = culture;
|
Culture = culture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CultureInfo Culture => _culture;
|
public CultureInfo Culture { get; }
|
||||||
|
|
||||||
protected PrefixContainer PrefixContainer
|
protected PrefixContainer PrefixContainer
|
||||||
{
|
{
|
||||||
|
|
@ -83,6 +82,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
throw new ArgumentNullException(nameof(key));
|
throw new ArgumentNullException(nameof(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key.Length == 0)
|
||||||
|
{
|
||||||
|
// Top level parameters will fall back to an empty prefix when the parameter name does not
|
||||||
|
// appear in any value provider. This would result in the parameter binding to a query string
|
||||||
|
// parameter with a empty key (e.g. /User?=test) which isn't a scenario we want to support.
|
||||||
|
// Return a "None" result in this event.
|
||||||
|
return ValueProviderResult.None;
|
||||||
|
}
|
||||||
|
|
||||||
var values = _values[key];
|
var values = _values[key];
|
||||||
if (values.Count == 0)
|
if (values.Count == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -90,7 +98,7 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return new ValueProviderResult(values, _culture);
|
return new ValueProviderResult(values, Culture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,15 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
throw new ArgumentNullException(nameof(key));
|
throw new ArgumentNullException(nameof(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key.Length == 0)
|
||||||
|
{
|
||||||
|
// Top level parameters will fall back to an empty prefix when the parameter name does not
|
||||||
|
// appear in any value provider. This would result in the parameter binding to a route value
|
||||||
|
// an empty key which isn't a scenario we want to support.
|
||||||
|
// Return a "None" result in this event.
|
||||||
|
return ValueProviderResult.None;
|
||||||
|
}
|
||||||
|
|
||||||
if (_values.TryGetValue(key, out var value))
|
if (_values.TryGetValue(key, out var value))
|
||||||
{
|
{
|
||||||
var stringValue = value as string ?? Convert.ToString(value, Culture) ?? string.Empty;
|
var stringValue = value as string ?? Convert.ToString(value, Culture) ?? string.Empty;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Internal;
|
||||||
using Microsoft.Extensions.Primitives;
|
using Microsoft.Extensions.Primitives;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -38,9 +40,8 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
Dictionary<string, StringValues> values,
|
Dictionary<string, StringValues> values,
|
||||||
CultureInfo culture)
|
CultureInfo culture)
|
||||||
{
|
{
|
||||||
var emptyValueProvider =
|
var emptyValueProvider = new QueryStringValueProvider(bindingSource, new QueryCollection(), culture);
|
||||||
new JQueryFormValueProvider(bindingSource, new Dictionary<string, StringValues>(), culture);
|
var valueProvider = new FormValueProvider(bindingSource, new FormCollection(values), culture);
|
||||||
var valueProvider = new JQueryFormValueProvider(bindingSource, values, culture);
|
|
||||||
|
|
||||||
return new CompositeValueProvider() { emptyValueProvider, valueProvider };
|
return new CompositeValueProvider() { emptyValueProvider, valueProvider };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,23 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
Assert.Equal(ValueProviderResult.None, result);
|
Assert.Equal(ValueProviderResult.None, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public virtual void GetValue_EmptyKey()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var store = new Dictionary<string, StringValues>(BackingStore)
|
||||||
|
{
|
||||||
|
{ string.Empty, "some-value" },
|
||||||
|
};
|
||||||
|
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, store, culture: null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = valueProvider.GetValue(string.Empty);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(ValueProviderResult.None, result);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public virtual void FilterInclude()
|
public virtual void FilterInclude()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -31,5 +31,22 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Null(result);
|
Assert.Null(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public override void GetValue_EmptyKey()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var store = new Dictionary<string, StringValues>(BackingStore)
|
||||||
|
{
|
||||||
|
{ string.Empty, "some-value" },
|
||||||
|
};
|
||||||
|
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, store, culture: null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = valueProvider.GetValue(string.Empty);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("some-value", (string)result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,5 +34,22 @@ namespace Microsoft.AspNetCore.Mvc.ModelBinding
|
||||||
// Assert
|
// Assert
|
||||||
Assert.Null(result);
|
Assert.Null(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public override void GetValue_EmptyKey()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var store = new Dictionary<string, StringValues>(BackingStore)
|
||||||
|
{
|
||||||
|
{ string.Empty, "some-value" },
|
||||||
|
};
|
||||||
|
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, store, culture: null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = valueProvider.GetValue(string.Empty);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("some-value", (string)result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,39 @@ namespace Microsoft.AspNetCore.Mvc.IntegrationTests
|
||||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task BindParameter_WithEmptyQueryStringKey_DoesNotGetBound()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var parameterBinder = ModelBindingTestHelper.GetParameterBinder();
|
||||||
|
var parameter = new ParameterDescriptor
|
||||||
|
{
|
||||||
|
Name = "Parameter1",
|
||||||
|
BindingInfo = new BindingInfo(),
|
||||||
|
|
||||||
|
ParameterType = typeof(string)
|
||||||
|
};
|
||||||
|
|
||||||
|
var testContext = ModelBindingTestHelper.GetTestContext(request =>
|
||||||
|
{
|
||||||
|
request.QueryString = new QueryString("?=someValue");
|
||||||
|
});
|
||||||
|
|
||||||
|
var modelState = testContext.ModelState;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var modelBindingResult = await parameterBinder.BindModelAsync(parameter, testContext);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
|
||||||
|
// ModelBindingResult
|
||||||
|
Assert.False(modelBindingResult.IsModelSet);
|
||||||
|
|
||||||
|
// ModelState
|
||||||
|
Assert.True(modelState.IsValid);
|
||||||
|
Assert.Empty(modelState.Keys);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
[ReplaceCulture("en-GB", "en-GB")]
|
[ReplaceCulture("en-GB", "en-GB")]
|
||||||
public async Task BindDecimalParameter_WithData_GetsBound()
|
public async Task BindDecimalParameter_WithData_GetsBound()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue