Change IValueProviderFactory.GetValueProvider to be synchronous.
This commit is contained in:
parent
ec8d09dd65
commit
d8ba998dec
|
|
@ -29,14 +29,12 @@ namespace Microsoft.AspNet.Mvc
|
|||
_validatorProviders = validatorProviders;
|
||||
}
|
||||
|
||||
public async Task<ActionBindingContext> GetActionBindingContextAsync(ActionContext actionContext)
|
||||
public Task<ActionBindingContext> GetActionBindingContextAsync(ActionContext actionContext)
|
||||
{
|
||||
var requestContext = new RequestContext(actionContext.HttpContext, actionContext.RouteValues);
|
||||
var valueProviders = await Task.WhenAll(_valueProviderFactories.Select(factory => factory.GetValueProviderAsync(requestContext)));
|
||||
valueProviders = valueProviders.Where(vp => vp != null)
|
||||
.ToArray();
|
||||
|
||||
return new ActionBindingContext(
|
||||
var valueProviders = _valueProviderFactories.Select(factory => factory.GetValueProvider(requestContext))
|
||||
.Where(vp => vp != null);
|
||||
var context = new ActionBindingContext(
|
||||
actionContext,
|
||||
_modelMetadataProvider,
|
||||
new CompositeModelBinder(_modelBinders),
|
||||
|
|
@ -44,6 +42,8 @@ namespace Microsoft.AspNet.Mvc
|
|||
_inputFormatterProvider,
|
||||
_validatorProviders
|
||||
);
|
||||
|
||||
return Task.FromResult(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
public virtual async Task<bool> ContainsPrefixAsync(string prefix)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
if (await this[i].ContainsPrefixAsync(prefix))
|
||||
{
|
||||
|
|
@ -39,11 +39,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
// Performance-sensitive
|
||||
// Caching the count is faster for IList<T>
|
||||
int itemCount = Items.Count;
|
||||
for (int i = 0; i < itemCount; i++)
|
||||
var itemCount = Items.Count;
|
||||
for (var i = 0; i < itemCount; i++)
|
||||
{
|
||||
IValueProvider vp = Items[i];
|
||||
ValueProviderResult result = await vp.GetValueAsync(key);
|
||||
var valueProvider = Items[i];
|
||||
var result = await valueProvider.GetValueAsync(key);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
|
|
@ -52,11 +52,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
return null;
|
||||
}
|
||||
|
||||
public virtual IDictionary<string, string> GetKeysFromPrefix(string prefix)
|
||||
public virtual async Task<IDictionary<string, string>> GetKeysFromPrefixAsync(string prefix)
|
||||
{
|
||||
foreach (IValueProvider vp in this)
|
||||
foreach (var valueProvider in this)
|
||||
{
|
||||
IDictionary<string, string> result = GetKeysFromPrefixFromProvider(vp, prefix);
|
||||
var result = await GetKeysFromPrefixFromProvider(valueProvider, prefix);
|
||||
if (result != null && result.Count > 0)
|
||||
{
|
||||
return result;
|
||||
|
|
@ -65,10 +65,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
internal static IDictionary<string, string> GetKeysFromPrefixFromProvider(IValueProvider provider, string prefix)
|
||||
private static Task<IDictionary<string, string>> GetKeysFromPrefixFromProvider(IValueProvider provider,
|
||||
string prefix)
|
||||
{
|
||||
IEnumerableValueProvider enumeratedProvider = provider as IEnumerableValueProvider;
|
||||
return (enumeratedProvider != null) ? enumeratedProvider.GetKeysFromPrefix(prefix) : null;
|
||||
var enumeratedProvider = provider as IEnumerableValueProvider;
|
||||
return (enumeratedProvider != null) ? enumeratedProvider.GetKeysFromPrefixAsync(prefix) : null;
|
||||
}
|
||||
|
||||
protected override void InsertItem(int index, [NotNull] IValueProvider item)
|
||||
|
|
|
|||
|
|
@ -12,15 +12,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
private const string FormEncodedContentType = "application/x-www-form-urlencoded";
|
||||
|
||||
public async Task<IValueProvider> GetValueProviderAsync(RequestContext requestContext)
|
||||
public IValueProvider GetValueProvider(RequestContext requestContext)
|
||||
{
|
||||
var request = requestContext.HttpContext.Request;
|
||||
|
||||
if (IsSupportedContentType(request))
|
||||
{
|
||||
var queryCollection = await request.GetFormAsync();
|
||||
var culture = GetCultureInfo(request);
|
||||
return new ReadableStringCollectionValueProvider(queryCollection, culture);
|
||||
return new ReadableStringCollectionValueProvider(request.GetFormAsync, culture);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -2,11 +2,12 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public interface IEnumerableValueProvider : IValueProvider
|
||||
{
|
||||
IDictionary<string, string> GetKeysFromPrefix(string prefix);
|
||||
Task<IDictionary<string, string>> GetKeysFromPrefixAsync(string prefix);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
/// </summary>
|
||||
/// <param name="requestContext">RequestContext that value provider will populate from</param>
|
||||
/// <returns>a value provider instance or null</returns>
|
||||
Task<IValueProvider> GetValueProviderAsync(RequestContext requestContext);
|
||||
IValueProvider GetValueProvider(RequestContext requestContext);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
|
|
@ -11,7 +9,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
private static readonly object _cacheKey = new object();
|
||||
|
||||
public Task<IValueProvider> GetValueProviderAsync([NotNull] RequestContext requestContext)
|
||||
public IValueProvider GetValueProvider([NotNull] RequestContext requestContext)
|
||||
{
|
||||
// Process the query collection once-per request.
|
||||
var storage = requestContext.HttpContext.Items;
|
||||
|
|
@ -27,7 +25,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
provider = (ReadableStringCollectionValueProvider)value;
|
||||
}
|
||||
return Task.FromResult(provider);
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
|
@ -14,7 +16,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
private readonly CultureInfo _culture;
|
||||
private PrefixContainer _prefixContainer;
|
||||
private readonly IReadableStringCollection _values;
|
||||
private readonly Func<Task<IReadableStringCollection>> _valuesFactory;
|
||||
private IReadableStringCollection _values;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a NameValuePairsProvider wrapping an existing set of key value pairs.
|
||||
|
|
@ -27,6 +30,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
_culture = culture;
|
||||
}
|
||||
|
||||
public ReadableStringCollectionValueProvider([NotNull] Func<Task<IReadableStringCollection>> valuesFactory,
|
||||
CultureInfo culture)
|
||||
{
|
||||
_valuesFactory = valuesFactory;
|
||||
_culture = culture;
|
||||
}
|
||||
|
||||
public CultureInfo Culture
|
||||
{
|
||||
get
|
||||
|
|
@ -35,35 +45,24 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
}
|
||||
}
|
||||
|
||||
private PrefixContainer PrefixContainer
|
||||
public virtual async Task<bool> ContainsPrefixAsync(string prefix)
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_prefixContainer == null)
|
||||
{
|
||||
// Initialization race is OK providing data remains read-only and object identity is not significant
|
||||
// TODO: Figure out if we can have IReadableStringCollection expose Keys, Count etc
|
||||
|
||||
_prefixContainer = new PrefixContainer(_values.Select(v => v.Key).ToArray());
|
||||
}
|
||||
return _prefixContainer;
|
||||
}
|
||||
var prefixContainer = await GetPrefixContainerAsync();
|
||||
return prefixContainer.ContainsPrefix(prefix);
|
||||
}
|
||||
|
||||
public virtual Task<bool> ContainsPrefixAsync(string prefix)
|
||||
public virtual async Task<IDictionary<string, string>> GetKeysFromPrefixAsync([NotNull] string prefix)
|
||||
{
|
||||
return Task.FromResult(PrefixContainer.ContainsPrefix(prefix));
|
||||
var prefixContainer = await GetPrefixContainerAsync();
|
||||
return prefixContainer.GetKeysFromPrefix(prefix);
|
||||
}
|
||||
|
||||
public virtual IDictionary<string, string> GetKeysFromPrefix([NotNull] string prefix)
|
||||
public virtual async Task<ValueProviderResult> GetValueAsync([NotNull] string key)
|
||||
{
|
||||
return PrefixContainer.GetKeysFromPrefix(prefix);
|
||||
}
|
||||
var collection = await GetValueCollectionAsync();
|
||||
var values = collection.GetValues(key);
|
||||
|
||||
public virtual Task<ValueProviderResult> GetValueAsync([NotNull] string key)
|
||||
{
|
||||
ValueProviderResult result;
|
||||
var values = _values.GetValues(key);
|
||||
if (values == null)
|
||||
{
|
||||
result = null;
|
||||
|
|
@ -78,7 +77,31 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
result = new ValueProviderResult(values, _values.Get(key), _culture);
|
||||
}
|
||||
|
||||
return Task.FromResult(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<IReadableStringCollection> GetValueCollectionAsync()
|
||||
{
|
||||
if (_values == null)
|
||||
{
|
||||
Contract.Assert(_valuesFactory != null);
|
||||
_values = await _valuesFactory();
|
||||
}
|
||||
|
||||
return _values;
|
||||
}
|
||||
|
||||
private async Task<PrefixContainer> GetPrefixContainerAsync()
|
||||
{
|
||||
if (_prefixContainer == null)
|
||||
{
|
||||
// Initialization race is OK providing data remains read-only and object identity is not significant
|
||||
// TODO: Fix this once https://github.com/aspnet/HttpAbstractions/issues/3 is sorted out.
|
||||
|
||||
var collection = await GetValueCollectionAsync();
|
||||
_prefixContainer = new PrefixContainer(collection.Select(v => v.Key).ToArray());
|
||||
}
|
||||
return _prefixContainer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public class RouteValueValueProviderFactory : IValueProviderFactory
|
||||
{
|
||||
public Task<IValueProvider> GetValueProviderAsync(RequestContext requestContext)
|
||||
public IValueProvider GetValueProvider(RequestContext requestContext)
|
||||
{
|
||||
var valueProvider = new DictionaryBasedValueProvider(requestContext.RouteValues);
|
||||
return Task.FromResult<IValueProvider>(valueProvider);
|
||||
return new DictionaryBasedValueProvider(requestContext.RouteValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
public class FormValueProviderFactoryTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task GetValueProvider_ReturnsNull_WhenContentTypeIsNotFormUrlEncoded()
|
||||
public void GetValueProvider_ReturnsNull_WhenContentTypeIsNotFormUrlEncoded()
|
||||
{
|
||||
// Arrange
|
||||
var requestContext = CreateRequestContext("some-content-type");
|
||||
var factory = new FormValueProviderFactory();
|
||||
|
||||
// Act
|
||||
var result = await factory.GetValueProviderAsync(requestContext);
|
||||
var result = factory.GetValueProvider(requestContext);
|
||||
|
||||
// Assert
|
||||
Assert.Null(result);
|
||||
|
|
@ -30,14 +30,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
[Theory]
|
||||
[InlineData("application/x-www-form-urlencoded")]
|
||||
[InlineData("application/x-www-form-urlencoded;charset=utf-8")]
|
||||
public async Task GetValueProvider_ReturnsValueProviderInstaceWithInvariantCulture(string contentType)
|
||||
public void GetValueProvider_ReturnsValueProviderInstaceWithInvariantCulture(string contentType)
|
||||
{
|
||||
// Arrange
|
||||
var requestContext = CreateRequestContext(contentType);
|
||||
var factory = new FormValueProviderFactory();
|
||||
|
||||
// Act
|
||||
var result = await factory.GetValueProviderAsync(requestContext);
|
||||
var result = factory.GetValueProvider(requestContext);
|
||||
|
||||
// Assert
|
||||
var valueProvider = Assert.IsType<ReadableStringCollectionValueProvider>(result);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
#if NET45
|
||||
using Moq;
|
||||
|
|
@ -18,7 +17,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
|
||||
#if NET45
|
||||
[Fact]
|
||||
public async Task GetValueProvider_ReturnsQueryStringValueProviderInstaceWithInvariantCulture()
|
||||
public void GetValueProvider_ReturnsQueryStringValueProviderInstaceWithInvariantCulture()
|
||||
{
|
||||
// Arrange
|
||||
var request = new Mock<HttpRequest>();
|
||||
|
|
@ -29,7 +28,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
var requestContext = new RequestContext(context.Object, new Dictionary<string, object>());
|
||||
|
||||
// Act
|
||||
var result = await _factory.GetValueProviderAsync(requestContext);
|
||||
var result = _factory.GetValueProvider(requestContext);
|
||||
|
||||
// Assert
|
||||
var valueProvider = Assert.IsType<ReadableStringCollectionValueProvider>(result);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
|
||||
|
||||
[Fact]
|
||||
public async Task ContainsPrefix_WithEmptyCollection_ReturnsFalseForEmptyPrefix()
|
||||
public async Task ContainsPrefixAsync_WithEmptyCollection_ReturnsFalseForEmptyPrefix()
|
||||
{
|
||||
// Arrange
|
||||
var backingStore = new ReadableStringCollection(new Dictionary<string, string[]>());
|
||||
|
|
@ -38,7 +38,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ContainsPrefix_WithNonEmptyCollection_ReturnsTrueForEmptyPrefix()
|
||||
public async Task ContainsPrefixAsync_WithNonEmptyCollection_ReturnsTrueForEmptyPrefix()
|
||||
{
|
||||
// Arrange
|
||||
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
|
||||
|
|
@ -51,7 +51,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ContainsPrefix_WithNonEmptyCollection_ReturnsTrueForKnownPrefixes()
|
||||
public async Task ContainsPrefixAsync_WithNonEmptyCollection_ReturnsTrueForKnownPrefixes()
|
||||
{
|
||||
// Arrange
|
||||
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
|
||||
|
|
@ -63,7 +63,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ContainsPrefix_WithNonEmptyCollection_ReturnsFalseForUnknownPrefix()
|
||||
public async Task ContainsPrefixAsync_WithNonEmptyCollection_ReturnsFalseForUnknownPrefix()
|
||||
{
|
||||
// Arrange
|
||||
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
|
||||
|
|
@ -76,13 +76,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetKeysFromPrefix_EmptyPrefix_ReturnsAllPrefixes()
|
||||
public async Task GetKeysFromPrefixAsync_EmptyPrefix_ReturnsAllPrefixes()
|
||||
{
|
||||
// Arrange
|
||||
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
|
||||
|
||||
// Act
|
||||
IDictionary<string, string> result = valueProvider.GetKeysFromPrefix("");
|
||||
var result = await valueProvider.GetKeysFromPrefixAsync("");
|
||||
|
||||
// Assert
|
||||
Assert.Equal<KeyValuePair<string, string>>(
|
||||
|
|
@ -91,35 +91,35 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetKeysFromPrefix_UnknownPrefix_ReturnsEmptyDictionary()
|
||||
public async Task GetKeysFromPrefixAsync_UnknownPrefix_ReturnsEmptyDictionary()
|
||||
{
|
||||
// Arrange
|
||||
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
|
||||
|
||||
// Act
|
||||
IDictionary<string, string> result = valueProvider.GetKeysFromPrefix("abc");
|
||||
var result = await valueProvider.GetKeysFromPrefixAsync("abc");
|
||||
|
||||
// Assert
|
||||
Assert.Empty(result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetKeysFromPrefix_KnownPrefix_ReturnsMatchingItems()
|
||||
public async Task GetKeysFromPrefixAsync_KnownPrefix_ReturnsMatchingItems()
|
||||
{
|
||||
// Arrange
|
||||
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
|
||||
|
||||
// Act
|
||||
IDictionary<string, string> result = valueProvider.GetKeysFromPrefix("bar");
|
||||
var result = await valueProvider.GetKeysFromPrefixAsync("bar");
|
||||
|
||||
// Assert
|
||||
KeyValuePair<string, string> kvp = Assert.Single(result);
|
||||
var kvp = Assert.Single(result);
|
||||
Assert.Equal("baz", kvp.Key);
|
||||
Assert.Equal("bar.baz", kvp.Value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetValue_SingleValue()
|
||||
public async Task GetValueAsync_SingleValue()
|
||||
{
|
||||
// Arrange
|
||||
var culture = new CultureInfo("fr-FR");
|
||||
|
|
@ -136,7 +136,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetValue_MultiValue()
|
||||
public async Task GetValueAsync_MultiValue()
|
||||
{
|
||||
// Arrange
|
||||
var culture = new CultureInfo("fr-FR");
|
||||
|
|
@ -174,7 +174,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
//}
|
||||
|
||||
[Fact]
|
||||
public async Task GetValue_NullMultipleValue()
|
||||
public async Task GetValueAsync_NullMultipleValue()
|
||||
{
|
||||
// Arrange
|
||||
var backingStore = new ReadableStringCollection(
|
||||
|
|
@ -194,7 +194,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetValue_ReturnsNullIfKeyNotFound()
|
||||
public async Task GetValueAsync_ReturnsNullIfKeyNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
|
||||
|
|
|
|||
Loading…
Reference in New Issue