Make IValueProvider sync, IValueProviderFactory async

This commit is contained in:
Ryan Nowak 2015-08-19 11:04:08 -07:00
parent 3519c375fc
commit 4a7ada5f64
36 changed files with 302 additions and 356 deletions

View File

@ -15,13 +15,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// </summary>
/// <param name="prefix">The prefix to search for.</param>
/// <returns>true if the collection contains the specified prefix; otherwise, false.</returns>
Task<bool> ContainsPrefixAsync(string prefix);
bool ContainsPrefix(string prefix);
/// <summary>
/// Retrieves a value object using the specified key.
/// </summary>
/// <param name="key">The key of the value object to retrieve.</param>
/// <returns>The value object for the specified key. If the exact key is not found, null.</returns>
Task<ValueProviderResult> GetValueAsync(string key);
ValueProviderResult GetValue(string key);
}
}

View File

@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. 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;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
@ -8,10 +9,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public interface IValueProviderFactory
{
/// <summary>
/// Get a value provider with values from the given <paramref name="requestContext"/>.
/// Gets a <see cref="IValueProvider"/> with values from the current request.
/// </summary>
/// <param name="context">ValueProviderFactoryContext that value provider will populate from</param>
/// <returns>a value provider instance or null</returns>
IValueProvider GetValueProvider([NotNull] ValueProviderFactoryContext context);
/// <param name="context">The <see cref="ValueProviderFactoryContext"/>.</param>
/// <returns>
/// A <see cref="Task"/> that when completed will yield a <see cref="IValueProvider"/> instance or <c>null</c>.
/// </returns>
Task<IValueProvider> GetValueProviderAsync([NotNull] ValueProviderFactoryContext context);
}
}

View File

@ -11,7 +11,7 @@ using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
/// <summary>
/// Result of an <see cref="IValueProvider.GetValueAsync(string)"/> operation.
/// Result of an <see cref="IValueProvider.GetValue(string)"/> operation.
/// </summary>
/// <remarks>
/// <para>

View File

@ -333,7 +333,7 @@ namespace Microsoft.AspNet.Mvc.Core
ActionContext.HttpContext,
ActionContext.RouteData.Values);
ActionBindingContext.ValueProvider = CompositeValueProvider.Create(
ActionBindingContext.ValueProvider = await CompositeValueProvider.CreateAsync(
_resourceExecutingContext.ValueProviderFactories,
valueProviderFactoryContext);

View File

@ -60,10 +60,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
protected BindingSource BindingSource { get; }
/// <inheritdoc />
public abstract Task<bool> ContainsPrefixAsync(string prefix);
public abstract bool ContainsPrefix(string prefix);
/// <inheritdoc />
public abstract Task<ValueProviderResult> GetValueAsync(string key);
public abstract ValueProviderResult GetValue(string key);
/// <inheritdoc />
public virtual IValueProvider Filter(BindingSource bindingSource)

View File

@ -13,7 +13,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public class ByteArrayModelBinder : IModelBinder
{
/// <inheritdoc />
public async Task<ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
public Task<ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
{
return Task.FromResult(BindModel(bindingContext));
}
private ModelBindingResult BindModel(ModelBindingContext bindingContext)
{
// Check if this binder applies.
if (bindingContext.ModelType != typeof(byte[]))
@ -22,7 +27,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
// Check for missing data case 1: There was no <input ... /> element containing this data.
var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == ValueProviderResult.None)
{
return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);

View File

@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ModelBindingHelper.ValidateBindingContext(bindingContext);
var model = bindingContext.Model;
if (!await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
{
// If this is the fallback case and we failed to find data for a top-level model, then generate a
// default 'empty' model (or use existing Model) and return it.
@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return null;
}
var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
CollectionResult result;
if (valueProviderResult == ValueProviderResult.None)
@ -188,7 +188,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
private async Task<CollectionResult> BindComplexCollection(ModelBindingContext bindingContext)
{
var indexPropertyName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, "index");
var valueProviderResultIndex = await bindingContext.ValueProvider.GetValueAsync(indexPropertyName);
var valueProviderResultIndex = bindingContext.ValueProvider.GetValue(indexPropertyName);
var indexNames = GetIndexNamesFromValueProviderResult(valueProviderResultIndex);
return await BindComplexCollectionFromIndexes(bindingContext, indexNames);

View File

@ -46,14 +46,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// A <see cref="CompositeValueProvider"/> containing all <see cref="IValueProvider"/> instances
/// created.
/// </returns>
public static CompositeValueProvider Create(
public static async Task<CompositeValueProvider> CreateAsync(
[NotNull] IEnumerable<IValueProviderFactory> factories,
[NotNull] ValueProviderFactoryContext context)
{
var composite = new CompositeValueProvider();
foreach (var valueProvidersFactory in factories)
{
var valueProvider = valueProvidersFactory.GetValueProvider(context);
var valueProvider = await valueProvidersFactory.GetValueProviderAsync(context);
if (valueProvider != null)
{
composite.Add(valueProvider);
@ -64,11 +64,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
/// <inheritdoc />
public virtual async Task<bool> ContainsPrefixAsync(string prefix)
public virtual bool ContainsPrefix(string prefix)
{
for (var i = 0; i < Count; i++)
{
if (await this[i].ContainsPrefixAsync(prefix))
if (this[i].ContainsPrefix(prefix))
{
return true;
}
@ -77,7 +77,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
/// <inheritdoc />
public virtual async Task<ValueProviderResult> GetValueAsync(string key)
public virtual ValueProviderResult GetValue(string key)
{
// Performance-sensitive
// Caching the count is faster for IList<T>
@ -85,7 +85,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
for (var i = 0; i < itemCount; i++)
{
var valueProvider = Items[i];
var result = await valueProvider.GetValueAsync(key);
var result = valueProvider.GetValue(key);
if (result != ValueProviderResult.None)
{
return result;
@ -96,14 +96,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
/// <inheritdoc />
public virtual async Task<IDictionary<string, string>> GetKeysFromPrefixAsync(string prefix)
public virtual IDictionary<string, string> GetKeysFromPrefix(string prefix)
{
foreach (var valueProvider in this)
{
var enumeratedProvider = valueProvider as IEnumerableValueProvider;
if (enumeratedProvider != null)
{
var result = await enumeratedProvider.GetKeysFromPrefixAsync(prefix);
var result = enumeratedProvider.GetKeysFromPrefix(prefix);
if (result != null && result.Count > 0)
{
return result;

View File

@ -44,27 +44,24 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
/// <inheritdoc />
public override Task<bool> ContainsPrefixAsync(string key)
public override bool ContainsPrefix(string key)
{
return Task.FromResult(PrefixContainer.ContainsPrefix(key));
return PrefixContainer.ContainsPrefix(key);
}
/// <inheritdoc />
public override Task<ValueProviderResult> GetValueAsync([NotNull] string key)
public override ValueProviderResult GetValue([NotNull] string key)
{
object value;
ValueProviderResult result;
if (_values.TryGetValue(key, out value))
{
var stringValue = value as string ?? value?.ToString() ?? string.Empty;
result = new ValueProviderResult(stringValue, CultureInfo.InvariantCulture);
return new ValueProviderResult(stringValue, CultureInfo.InvariantCulture);
}
else
{
result = ValueProviderResult.None;
return ValueProviderResult.None;
}
return Task.FromResult(result);
}
}
}

View File

@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
// Attempt to bind dictionary from a set of prefix[key]=value entries. Get the short and long keys first.
var keys = await enumerableValueProvider.GetKeysFromPrefixAsync(bindingContext.ModelName);
var keys = enumerableValueProvider.GetKeysFromPrefix(bindingContext.ModelName);
if (!keys.Any())
{
// No entries with the expected keys.

View File

@ -3,7 +3,6 @@
using System;
using System.Globalization;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
@ -22,20 +21,20 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public string Value { get; }
public Task<bool> ContainsPrefixAsync(string prefix)
public bool ContainsPrefix(string prefix)
{
return Task.FromResult(PrefixContainer.IsPrefixMatch(prefix, Key));
return PrefixContainer.IsPrefixMatch(prefix, Key);
}
public Task<ValueProviderResult> GetValueAsync(string key)
public ValueProviderResult GetValue(string key)
{
if (string.Equals(key, Key, StringComparison.OrdinalIgnoreCase))
{
return Task.FromResult(new ValueProviderResult(Value, Culture));
return new ValueProviderResult(Value, Culture);
}
else
{
return Task.FromResult(ValueProviderResult.None);
return ValueProviderResult.None;
}
}
}

View File

@ -2,6 +2,7 @@
// 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.Http;
using Microsoft.Framework.Internal;
@ -9,7 +10,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
public class FormValueProviderFactory : IValueProviderFactory
{
public IValueProvider GetValueProvider([NotNull] ValueProviderFactoryContext context)
public async Task<IValueProvider> GetValueProviderAsync([NotNull] ValueProviderFactoryContext context)
{
var request = context.HttpContext.Request;
@ -19,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return new ReadableStringCollectionValueProvider(
BindingSource.Form,
async () => await request.ReadFormAsync(),
await request.ReadFormAsync(),
culture);
}

View File

@ -2,12 +2,11 @@
// 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
{
Task<IDictionary<string, string>> GetKeysFromPrefixAsync(string prefix);
IDictionary<string, string> GetKeysFromPrefix(string prefix);
}
}

View File

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. 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;
using System.Globalization;
@ -11,15 +10,12 @@ using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
/// <summary>
/// An <see cref="IValueProvider"/> for form data stored in an <see cref="IDictionary{string, string[]}"/> and
/// generally accessed asynchronously.
/// An <see cref="IValueProvider"/> for form data stored in an <see cref="IDictionary{string, string[]}"/>.
/// </summary>
public class JQueryFormValueProvider : BindingSourceValueProvider, IEnumerableValueProvider
{
private readonly Func<Task<IDictionary<string, string[]>>> _valuesFactory;
private PrefixContainer _prefixContainer;
private IDictionary<string, string[]> _values;
private readonly IDictionary<string, string[]> _values;
/// <summary>
/// Initializes a new instance of the <see cref="DictionaryBasedValueProvider"/> class.
@ -28,17 +24,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// <param name="valuesFactory">A delegate which provides the values to wrap.</param>
/// <param name="culture">The culture to return with ValueProviderResult instances.</param>
public JQueryFormValueProvider(
[NotNull] BindingSource bindingSource,
[NotNull] Func<Task<IDictionary<string, string[]>>> valuesFactory,
CultureInfo culture)
: base(bindingSource)
{
_valuesFactory = valuesFactory;
Culture = culture;
}
// Internal for testing.
internal JQueryFormValueProvider(
[NotNull] BindingSource bindingSource,
[NotNull] IDictionary<string, string[]> values,
CultureInfo culture)
@ -51,58 +36,41 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Internal for testing
internal CultureInfo Culture { get; }
/// <inheritdoc />
public override async Task<bool> ContainsPrefixAsync(string prefix)
protected PrefixContainer PrefixContainer
{
var prefixContainer = await GetPrefixContainerAsync();
return prefixContainer.ContainsPrefix(prefix);
get
{
if (_prefixContainer == null)
{
_prefixContainer = new PrefixContainer(_values.Keys);
}
return _prefixContainer;
}
}
/// <inheritdoc />
public async Task<IDictionary<string, string>> GetKeysFromPrefixAsync(string prefix)
public override bool ContainsPrefix(string prefix)
{
var prefixContainer = await GetPrefixContainerAsync();
return prefixContainer.GetKeysFromPrefix(prefix);
return PrefixContainer.ContainsPrefix(prefix);
}
/// <inheritdoc />
public override async Task<ValueProviderResult> GetValueAsync(string key)
public IDictionary<string, string> GetKeysFromPrefix(string prefix)
{
var dictionary = await GetDictionary();
return PrefixContainer.GetKeysFromPrefix(prefix);
}
/// <inheritdoc />
public override ValueProviderResult GetValue(string key)
{
string[] values;
if (dictionary.TryGetValue(key, out values) && values != null && values.Length > 0)
if (_values.TryGetValue(key, out values) && values != null && values.Length > 0)
{
return new ValueProviderResult(values, Culture);
}
return ValueProviderResult.None;
}
private async Task<IDictionary<string, string[]>> GetDictionary()
{
if (_values == null)
{
Debug.Assert(_valuesFactory != null);
// Initialization race is OK providing data remains read-only.
_values = await _valuesFactory();
}
return _values;
}
private async Task<PrefixContainer> GetPrefixContainerAsync()
{
if (_prefixContainer == null)
{
var dictionary = await GetDictionary();
// Initialization race is OK providing data remains read-only and object identity is not significant.
_prefixContainer = new PrefixContainer(dictionary.Keys);
}
return _prefixContainer;
}
}
}

View File

@ -14,7 +14,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
public class JQueryFormValueProviderFactory : IValueProviderFactory
{
public IValueProvider GetValueProvider([NotNull] ValueProviderFactoryContext context)
public async Task<IValueProvider> GetValueProviderAsync([NotNull] ValueProviderFactoryContext context)
{
var request = context.HttpContext.Request;
@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
return new JQueryFormValueProvider(
BindingSource.Form,
() => GetValueCollectionAsync(request),
await GetValueCollectionAsync(request),
CultureInfo.CurrentCulture);
}

View File

@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
PropertyMetadata = GetMetadataForProperties(bindingContext).ToArray(),
};
if (!(await CanCreateModel(mutableObjectBinderContext)))
if (!(CanCreateModel(mutableObjectBinderContext)))
{
return null;
}
@ -72,7 +72,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return CanUpdatePropertyInternal(propertyMetadata);
}
internal async Task<bool> CanCreateModel(MutableObjectBinderContext context)
internal bool CanCreateModel(MutableObjectBinderContext context)
{
var bindingContext = context.ModelBindingContext;
var isTopLevelObject = bindingContext.IsTopLevelObject;
@ -109,7 +109,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
// 3. Any of the model properties can be bound using a value provider.
if (await CanValueBindAnyModelProperties(context))
if (CanValueBindAnyModelProperties(context))
{
return true;
}
@ -117,7 +117,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return false;
}
private async Task<bool> CanValueBindAnyModelProperties(MutableObjectBinderContext context)
private bool CanValueBindAnyModelProperties(MutableObjectBinderContext context)
{
// If there are no properties on the model, there is nothing to bind. We are here means this is not a top
// level object. So we return false.
@ -170,7 +170,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
propertyMetadata);
// If any property can return a true value.
if (await CanBindValue(propertyModelBindingContext))
if (CanBindValue(propertyModelBindingContext))
{
return true;
}
@ -189,7 +189,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return false;
}
private async Task<bool> CanBindValue(ModelBindingContext bindingContext)
private bool CanBindValue(ModelBindingContext bindingContext)
{
var valueProvider = bindingContext.ValueProvider;
@ -209,7 +209,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
if (await valueProvider.ContainsPrefixAsync(bindingContext.ModelName))
if (valueProvider.ContainsPrefix(bindingContext.ModelName))
{
return true;
}

View File

@ -2,6 +2,7 @@
// 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.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
@ -13,12 +14,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public class QueryStringValueProviderFactory : IValueProviderFactory
{
/// <inheritdoc />
public IValueProvider GetValueProvider([NotNull] ValueProviderFactoryContext context)
public Task<IValueProvider> GetValueProviderAsync([NotNull] ValueProviderFactoryContext context)
{
return new ReadableStringCollectionValueProvider(
return Task.FromResult<IValueProvider>(new ReadableStringCollectionValueProvider(
BindingSource.Query,
context.HttpContext.Request.Query,
CultureInfo.InvariantCulture);
CultureInfo.InvariantCulture));
}
}
}

View File

@ -18,7 +18,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public class ReadableStringCollectionValueProvider : BindingSourceValueProvider, IEnumerableValueProvider
{
private readonly CultureInfo _culture;
private readonly Func<Task<IReadableStringCollection>> _valuesFactory;
private PrefixContainer _prefixContainer;
private IReadableStringCollection _values;
@ -38,23 +37,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
_culture = culture;
}
/// <summary>
/// Creates a provider for <see cref="IReadableStringCollection"/> wrapping an
/// existing set of key value pairs provided by the delegate.
/// </summary>
/// <param name="bindingSource">The <see cref="BindingSource"/> for the data.</param>
/// <param name="values">The delegate that provides the key value pairs to wrap.</param>
/// <param name="culture">The culture to return with ValueProviderResult instances.</param>
public ReadableStringCollectionValueProvider(
[NotNull] BindingSource bindingSource,
[NotNull] Func<Task<IReadableStringCollection>> valuesFactory,
CultureInfo culture)
: base(bindingSource)
{
_valuesFactory = valuesFactory;
_culture = culture;
}
public CultureInfo Culture
{
get
@ -63,59 +45,43 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
}
/// <inheritdoc />
public override async Task<bool> ContainsPrefixAsync(string prefix)
protected PrefixContainer PrefixContainer
{
var prefixContainer = await GetPrefixContainerAsync();
return prefixContainer.ContainsPrefix(prefix);
get
{
if (_prefixContainer == null)
{
_prefixContainer = new PrefixContainer(_values.Keys);
}
return _prefixContainer;
}
}
/// <inheritdoc />
public virtual async Task<IDictionary<string, string>> GetKeysFromPrefixAsync([NotNull] string prefix)
public override bool ContainsPrefix(string prefix)
{
var prefixContainer = await GetPrefixContainerAsync();
return prefixContainer.GetKeysFromPrefix(prefix);
return PrefixContainer.ContainsPrefix(prefix);
}
/// <inheritdoc />
public override async Task<ValueProviderResult> GetValueAsync([NotNull] string key)
public virtual IDictionary<string, string> GetKeysFromPrefix([NotNull] string prefix)
{
var collection = await GetValueCollectionAsync();
var values = collection.GetValues(key);
return PrefixContainer.GetKeysFromPrefix(prefix);
}
ValueProviderResult result;
/// <inheritdoc />
public override ValueProviderResult GetValue([NotNull] string key)
{
var values = _values.GetValues(key);
if (values == null)
{
result = ValueProviderResult.None;
return ValueProviderResult.None;
}
else
{
result = new ValueProviderResult(values.ToArray(), _culture);
return new ValueProviderResult(values.ToArray(), _culture);
}
return result;
}
private async Task<IReadableStringCollection> GetValueCollectionAsync()
{
if (_values == null)
{
Debug.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
var collection = await GetValueCollectionAsync();
_prefixContainer = new PrefixContainer(collection.Keys);
}
return _prefixContainer;
}
}
}

View File

@ -1,15 +1,18 @@
// Copyright (c) .NET Foundation. 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;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
public class RouteValueValueProviderFactory : IValueProviderFactory
{
public IValueProvider GetValueProvider([NotNull] ValueProviderFactoryContext context)
public Task<IValueProvider> GetValueProviderAsync([NotNull] ValueProviderFactoryContext context)
{
return new DictionaryBasedValueProvider(BindingSource.Path, context.RouteValues);
return Task.FromResult<IValueProvider>(new DictionaryBasedValueProvider(
BindingSource.Path,
context.RouteValues));
}
}
}

View File

@ -10,7 +10,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
public class SimpleTypeModelBinder : IModelBinder
{
public async Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
{
return Task.FromResult(BindModel(bindingContext));
}
public ModelBindingResult BindModel(ModelBindingContext bindingContext)
{
if (bindingContext.ModelMetadata.IsComplexType)
{
@ -18,7 +23,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return null;
}
var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult == ValueProviderResult.None)
{
// no entry
@ -60,7 +65,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, model) :
null;
return new ModelBindingResult(model, bindingContext.ModelName, isModelSet, validationNode);
return new ModelBindingResult(
model,
bindingContext.ModelName,
isModelSet,
validationNode);
}
catch (Exception ex)
{
@ -69,7 +78,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Were able to find a converter for the type but conversion failed.
// Tell the model binding system to skip other model binders i.e. return non-null.
return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
return new ModelBindingResult(
model: null,
key: bindingContext.ModelName,
isModelSet: false);
}
private static bool AllowsNullValue(Type type)

View File

@ -193,15 +193,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var mockIntBinder = new Mock<IModelBinder>();
mockIntBinder
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(async (ModelBindingContext mbc) =>
.Returns((ModelBindingContext mbc) =>
{
var value = await mbc.ValueProvider.GetValueAsync(mbc.ModelName);
var value = mbc.ValueProvider.GetValue(mbc.ModelName);
if (value != ValueProviderResult.None)
{
var model = value.ConvertTo(mbc.ModelType);
return new ModelBindingResult(model, key: null, isModelSet: true);
return Task.FromResult(new ModelBindingResult(model, key: null, isModelSet: true));
}
return null;
return Task.FromResult<ModelBindingResult>(null);
});
return mockIntBinder.Object;
}

View File

@ -83,12 +83,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
}
public override Task<bool> ContainsPrefixAsync(string prefix)
public override bool ContainsPrefix(string prefix)
{
throw new NotImplementedException();
}
public override Task<ValueProviderResult> GetValueAsync(string key)
public override ValueProviderResult GetValue(string key)
{
throw new NotImplementedException();
}

View File

@ -435,17 +435,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
mockIntBinder
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(async (ModelBindingContext mbc) =>
.Returns((ModelBindingContext mbc) =>
{
var value = await mbc.ValueProvider.GetValueAsync(mbc.ModelName);
var value = mbc.ValueProvider.GetValue(mbc.ModelName);
if (value != ValueProviderResult.None)
{
var model = value.ConvertTo(mbc.ModelType);
var modelValidationNode = new ModelValidationNode(mbc.ModelName, mbc.ModelMetadata, model);
return new ModelBindingResult(model, mbc.ModelName, model != null, modelValidationNode);
return Task.FromResult(new ModelBindingResult(
model,
mbc.ModelName,
model != null,
modelValidationNode));
}
return null;
return Task.FromResult<ModelBindingResult>(null);
});
return mockIntBinder.Object;
}

View File

@ -30,7 +30,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
#if DNX451
[Fact]
public async Task GetKeysFromPrefixAsync_ReturnsResultFromFirstValueProviderThatReturnsValues()
public void GetKeysFromPrefixAsync_ReturnsResultFromFirstValueProviderThatReturnsValues()
{
// Arrange
var provider1 = Mock.Of<IValueProvider>();
@ -39,13 +39,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{ "prefix-test", "some-value" },
};
var provider2 = new Mock<IEnumerableValueProvider>();
provider2.Setup(p => p.GetKeysFromPrefixAsync("prefix"))
.Returns(Task.FromResult<IDictionary<string, string>>(dictionary))
provider2.Setup(p => p.GetKeysFromPrefix("prefix"))
.Returns(dictionary)
.Verifiable();
var provider = new CompositeValueProvider(new[] { provider1, provider2.Object });
// Act
var values = await provider.GetKeysFromPrefixAsync("prefix");
var values = provider.GetKeysFromPrefix("prefix");
// Assert
var result = Assert.Single(values);
@ -55,7 +55,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
[Fact]
public async Task GetKeysFromPrefixAsync_ReturnsEmptyDictionaryIfNoValueProviderReturnsValues()
public void GetKeysFromPrefixAsync_ReturnsEmptyDictionaryIfNoValueProviderReturnsValues()
{
// Arrange
var provider1 = Mock.Of<IValueProvider>();
@ -63,7 +63,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var provider = new CompositeValueProvider(new[] { provider1, provider2 });
// Act
var values = await provider.GetKeysFromPrefixAsync("prefix");
var values = provider.GetKeysFromPrefix("prefix");
// Assert
Assert.Empty(values);

View File

@ -11,7 +11,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public class DictionaryBasedValueProviderTests
{
[Fact]
public async Task GetValueProvider_ReturnsNull_WhenKeyIsNotFound()
public void GetValueProvider_ReturnsNull_WhenKeyIsNotFound()
{
// Arrange
var values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
@ -21,14 +21,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var provider = new DictionaryBasedValueProvider(BindingSource.Query, values);
// Act
var result = await provider.GetValueAsync("not-test-key");
var result = provider.GetValue("not-test-key");
// Assert
Assert.Equal(ValueProviderResult.None, result);
}
[Fact]
public async Task GetValueProvider_ReturnsValue_IfKeyIsPresent()
public void GetValueProvider_ReturnsValue_IfKeyIsPresent()
{
// Arrange
var values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
@ -38,14 +38,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var provider = new DictionaryBasedValueProvider(BindingSource.Query, values);
// Act
var result = await provider.GetValueAsync("test-key");
var result = provider.GetValue("test-key");
// Assert
Assert.Equal("test-value", (string)result);
}
[Fact]
public async Task ContainsPrefixAsync_ReturnsNullValue_IfKeyIsPresent()
public void ContainsPrefix_ReturnsNullValue_IfKeyIsPresent()
{
// Arrange
var values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
@ -55,7 +55,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var provider = new DictionaryBasedValueProvider(BindingSource.Query, values);
// Act
var result = await provider.GetValueAsync("test-key");
var result = provider.GetValue("test-key");
// Assert
Assert.Equal(string.Empty, (string)result);
@ -65,7 +65,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[InlineData("foo")]
[InlineData("bar")]
[InlineData("bar.baz")]
public async Task ContainsPrefixAsync_ReturnsTrue_ForKnownPrefixes(string prefix)
public void ContainsPrefix_ReturnsTrue_ForKnownPrefixes(string prefix)
{
// Arrange
var values = new Dictionary<string, object>
@ -77,7 +77,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var valueProvider = new DictionaryBasedValueProvider(BindingSource.Query, values);
// Act
var result = await valueProvider.ContainsPrefixAsync(prefix);
var result = valueProvider.ContainsPrefix(prefix);
// Assert
Assert.True(result);
@ -86,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[Theory]
[InlineData("bar", "1")]
[InlineData("bar.baz", "2")]
public async Task GetValueAsync_ReturnsCorrectValue_ForKnownKeys(string prefix, string expectedValue)
public void GetValue_ReturnsCorrectValue_ForKnownKeys(string prefix, string expectedValue)
{
// Arrange
var values = new Dictionary<string, object>
@ -98,14 +98,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var valueProvider = new DictionaryBasedValueProvider(BindingSource.Query, values);
// Act
var result = await valueProvider.GetValueAsync(prefix);
var result = valueProvider.GetValue(prefix);
// Assert
Assert.Equal(expectedValue, (string)result);
}
[Fact]
public async Task GetValueAsync_DoesNotReturnAValue_ForAKeyPrefix()
public void GetValue_DoesNotReturnAValue_ForAKeyPrefix()
{
// Arrange
var values = new Dictionary<string, object>
@ -116,14 +116,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var valueProvider = new DictionaryBasedValueProvider(BindingSource.Query, values);
// Act
var result = await valueProvider.GetValueAsync("bar");
var result = valueProvider.GetValue("bar");
// Assert
Assert.Equal(ValueProviderResult.None, result);
}
[Fact]
public async Task ContainsPrefixAsync_ReturnsFalse_IfKeyIsNotPresent()
public void ContainsPrefix_ReturnsFalse_IfKeyIsNotPresent()
{
// Arrange
var values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
@ -133,14 +133,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var provider = new DictionaryBasedValueProvider(BindingSource.Query, values);
// Act
var result = await provider.ContainsPrefixAsync("not-test-key");
var result = provider.ContainsPrefix("not-test-key");
// Assert
Assert.False(result);
}
[Fact]
public async Task ContainsPrefixAsync_ReturnsTrue_IfKeyIsPresent()
public void ContainsPrefix_ReturnsTrue_IfKeyIsPresent()
{
// Arrange
var values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
@ -150,7 +150,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var provider = new DictionaryBasedValueProvider(BindingSource.Query, values);
// Act
var result = await provider.ContainsPrefixAsync("test-key");
var result = provider.ContainsPrefix("test-key");
// Assert
Assert.True(result);

View File

@ -14,8 +14,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[InlineData("MyProperty", "MyProperty")]
[InlineData("MyProperty.SubProperty", "MyProperty")]
[InlineData("MyProperty[0]", "MyProperty")]
public async Task ContainsPrefixAsync_ReturnsTrue_IfElementNameStartsWithPrefix(string elementName,
string prefix)
public void ContainsPrefix_ReturnsTrue_IfElementNameStartsWithPrefix(
string elementName,
string prefix)
{
// Arrange
var culture = new CultureInfo("en-US");
@ -25,7 +26,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
culture);
// Act
var containsPrefix = await elementalValueProvider.ContainsPrefixAsync(prefix);
var containsPrefix = elementalValueProvider.ContainsPrefix(prefix);
// Assert
Assert.True(containsPrefix);
@ -35,8 +36,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[InlineData("MyProperty", "MyProperty1")]
[InlineData("MyPropertyTest", "MyProperty")]
[InlineData("Random", "MyProperty")]
public async Task ContainsPrefixAsync_ReturnsFalse_IfElementCannotSpecifyValuesForPrefix(string elementName,
string prefix)
public void ContainsPrefix_ReturnsFalse_IfElementCannotSpecifyValuesForPrefix(
string elementName,
string prefix)
{
// Arrange
var culture = new CultureInfo("en-US");
@ -46,21 +48,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
culture);
// Act
var containsPrefix = await elementalValueProvider.ContainsPrefixAsync(prefix);
var containsPrefix = elementalValueProvider.ContainsPrefix(prefix);
// Assert
Assert.False(containsPrefix);
}
[Fact]
public async Task GetValueAsync_NameDoesNotMatch_ReturnsEmptyResult()
public void GetValue_NameDoesNotMatch_ReturnsEmptyResult()
{
// Arrange
var culture = new CultureInfo("fr-FR");
var valueProvider = new ElementalValueProvider("foo", "hi", culture);
// Act
var result = await valueProvider.GetValueAsync("bar");
var result = valueProvider.GetValue("bar");
// Assert
Assert.Equal(ValueProviderResult.None, result);
@ -70,14 +72,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[InlineData("foo")]
[InlineData("FOO")]
[InlineData("FoO")]
public async Task GetValueAsync_NameMatches_ReturnsValueProviderResult(string name)
public void GetValue_NameMatches_ReturnsValueProviderResult(string name)
{
// Arrange
var culture = new CultureInfo("fr-FR");
var valueProvider = new ElementalValueProvider("foo", "hi", culture);
// Act
var result = await valueProvider.GetValueAsync(name);
var result = valueProvider.GetValue(name);
// Assert
Assert.NotNull(result);

View File

@ -29,61 +29,62 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
};
[Fact]
public async Task ContainsPrefixAsync_WithEmptyCollection_ReturnsFalseForEmptyPrefix()
public void ContainsPrefix_WithEmptyCollection_ReturnsFalseForEmptyPrefix()
{
// Arrange
var backingStore = new Dictionary<string, string[]>();
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, backingStore, culture: null);
// Act
var result = await valueProvider.ContainsPrefixAsync(string.Empty);
var result = valueProvider.ContainsPrefix(string.Empty);
// Assert
Assert.False(result);
}
[Fact]
public async Task ContainsPrefixAsync_WithNonEmptyCollection_ReturnsTrueForEmptyPrefix()
public void ContainsPrefix_WithNonEmptyCollection_ReturnsTrueForEmptyPrefix()
{
// Arrange
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture: null);
// Act
var result = await valueProvider.ContainsPrefixAsync(string.Empty);
var result = valueProvider.ContainsPrefix(string.Empty);
// Assert
Assert.True(result);
}
[Fact]
public async Task ContainsPrefixAsync_WithNonEmptyCollection_ReturnsTrueForKnownPrefixes()
[Theory]
[InlineData("some")]
[InlineData("prefix")]
[InlineData("prefix.name")]
[InlineData("[index]")]
[InlineData("prefix[index1]")]
public void ContainsPrefix_WithNonEmptyCollection_ReturnsTrueForKnownPrefixes(string prefix)
{
// Arrange
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture: null);
// Act & Assert
Assert.True(await valueProvider.ContainsPrefixAsync("some"));
Assert.True(await valueProvider.ContainsPrefixAsync("prefix"));
Assert.True(await valueProvider.ContainsPrefixAsync("prefix.name"));
Assert.True(await valueProvider.ContainsPrefixAsync("[index]"));
Assert.True(await valueProvider.ContainsPrefixAsync("prefix[index1]"));
Assert.True(valueProvider.ContainsPrefix(prefix));
}
[Fact]
public async Task ContainsPrefixAsync_WithNonEmptyCollection_ReturnsFalseForUnknownPrefix()
public void ContainsPrefix_WithNonEmptyCollection_ReturnsFalseForUnknownPrefix()
{
// Arrange
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture: null);
// Act
var result = await valueProvider.ContainsPrefixAsync("biff");
var result = valueProvider.ContainsPrefix("biff");
// Assert
Assert.False(result);
}
[Fact]
public async Task GetKeysFromPrefixAsync_EmptyPrefix_ReturnsAllPrefixes()
public void GetKeysFromPrefix_EmptyPrefix_ReturnsAllPrefixes()
{
// Arrange
var expected = new Dictionary<string, string>
@ -96,27 +97,27 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture: null);
// Act
var result = await valueProvider.GetKeysFromPrefixAsync(string.Empty);
var result = valueProvider.GetKeysFromPrefix(string.Empty);
// Assert
Assert.Equal(expected, result.OrderBy(kvp => kvp.Key));
}
[Fact]
public async Task GetKeysFromPrefixAsync_UnknownPrefix_ReturnsEmptyDictionary()
public void GetKeysFromPrefix_UnknownPrefix_ReturnsEmptyDictionary()
{
// Arrange
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture: null);
// Act
var result = await valueProvider.GetKeysFromPrefixAsync("abc");
var result = valueProvider.GetKeysFromPrefix("abc");
// Assert
Assert.Empty(result);
}
[Fact]
public async Task GetKeysFromPrefixAsync_KnownPrefix_ReturnsMatchingItems()
public void GetKeysFromPrefix_KnownPrefix_ReturnsMatchingItems()
{
// Arrange
var expected = new Dictionary<string, string>
@ -131,14 +132,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture: null);
// Act
var result = await valueProvider.GetKeysFromPrefixAsync("prefix");
var result = valueProvider.GetKeysFromPrefix("prefix");
// Assert
Assert.Equal(expected, result);
}
[Fact]
public async Task GetKeysFromPrefixAsync_IndexPrefix_ReturnsMatchingItems()
public void GetKeysFromPrefix_IndexPrefix_ReturnsMatchingItems()
{
// Arrange
var expected = new Dictionary<string, string>
@ -149,21 +150,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture: null);
// Act
var result = await valueProvider.GetKeysFromPrefixAsync("[index]");
var result = valueProvider.GetKeysFromPrefix("[index]");
// Assert
Assert.Equal(expected, result);
}
[Fact]
public async Task GetValueAsync_SingleValue()
public void GetValue_SingleValue()
{
// Arrange
var culture = new CultureInfo("fr-FR");
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture);
// Act
var result = await valueProvider.GetValueAsync("prefix.name");
var result = valueProvider.GetValue("prefix.name");
// Assert
Assert.NotNull(result);
@ -172,14 +173,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
[Fact]
public async Task GetValueAsync_MultiValue()
public void GetValue_MultiValue()
{
// Arrange
var culture = new CultureInfo("fr-FR");
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture);
// Act
var result = await valueProvider.GetValueAsync("some");
var result = valueProvider.GetValue("some");
// Assert
Assert.NotNull(result);
@ -191,21 +192,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[Theory]
[InlineData("null_value")]
[InlineData("prefix.null_value")]
public async Task GetValue_NullValue(string key)
public void GetValue_NullValue(string key)
{
// Arrange
var culture = new CultureInfo("fr-FR");
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture);
// Act
var result = await valueProvider.GetValueAsync(key);
var result = valueProvider.GetValue(key);
// Assert
Assert.Equal(ValueProviderResult.None, result);
}
[Fact]
public async Task GetValueAsync_NullMultipleValue()
public void GetValue_NullMultipleValue()
{
// Arrange
var backingStore = new Dictionary<string, string[]>
@ -216,7 +217,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, backingStore, culture);
// Act
var result = await valueProvider.GetValueAsync("key");
var result = valueProvider.GetValue("key");
// Assert
Assert.Equal(new[] { null, null, "value" }, result.Values);
@ -224,13 +225,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
[Fact]
public async Task GetValueAsync_ReturnsNullIfKeyNotFound()
public void GetValue_ReturnsNullIfKeyNotFound()
{
// Arrange
var valueProvider = GetEnumerableValueProvider(BindingSource.Query, _backingStore, culture: null);
// Act
var result = await valueProvider.GetValueAsync("prefix");
var result = valueProvider.GetValue("prefix");
// Assert
Assert.Equal(ValueProviderResult.None, result);

View File

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNet.Http.Internal;
using Xunit;
@ -12,14 +13,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public class FormValueProviderFactoryTest
{
[Fact]
public void GetValueProvider_ReturnsNull_WhenContentTypeIsNotFormUrlEncoded()
public async Task GetValueProviderAsync_ReturnsNull_WhenContentTypeIsNotFormUrlEncoded()
{
// Arrange
var context = CreateContext("some-content-type");
var factory = new FormValueProviderFactory();
// Act
var result = factory.GetValueProvider(context);
var result = await factory.GetValueProviderAsync(context);
// Assert
Assert.Null(result);
@ -30,14 +31,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
[InlineData("application/x-www-form-urlencoded;charset=utf-8")]
[InlineData("multipart/form-data; boundary=----WebKitFormBoundarymx2fSWqWSd0OxQqq")]
[InlineData("multipart/form-data; boundary=----WebKitFormBoundarymx2fSWqWSd0OxQqq; charset=utf-8")]
public void GetValueProvider_ReturnsValueProviderInstanceWithCurrentCulture(string contentType)
public async Task GetValueProviderAsync_ReturnsValueProvider_WithCurrentCulture(string contentType)
{
// Arrange
var context = CreateContext(contentType);
var factory = new FormValueProviderFactory();
// Act
var result = factory.GetValueProvider(context);
var result = await factory.GetValueProviderAsync(context);
// Assert
var valueProvider = Assert.IsType<ReadableStringCollectionValueProvider>(result);
@ -49,6 +50,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var context = new DefaultHttpContext();
context.Request.ContentType = contentType;
if (context.Request.HasFormContentType)
{
context.Request.Form = new FormCollection(new Dictionary<string, string[]>());
}
return new ValueProviderFactoryContext(
context,
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase));

View File

@ -37,14 +37,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
};
[Fact]
public void GetValueProvider_ReturnsNull_WhenContentTypeIsNotFormUrlEncoded()
public async Task GetValueProvider_ReturnsNull_WhenContentTypeIsNotFormUrlEncoded()
{
// Arrange
var context = CreateContext("some-content-type", formValues: null);
var factory = new JQueryFormValueProviderFactory();
// Act
var result = factory.GetValueProvider(context);
var result = await factory.GetValueProviderAsync(context);
// Assert
Assert.Null(result);
@ -55,14 +55,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
[InlineData("application/x-www-form-urlencoded;charset=utf-8")]
[InlineData("multipart/form-data; boundary=----WebKitFormBoundarymx2fSWqWSd0OxQqq")]
[InlineData("multipart/form-data; boundary=----WebKitFormBoundarymx2fSWqWSd0OxQqq; charset=utf-8")]
public void GetValueProvider_ReturnsExpectedValueProviderInstanceWithCurrentCulture(string contentType)
public async Task GetValueProviderAsync_ReturnsValueProvider_WithCurrentCulture(string contentType)
{
// Arrange
var context = CreateContext(contentType, formValues: null);
var factory = new JQueryFormValueProviderFactory();
// Act
var result = factory.GetValueProvider(context);
var result = await factory.GetValueProviderAsync(context);
// Assert
var valueProvider = Assert.IsType<JQueryFormValueProvider>(result);
@ -106,8 +106,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var factory = new JQueryFormValueProviderFactory();
// Act
var valueProvider = factory.GetValueProvider(context);
var result = await valueProvider.GetValueAsync(key);
var valueProvider = await factory.GetValueProviderAsync(context);
var result = valueProvider.GetValue(key);
// Assert
Assert.Equal("found", (string)result);
@ -119,9 +119,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
var context = new DefaultHttpContext();
context.Request.ContentType = contentType;
if (formValues != null)
if (context.Request.HasFormContentType)
{
context.Request.Form = new FormCollection(formValues);
context.Request.Form = new FormCollection(formValues ?? new Dictionary<string, string[]>());
}
return new ValueProviderFactoryContext(

View File

@ -36,7 +36,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[InlineData(true, false, "prefix", "dummyModelName", true)]
[InlineData(false, true, "prefix", "dummyModelName", false)]
[InlineData(false, false, "prefix", "dummyModelName", false)]
public async Task CanCreateModel_ReturnsTrue_IfIsTopLevelObjectAndNotIsFirstChanceBinding(
public void CanCreateModel_ReturnsTrue_IfIsTopLevelObjectAndNotIsFirstChanceBinding(
bool isTopLevelObject,
bool isFirstChanceBinding,
string binderModelName,
@ -45,8 +45,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
var mockValueProvider = new Mock<IValueProvider>();
mockValueProvider
.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(Task.FromResult(false));
.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
.Returns(false);
var metadataProvider = new TestModelMetadataProvider();
var bindingContext = new MutableObjectBinderContext
@ -77,14 +77,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray();
// Act
var canCreate = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
Assert.Equal(expectedCanCreate, canCreate);
}
[Fact]
public async Task CanCreateModel_ReturnsFalse_IfNotIsTopLevelObjectAndModelIsMarkedWithBinderMetadata()
public void CanCreateModel_ReturnsFalse_IfNotIsTopLevelObjectAndModelIsMarkedWithBinderMetadata()
{
// Get the property metadata so that it is not a top level object.
var modelMetadata = GetMetadataForType(typeof(Document))
@ -107,14 +107,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var mutableBinder = new MutableObjectModelBinder();
// Act
var canCreate = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
Assert.False(canCreate);
}
[Fact]
public async Task CanCreateModel_ReturnsTrue_IfIsTopLevelObjectAndModelIsMarkedWithBinderMetadata()
public void CanCreateModel_ReturnsTrue_IfIsTopLevelObjectAndModelIsMarkedWithBinderMetadata()
{
var bindingContext = new MutableObjectBinderContext
{
@ -134,18 +134,19 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var mutableBinder = new MutableObjectModelBinder();
// Act
var canCreate = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
Assert.True(canCreate);
}
[Fact]
public async Task CanCreateModel_CreatesModel_IfTheModelIsBinderPoco()
public void CanCreateModel_CreatesModel_IfTheModelIsBinderPoco()
{
var mockValueProvider = new Mock<IValueProvider>();
mockValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(Task.FromResult(false));
mockValueProvider
.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
.Returns(false);
var bindingContext = new MutableObjectBinderContext
{
@ -170,23 +171,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray();
// Act
var retModel = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
Assert.True(retModel);
Assert.True(canCreate);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task CanCreateModel_ReturnsTrue_IfNotIsTopLevelObject_BasedOnValueAvailability(
public void CanCreateModel_ReturnsTrue_IfNotIsTopLevelObject_BasedOnValueAvailability(
bool valueAvailable)
{
// Arrange
var mockValueProvider = new Mock<IValueProvider>(MockBehavior.Strict);
mockValueProvider
.Setup(provider => provider.ContainsPrefixAsync("SimpleContainer.Simple.Name"))
.Returns(Task.FromResult(valueAvailable));
.Setup(provider => provider.ContainsPrefix("SimpleContainer.Simple.Name"))
.Returns(valueAvailable);
var typeMetadata = GetMetadataForType(typeof(SimpleContainer));
var modelMetadata = typeMetadata.Properties[nameof(SimpleContainer.Simple)];
@ -210,15 +211,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var mutableBinder = new MutableObjectModelBinder();
// Act
var result = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
// Result matches whether first Simple property can bind.
Assert.Equal(valueAvailable, result);
Assert.Equal(valueAvailable, canCreate);
}
[Fact]
public async Task CanCreateModel_ReturnsFalse_IfNotIsTopLevelObjectAndModelHasNoProperties()
public void CanCreateModel_ReturnsFalse_IfNotIsTopLevelObjectAndModelHasNoProperties()
{
// Arrange
var bindingContext = new MutableObjectBinderContext
@ -236,14 +237,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray();
// Act
var canCreate = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
Assert.False(canCreate);
}
[Fact]
public async Task CanCreateModel_ReturnsTrue_IfIsTopLevelObjectAndModelHasNoProperties()
public void CanCreateModel_ReturnsTrue_IfIsTopLevelObjectAndModelHasNoProperties()
{
// Arrange
var bindingContext = new MutableObjectBinderContext
@ -260,10 +261,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray();
// Act
var retModel = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
Assert.True(retModel);
Assert.True(canCreate);
}
[Theory]
@ -273,13 +274,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[InlineData(typeof(TypeWithAtLeastOnePropertyMarkedUsingValueBinderMetadata), true)]
[InlineData(typeof(TypeWithUnmarkedAndBinderMetadataMarkedProperties), false)]
[InlineData(typeof(TypeWithUnmarkedAndBinderMetadataMarkedProperties), true)]
public async Task
CanCreateModel_CreatesModelForValueProviderBasedBinderMetadatas_IfAValueProviderProvidesValue
(Type modelType, bool valueProviderProvidesValue)
public void CanCreateModel_CreatesModelForValueProviderBasedBinderMetadatas_IfAValueProviderProvidesValue(
Type modelType,
bool valueProviderProvidesValue)
{
var mockValueProvider = new Mock<IValueProvider>();
mockValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(Task.FromResult(valueProviderProvidesValue));
mockValueProvider.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
.Returns(valueProviderProvidesValue);
var bindingContext = new MutableObjectBinderContext
{
@ -303,27 +304,28 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray();
// Act
var retModel = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
Assert.Equal(valueProviderProvidesValue, retModel);
Assert.Equal(valueProviderProvidesValue, canCreate);
}
[Theory]
[InlineData(typeof(TypeWithAtLeastOnePropertyMarkedUsingValueBinderMetadata), false)]
[InlineData(typeof(TypeWithAtLeastOnePropertyMarkedUsingValueBinderMetadata), true)]
public async Task CanCreateModel_ForExplicitValueProviderMetadata_UsesOriginalValueProvider(
public void CanCreateModel_ForExplicitValueProviderMetadata_UsesOriginalValueProvider(
Type modelType,
bool originalValueProviderProvidesValue)
{
var mockValueProvider = new Mock<IValueProvider>();
mockValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(Task.FromResult(false));
mockValueProvider
.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
.Returns(false);
var mockOriginalValueProvider = new Mock<IBindingSourceValueProvider>();
mockOriginalValueProvider
.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(Task.FromResult(originalValueProviderProvidesValue));
.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
.Returns(originalValueProviderProvidesValue);
mockOriginalValueProvider
.Setup(o => o.Filter(It.IsAny<BindingSource>()))
@ -363,10 +365,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray();
// Act
var retModel = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
Assert.Equal(originalValueProviderProvidesValue, retModel);
Assert.Equal(originalValueProviderProvidesValue, canCreate);
}
[Theory]
@ -374,17 +376,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[InlineData(typeof(TypeWithUnmarkedAndBinderMetadataMarkedProperties), true)]
[InlineData(typeof(TypeWithNoBinderMetadata), false)]
[InlineData(typeof(TypeWithNoBinderMetadata), true)]
public async Task CanCreateModel_UnmarkedProperties_UsesCurrentValueProvider(
public void CanCreateModel_UnmarkedProperties_UsesCurrentValueProvider(
Type modelType,
bool valueProviderProvidesValue)
{
var mockValueProvider = new Mock<IValueProvider>();
mockValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(Task.FromResult(valueProviderProvidesValue));
mockValueProvider.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
.Returns(valueProviderProvidesValue);
var mockOriginalValueProvider = new Mock<IValueProvider>();
mockOriginalValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(Task.FromResult(false));
mockOriginalValueProvider.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
.Returns(false);
var bindingContext = new MutableObjectBinderContext
{
@ -408,10 +410,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
mutableBinder.GetMetadataForProperties(bindingContext.ModelBindingContext).ToArray();
// Act
var retModel = await mutableBinder.CanCreateModel(bindingContext);
var canCreate = mutableBinder.CanCreateModel(bindingContext);
// Assert
Assert.Equal(valueProviderProvidesValue, retModel);
Assert.Equal(valueProviderProvidesValue, canCreate);
}
[Fact]
@ -420,8 +422,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var mockValueProvider = new Mock<IValueProvider>();
mockValueProvider
.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(Task.FromResult(true));
.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
.Returns(true);
// Mock binder fails to bind all properties.
var mockBinder = new Mock<IModelBinder>();
@ -470,8 +472,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var mockValueProvider = new Mock<IValueProvider>();
mockValueProvider
.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(Task.FromResult(false));
.Setup(o => o.ContainsPrefix(It.IsAny<string>()))
.Returns(false);
// Mock binder fails to bind all properties.
var mockBinder = new Mock<IModelBinder>();
@ -567,10 +569,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var testableBinder = new TestableMutableObjectModelBinder();
// Act
var retModel = testableBinder.CreateModelPublic(bindingContext);
var model = testableBinder.CreateModelPublic(bindingContext);
// Assert
Assert.IsType<Person>(retModel);
Assert.IsType<Person>(model);
}
[Fact]

View File

@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Moq;
using Xunit;
@ -18,7 +19,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
#if DNX451
[Fact]
public void GetValueProvider_ReturnsQueryStringValueProviderInstanceWithInvariantCulture()
public async Task GetValueProvider_ReturnsQueryStringValueProviderInstanceWithInvariantCulture()
{
// Arrange
var request = new Mock<HttpRequest>();
@ -31,7 +32,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase));
// Act
var result = _factory.GetValueProvider(factoryContext);
var result = await _factory.GetValueProviderAsync(factoryContext);
// Assert
var valueProvider = Assert.IsType<ReadableStringCollectionValueProvider>(result);

View File

@ -23,44 +23,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
_culture = culture ?? CultureInfo.InvariantCulture;
}
// copied from ValueProviderUtil
public Task<bool> ContainsPrefixAsync(string prefix)
public bool ContainsPrefix(string prefix)
{
foreach (string key in Keys)
{
if (key != null)
if (PrefixContainer.IsPrefixMatch(prefix, key))
{
if (prefix.Length == 0)
{
return Task.FromResult(true); // shortcut - non-null key matches empty prefix
}
if (key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{
if (key.Length == prefix.Length)
{
return Task.FromResult(true); // exact match
}
else
{
switch (key[prefix.Length])
{
case '.': // known separator characters
case '[':
return Task.FromResult(true);
}
}
}
return true;
}
}
return Task.FromResult(false); // nothing found
return false;
}
public Task<ValueProviderResult> GetValueAsync(string key)
public ValueProviderResult GetValue(string key)
{
ValueProviderResult result = ValueProviderResult.None;
object rawValue;
if (TryGetValue(key, out rawValue))
{
@ -74,16 +51,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
stringValues[i] = array.GetValue(i) as string ?? Convert.ToString(array.GetValue(i), _culture);
}
result = new ValueProviderResult(stringValues, _culture);
return new ValueProviderResult(stringValues, _culture);
}
else
{
var stringValue = rawValue as string ?? Convert.ToString(rawValue, _culture) ?? string.Empty;
result = new ValueProviderResult(stringValue, _culture);
return new ValueProviderResult(stringValue, _culture);
}
}
return Task.FromResult(result);
return ValueProviderResult.None;
}
}
}

View File

@ -97,9 +97,9 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
actionContext.HttpContext,
actionContext.RouteData.Values);
var valueProvider = CompositeValueProvider.Create(
var valueProvider = CompositeValueProvider.CreateAsync(
options.ValueProviderFactories,
valueProviderFactoryContext);
valueProviderFactoryContext).Result;
return new ActionBindingContext()
{

View File

@ -85,7 +85,7 @@ namespace ModelBindingWebSite.Controllers
private class ProductModelBinder : IModelBinder
{
public async Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
public Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
{
if (typeof(Product).IsAssignableFrom(bindingContext.ModelType))
{
@ -97,16 +97,16 @@ namespace ModelBindingWebSite.Controllers
string.IsNullOrEmpty(bindingContext.ModelName) ?
"productId" :
bindingContext.ModelName + "." + "productId";
var value = await bindingContext.ValueProvider.GetValueAsync(key);
var value = bindingContext.ValueProvider.GetValue(key);
model.ProductId = value.ConvertTo<int>();
var validationNode =
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value);
return new ModelBindingResult(model, key, true, validationNode);
return Task.FromResult(new ModelBindingResult(model, key, true, validationNode));
}
return null;
return Task.FromResult<ModelBindingResult>(null);
}
}
}

View File

@ -211,14 +211,14 @@ namespace ModelBindingWebSite.Controllers
public class CustomValueProvider : IValueProvider
{
public Task<bool> ContainsPrefixAsync(string prefix)
public bool ContainsPrefix(string prefix)
{
return Task.FromResult(false);
return false;
}
public Task<ValueProviderResult> GetValueAsync(string key)
public ValueProviderResult GetValue(string key)
{
return Task.FromResult<ValueProviderResult>(ValueProviderResult.None);
return ValueProviderResult.None;
}
}
}

View File

@ -10,29 +10,27 @@ namespace ValueProvidersWebSite
{
public class CustomValueProviderFactory : IValueProviderFactory
{
public IValueProvider GetValueProvider(ValueProviderFactoryContext context)
public Task<IValueProvider> GetValueProviderAsync(ValueProviderFactoryContext context)
{
if (context.HttpContext.Request.Path.Value.Contains("TestValueProvider"))
{
return new CustomValueProvider();
return Task.FromResult<IValueProvider>(new CustomValueProvider());
}
return null;
return Task.FromResult<IValueProvider>(null);
}
private class CustomValueProvider : IValueProvider
{
public Task<bool> ContainsPrefixAsync(string prefix)
public bool ContainsPrefix(string prefix)
{
var result = string.Equals(prefix, "test", StringComparison.OrdinalIgnoreCase);
return Task.FromResult(result);
return string.Equals(prefix, "test", StringComparison.OrdinalIgnoreCase);
}
public Task<ValueProviderResult> GetValueAsync(string key)
public ValueProviderResult GetValue(string key)
{
var value = "custom-value-provider-value";
var result = new ValueProviderResult(value, CultureInfo.CurrentCulture);
return Task.FromResult(result);
return new ValueProviderResult(value, CultureInfo.CurrentCulture);
}
}
}