diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/ValueProviders/CompositeValueProvider.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/ValueProviders/CompositeValueProvider.cs
index 375d30a69f..059d682bc0 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/ValueProviders/CompositeValueProvider.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/ValueProviders/CompositeValueProvider.cs
@@ -9,18 +9,30 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
+ ///
+ /// Represents a whose values come from a collection of s.
+ ///
public class CompositeValueProvider : Collection, IEnumerableValueProvider, IMetadataAwareValueProvider
{
+ ///
+ /// Initializes a new instance of .
+ ///
public CompositeValueProvider()
: base()
{
}
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The sequence of to add to this instance of
+ /// .
public CompositeValueProvider(IEnumerable valueProviders)
: base(valueProviders.ToList())
{
}
+ ///
public virtual async Task ContainsPrefixAsync(string prefix)
{
for (var i = 0; i < Count; i++)
@@ -33,6 +45,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return false;
}
+ ///
public virtual async Task GetValueAsync(string key)
{
// Performance-sensitive
@@ -50,36 +63,37 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return null;
}
+ ///
public virtual async Task> GetKeysFromPrefixAsync(string prefix)
{
foreach (var valueProvider in this)
{
- var result = await GetKeysFromPrefixFromProvider(valueProvider, prefix);
- if (result != null && result.Count > 0)
+ var enumeratedProvider = valueProvider as IEnumerableValueProvider;
+ if (enumeratedProvider != null)
{
- return result;
+ var result = await enumeratedProvider.GetKeysFromPrefixAsync(prefix);
+ if (result != null && result.Count > 0)
+ {
+ return result;
+ }
}
}
return new Dictionary(StringComparer.OrdinalIgnoreCase);
}
- private static Task> GetKeysFromPrefixFromProvider(IValueProvider provider,
- string prefix)
- {
- var enumeratedProvider = provider as IEnumerableValueProvider;
- return (enumeratedProvider != null) ? enumeratedProvider.GetKeysFromPrefixAsync(prefix) : null;
- }
-
+ ///
protected override void InsertItem(int index, [NotNull] IValueProvider item)
{
base.InsertItem(index, item);
}
+ ///
protected override void SetItem(int index, [NotNull] IValueProvider item)
{
base.SetItem(index, item);
}
+ ///
public IValueProvider Filter(IValueProviderMetadata valueBinderMetadata)
{
var filteredValueProviders = new List();
diff --git a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/ValueProviders/CompositeValueProviderTests.cs b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/ValueProviders/CompositeValueProviderTests.cs
index ceddc0d88e..f59b3f2cef 100644
--- a/test/Microsoft.AspNet.Mvc.ModelBinding.Test/ValueProviders/CompositeValueProviderTests.cs
+++ b/test/Microsoft.AspNet.Mvc.ModelBinding.Test/ValueProviders/CompositeValueProviderTests.cs
@@ -5,10 +5,11 @@
using System;
using System.Collections.Generic;
+using System.Threading.Tasks;
using Moq;
using Xunit;
-namespace Microsoft.AspNet.Mvc.ModelBinding.Test
+namespace Microsoft.AspNet.Mvc.ModelBinding
{
public class CompositeValueProviderTests
{
@@ -21,6 +22,46 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
}
+ [Fact]
+ public async Task GetKeysFromPrefixAsync_ReturnsResultFromFirstValueProviderThatReturnsValues()
+ {
+ // Arrange
+ var provider1 = Mock.Of();
+ var dictionary = new Dictionary(StringComparer.Ordinal)
+ {
+ { "prefix-test", "some-value" },
+ };
+ var provider2 = new Mock();
+ provider2.Setup(p => p.GetKeysFromPrefixAsync("prefix"))
+ .Returns(Task.FromResult>(dictionary))
+ .Verifiable();
+ var provider = new CompositeValueProvider(new[] { provider1, provider2.Object });
+
+ // Act
+ var values = await provider.GetKeysFromPrefixAsync("prefix");
+
+ // Assert
+ var result = Assert.Single(values);
+ Assert.Equal("prefix-test", result.Key);
+ Assert.Equal("some-value", result.Value);
+ provider2.Verify();
+ }
+
+ [Fact]
+ public async Task GetKeysFromPrefixAsync_ReturnsEmptyDictionaryIfNoValueProviderReturnsValues()
+ {
+ // Arrange
+ var provider1 = Mock.Of();
+ var provider2 = Mock.Of();
+ var provider = new CompositeValueProvider(new[] { provider1, provider2 });
+
+ // Act
+ var values = await provider.GetKeysFromPrefixAsync("prefix");
+
+ // Assert
+ Assert.Empty(values);
+ }
+
[Theory]
[MemberData(nameof(RegisteredAsMetadataClasses))]
public void FilterReturnsItself_ForAnyClassRegisteredAsGenericParam(IValueProviderMetadata metadata)