[Fixes #1389] Can't bind complex type data from route parameters.
Changed DictionaryBasedValueProvider to do a prefix check instead of just checking if the underlying dictionary contains the key.
This commit is contained in:
parent
66f626b828
commit
98d749d03c
|
|
@ -4,6 +4,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
|
|
@ -11,6 +12,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
where TBinderMarker : IValueBinderMarker
|
||||
{
|
||||
private readonly IDictionary<string, object> _values;
|
||||
private PrefixContainer _prefixContainer;
|
||||
|
||||
public DictionaryBasedValueProvider(IDictionary<string, object> values)
|
||||
{
|
||||
|
|
@ -19,7 +21,18 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
public override Task<bool> ContainsPrefixAsync(string key)
|
||||
{
|
||||
return Task.FromResult(_values.ContainsKey(key));
|
||||
var prefixContainer = GetOrCreatePrefixContainer();
|
||||
return Task.FromResult(prefixContainer.ContainsPrefix(key));
|
||||
}
|
||||
|
||||
private PrefixContainer GetOrCreatePrefixContainer()
|
||||
{
|
||||
if (_prefixContainer == null)
|
||||
{
|
||||
_prefixContainer = new PrefixContainer(_values.Keys);
|
||||
}
|
||||
|
||||
return _prefixContainer;
|
||||
}
|
||||
|
||||
public override Task<ValueProviderResult> GetValueAsync([NotNull] string key)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
var client = server.CreateClient();
|
||||
|
||||
// Provide all three values, it should bind based on the attribute on the action method.
|
||||
var request = new HttpRequestMessage(HttpMethod.Post,
|
||||
var request = new HttpRequestMessage(HttpMethod.Post,
|
||||
string.Format("http://localhost/CompositeTest/{0}/valueFromRoute?param=valueFromQuery", actionName));
|
||||
var nameValueCollection = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
|
|
@ -107,6 +107,31 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
Assert.Equal(12, person.Age);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("http://localhost/Home/ActionWithPersonFromUrlWithPrefix/Javier/26")]
|
||||
[InlineData("http://localhost/Home/ActionWithPersonFromUrlWithoutPrefix/Javier/26")]
|
||||
public async Task CanBind_ComplexData_FromRouteData(string url)
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
var response = await
|
||||
client.GetAsync(url);
|
||||
|
||||
//Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
Assert.NotNull(body);
|
||||
|
||||
var person = JsonConvert.DeserializeObject<Person>(body);
|
||||
Assert.NotNull(person);
|
||||
Assert.Equal("Javier", person.Name);
|
||||
Assert.Equal(26, person.Age);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelBindCancellationTokenParameteres()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using Xunit;
|
|||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public class DictionaryBasedValueProviderTestss
|
||||
public class DictionaryBasedValueProviderTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetValueProvider_ReturnsNull_WhenKeyIsNotFound()
|
||||
|
|
@ -63,6 +63,67 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
Assert.Null(result.AttemptedValue);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("foo")]
|
||||
[InlineData("bar")]
|
||||
[InlineData("bar.baz")]
|
||||
public async Task ContainsPrefixAsync_ReturnsTrue_ForKnownPrefixes(string prefix)
|
||||
{
|
||||
// Arrange
|
||||
var values = new Dictionary<string, object>
|
||||
{
|
||||
{ "foo", 1 },
|
||||
{ "bar.baz", 1 },
|
||||
};
|
||||
|
||||
var valueProvider = new DictionaryBasedValueProvider<TestValueBinderMarker>(values);
|
||||
|
||||
// Act
|
||||
var result = await valueProvider.ContainsPrefixAsync(prefix);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("bar", "1")]
|
||||
[InlineData("bar.baz", "2")]
|
||||
public async Task GetValueAsync_ReturnsCorrectValue_ForKnownKeys(string prefix, string expectedValue)
|
||||
{
|
||||
// Arrange
|
||||
var values = new Dictionary<string, object>
|
||||
{
|
||||
{ "bar", 1 },
|
||||
{ "bar.baz", 2 },
|
||||
};
|
||||
|
||||
var valueProvider = new DictionaryBasedValueProvider<TestValueBinderMarker>(values);
|
||||
|
||||
// Act
|
||||
var result = await valueProvider.GetValueAsync(prefix);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedValue, (string)result.AttemptedValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetValueAsync_DoesNotReturnAValue_ForAKeyPrefix()
|
||||
{
|
||||
// Arrange
|
||||
var values = new Dictionary<string, object>
|
||||
{
|
||||
{ "bar.baz", 2 },
|
||||
};
|
||||
|
||||
var valueProvider = new DictionaryBasedValueProvider<TestValueBinderMarker>(values);
|
||||
|
||||
// Act
|
||||
var result = await valueProvider.GetValueAsync("bar");
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ContainsPrefixAsync_ReturnsFalse_IfKeyIsNotPresent()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,18 @@ namespace ModelBindingWebSite.Controllers
|
|||
return wrapper.CancellationToken == ActionContext.HttpContext.RequestAborted;
|
||||
}
|
||||
|
||||
[HttpGet("Home/ActionWithPersonFromUrlWithPrefix/{person.name}/{person.age}")]
|
||||
public Person ActionWithPersonFromUrlWithPrefix([FromRoute] Person person)
|
||||
{
|
||||
return person;
|
||||
}
|
||||
|
||||
[HttpGet("Home/ActionWithPersonFromUrlWithoutPrefix/{name}/{age}")]
|
||||
public Person ActionWithPersonFromUrlWithoutPrefix([FromRoute] Person person)
|
||||
{
|
||||
return person;
|
||||
}
|
||||
|
||||
private Dictionary<string, string> CreateValidationDictionary()
|
||||
{
|
||||
var result = new Dictionary<string, string>();
|
||||
|
|
|
|||
Loading…
Reference in New Issue