Make IModelBinder and IValueProvider methods async

This commit is contained in:
Pranav K 2014-04-24 06:45:53 -07:00
parent d46389888d
commit b0c7dc9220
26 changed files with 251 additions and 288 deletions

View File

@ -78,7 +78,7 @@ namespace Microsoft.AspNet.Mvc
foreach (var parameter in action.Parameters.Where(p => p.ParameterBindingInfo != null)) foreach (var parameter in action.Parameters.Where(p => p.ParameterBindingInfo != null))
{ {
if (actionBindingContext.ValueProvider.ContainsPrefix(parameter.ParameterBindingInfo.Prefix)) if (await actionBindingContext.ValueProvider.ContainsPrefixAsync(parameter.ParameterBindingInfo.Prefix))
{ {
candidate.FoundParameters++; candidate.FoundParameters++;
if (parameter.IsOptional) if (parameter.IsOptional)

View File

@ -278,7 +278,7 @@ namespace Microsoft.AspNet.Mvc
HttpContext = actionBindingContext.ActionContext.HttpContext, HttpContext = actionBindingContext.ActionContext.HttpContext,
FallbackToEmptyPrefix = true FallbackToEmptyPrefix = true
}; };
actionBindingContext.ModelBinder.BindModel(modelBindingContext); await actionBindingContext.ModelBinder.BindModelAsync(modelBindingContext);
parameterValues[parameter.Name] = modelBindingContext.Model; parameterValues[parameter.Name] = modelBindingContext.Model;
} }
} }

View File

@ -1,18 +1,19 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public class ArrayModelBinder<TElement> : CollectionModelBinder<TElement> public class ArrayModelBinder<TElement> : CollectionModelBinder<TElement>
{ {
public override bool BindModel(ModelBindingContext bindingContext) public override Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{ {
if (bindingContext.ModelMetadata.IsReadOnly) if (bindingContext.ModelMetadata.IsReadOnly)
{ {
return false; return Task.FromResult(false);
} }
return base.BindModel(bindingContext); return base.BindModelAsync(bindingContext);
} }
protected override bool CreateOrReplaceCollection(ModelBindingContext bindingContext, IList<TElement> newCollection) protected override bool CreateOrReplaceCollection(ModelBindingContext bindingContext, IList<TElement> newCollection)

View File

@ -3,36 +3,36 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal; using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public class CollectionModelBinder<TElement> : IModelBinder public class CollectionModelBinder<TElement> : IModelBinder
{ {
public virtual bool BindModel(ModelBindingContext bindingContext) public virtual async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{ {
ModelBindingHelper.ValidateBindingContext(bindingContext); ModelBindingHelper.ValidateBindingContext(bindingContext);
if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) if (!await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
{ {
return false; return false;
} }
ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
List<TElement> boundCollection = (valueProviderResult != null) var boundCollection = await ((valueProviderResult != null) ?
? BindSimpleCollection(bindingContext, valueProviderResult.RawValue, valueProviderResult.Culture) BindSimpleCollection(bindingContext, valueProviderResult.RawValue, valueProviderResult.Culture) :
: BindComplexCollection(bindingContext); BindComplexCollection(bindingContext));
bool retVal = CreateOrReplaceCollection(bindingContext, boundCollection); return CreateOrReplaceCollection(bindingContext, boundCollection);
return retVal;
} }
// TODO: Make this method internal // TODO: Make this method internal
// Used when the ValueProvider contains the collection to be bound as a single element, e.g. the raw value // Used when the ValueProvider contains the collection to be bound as a single element, e.g. the raw value
// is [ "1", "2" ] and needs to be converted to an int[]. // is [ "1", "2" ] and needs to be converted to an int[].
public List<TElement> BindSimpleCollection(ModelBindingContext bindingContext, public async Task<List<TElement>> BindSimpleCollection(ModelBindingContext bindingContext,
object rawValue, object rawValue,
CultureInfo culture) CultureInfo culture)
{ {
if (rawValue == null) if (rawValue == null)
{ {
@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}; };
object boundValue = null; object boundValue = null;
if (bindingContext.ModelBinder.BindModel(innerBindingContext)) if (await bindingContext.ModelBinder.BindModelAsync(innerBindingContext))
{ {
boundValue = innerBindingContext.Model; boundValue = innerBindingContext.Model;
bindingContext.ValidationNode.ChildNodes.Add(innerBindingContext.ValidationNode); bindingContext.ValidationNode.ChildNodes.Add(innerBindingContext.ValidationNode);
@ -69,17 +69,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
} }
// Used when the ValueProvider contains the collection to be bound as multiple elements, e.g. foo[0], foo[1]. // Used when the ValueProvider contains the collection to be bound as multiple elements, e.g. foo[0], foo[1].
private List<TElement> BindComplexCollection(ModelBindingContext bindingContext) private async Task<List<TElement>> BindComplexCollection(ModelBindingContext bindingContext)
{ {
string indexPropertyName = ModelBindingHelper.CreatePropertyModelName(bindingContext.ModelName, "index"); string indexPropertyName = ModelBindingHelper.CreatePropertyModelName(bindingContext.ModelName, "index");
ValueProviderResult valueProviderResultIndex = bindingContext.ValueProvider.GetValue(indexPropertyName); ValueProviderResult valueProviderResultIndex = await bindingContext.ValueProvider.GetValueAsync(indexPropertyName);
IEnumerable<string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(valueProviderResultIndex); IEnumerable<string> indexNames = CollectionModelBinderUtil.GetIndexNamesFromValueProviderResult(valueProviderResultIndex);
return BindComplexCollectionFromIndexes(bindingContext, indexNames); return await BindComplexCollectionFromIndexes(bindingContext, indexNames);
} }
// TODO: Convert to internal // TODO: Convert to internal
public List<TElement> BindComplexCollectionFromIndexes(ModelBindingContext bindingContext, public async Task<List<TElement>> BindComplexCollectionFromIndexes(ModelBindingContext bindingContext,
IEnumerable<string> indexNames) IEnumerable<string> indexNames)
{ {
bool indexNamesIsFinite; bool indexNamesIsFinite;
if (indexNames != null) if (indexNames != null)
@ -108,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Type modelType = bindingContext.ModelType; Type modelType = bindingContext.ModelType;
if (bindingContext.ModelBinder.BindModel(childBindingContext)) if (await bindingContext.ModelBinder.BindModelAsync(childBindingContext))
{ {
didBind = true; didBind = true;
boundValue = childBindingContext.Model; boundValue = childBindingContext.Model;

View File

@ -1,10 +1,11 @@
using Microsoft.AspNet.Mvc.ModelBinding.Internal; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public sealed class ComplexModelDtoModelBinder : IModelBinder public sealed class ComplexModelDtoModelBinder : IModelBinder
{ {
public bool BindModel(ModelBindingContext bindingContext) public async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{ {
if (bindingContext.ModelType == typeof(ComplexModelDto)) if (bindingContext.ModelType == typeof(ComplexModelDto))
{ {
@ -21,8 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// bind and propagate the values // bind and propagate the values
// If we can't bind, then leave the result missing (don't add a null). // If we can't bind, then leave the result missing (don't add a null).
if (await bindingContext.ModelBinder.BindModelAsync(propertyBindingContext))
if (bindingContext.ModelBinder.BindModel(propertyBindingContext))
{ {
dto.Results[propertyMetadata] = new ComplexModelDtoResult(propertyBindingContext.Model, propertyBindingContext.ValidationNode); dto.Results[propertyMetadata] = new ComplexModelDtoResult(propertyBindingContext.Model, propertyBindingContext.ValidationNode);
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
@ -26,13 +27,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
private IModelBinder[] Binders { get; set; } private IModelBinder[] Binders { get; set; }
public virtual bool BindModel(ModelBindingContext bindingContext) public virtual async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{ {
var newBindingContext = CreateNewBindingContext(bindingContext, var newBindingContext = CreateNewBindingContext(bindingContext,
bindingContext.ModelName, bindingContext.ModelName,
reuseValidationNode: true); reuseValidationNode: true);
bool boundSuccessfully = TryBind(newBindingContext); var boundSuccessfully = await TryBind(newBindingContext);
if (!boundSuccessfully && !string.IsNullOrEmpty(bindingContext.ModelName) if (!boundSuccessfully && !string.IsNullOrEmpty(bindingContext.ModelName)
&& bindingContext.FallbackToEmptyPrefix) && bindingContext.FallbackToEmptyPrefix)
{ {
@ -40,7 +41,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
newBindingContext = CreateNewBindingContext(bindingContext, newBindingContext = CreateNewBindingContext(bindingContext,
modelName: string.Empty, modelName: string.Empty,
reuseValidationNode: false); reuseValidationNode: false);
boundSuccessfully = TryBind(newBindingContext); boundSuccessfully = await TryBind(newBindingContext);
} }
if (!boundSuccessfully) if (!boundSuccessfully)
@ -68,7 +69,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return true; return true;
} }
private bool TryBind([NotNull] ModelBindingContext bindingContext) private async Task<bool> TryBind([NotNull] ModelBindingContext bindingContext)
{ {
// TODO: RuntimeHelpers.EnsureSufficientExecutionStack does not exist in the CoreCLR. // TODO: RuntimeHelpers.EnsureSufficientExecutionStack does not exist in the CoreCLR.
// Protects against stack overflow for deeply nested model binding // Protects against stack overflow for deeply nested model binding
@ -76,7 +77,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
foreach (var binder in Binders) foreach (var binder in Binders)
{ {
if (binder.BindModel(bindingContext)) if (await binder.BindModelAsync(bindingContext))
{ {
return true; return true;
} }

View File

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Contracts; using System.Diagnostics.Contracts;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.DependencyInjection; using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.ModelBinding.Internal; using Microsoft.AspNet.Mvc.ModelBinding.Internal;
@ -18,16 +19,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
_activator = activator; _activator = activator;
} }
public bool BindModel(ModelBindingContext bindingContext) public Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{ {
Type binderType = ResolveBinderType(bindingContext.ModelType); Type binderType = ResolveBinderType(bindingContext.ModelType);
if (binderType != null) if (binderType != null)
{ {
var binder = (IModelBinder)_activator.CreateInstance(_serviceProvider, binderType); var binder = (IModelBinder)_activator.CreateInstance(_serviceProvider, binderType);
return binder.BindModel(bindingContext); return binder.BindModelAsync(bindingContext);
} }
return false; return Task.FromResult(false);
} }
private static Type ResolveBinderType(Type modelType) private static Type ResolveBinderType(Type modelType)

View File

@ -1,4 +1,4 @@
using Microsoft.AspNet.Abstractions; using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
@ -7,6 +7,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// </summary> /// </summary>
public interface IModelBinder public interface IModelBinder
{ {
bool BindModel(ModelBindingContext bindingContext); Task<bool> BindModelAsync(ModelBindingContext bindingContext);
} }
} }

View File

@ -1,31 +1,28 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal; using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public sealed class KeyValuePairModelBinder<TKey, TValue> : IModelBinder public sealed class KeyValuePairModelBinder<TKey, TValue> : IModelBinder
{ {
public bool BindModel(ModelBindingContext bindingContext) public async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{ {
ModelBindingHelper.ValidateBindingContext(bindingContext, typeof(KeyValuePair<TKey, TValue>), allowNullModel: true); ModelBindingHelper.ValidateBindingContext(bindingContext, typeof(KeyValuePair<TKey, TValue>), allowNullModel: true);
TKey key; var keyResult = await TryBindStrongModel<TKey>(bindingContext, "key");
bool keyBindingSucceeded = TryBindStrongModel(bindingContext, "key", out key); var valueResult = await TryBindStrongModel<TValue>(bindingContext, "value");
TValue value; if (keyResult.Success && valueResult.Success)
bool valueBindingSucceeded = TryBindStrongModel(bindingContext, "value", out value);
if (keyBindingSucceeded && valueBindingSucceeded)
{ {
bindingContext.Model = new KeyValuePair<TKey, TValue>(key, value); bindingContext.Model = new KeyValuePair<TKey, TValue>(keyResult.Model, valueResult.Model);
} }
return keyBindingSucceeded || valueBindingSucceeded; return keyResult.Success || valueResult.Success;
} }
// TODO: Make this internal internal async Task<BindResult<TModel>> TryBindStrongModel<TModel>(ModelBindingContext parentBindingContext,
public bool TryBindStrongModel<TModel>(ModelBindingContext parentBindingContext, string propertyName)
string propertyName,
out TModel model)
{ {
ModelBindingContext propertyBindingContext = new ModelBindingContext(parentBindingContext) ModelBindingContext propertyBindingContext = new ModelBindingContext(parentBindingContext)
{ {
@ -33,16 +30,28 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ModelName = ModelBindingHelper.CreatePropertyModelName(parentBindingContext.ModelName, propertyName) ModelName = ModelBindingHelper.CreatePropertyModelName(parentBindingContext.ModelName, propertyName)
}; };
if (propertyBindingContext.ModelBinder.BindModel(propertyBindingContext)) if (await propertyBindingContext.ModelBinder.BindModelAsync(propertyBindingContext))
{ {
object untypedModel = propertyBindingContext.Model; object untypedModel = propertyBindingContext.Model;
model = ModelBindingHelper.CastOrDefault<TModel>(untypedModel); var model = ModelBindingHelper.CastOrDefault<TModel>(untypedModel);
parentBindingContext.ValidationNode.ChildNodes.Add(propertyBindingContext.ValidationNode); parentBindingContext.ValidationNode.ChildNodes.Add(propertyBindingContext.ValidationNode);
return true; return new BindResult<TModel>(true, model);
} }
model = default(TModel); return new BindResult<TModel>(false, default(TModel));
return false; }
internal sealed class BindResult<TModel>
{
public BindResult(bool success, TModel model)
{
Success = success;
Model = model;
}
public bool Success { get; private set; }
public TModel Model { get; private set; }
} }
} }
} }

View File

@ -4,18 +4,19 @@ using System.ComponentModel;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal; using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public class MutableObjectModelBinder : IModelBinder public class MutableObjectModelBinder : IModelBinder
{ {
public virtual bool BindModel(ModelBindingContext bindingContext) public virtual async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{ {
ModelBindingHelper.ValidateBindingContext(bindingContext); ModelBindingHelper.ValidateBindingContext(bindingContext);
if (!CanBindType(bindingContext.ModelType) || if (!CanBindType(bindingContext.ModelType) ||
!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) !await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
{ {
return false; return false;
} }
@ -94,7 +95,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ModelName = bindingContext.ModelName ModelName = bindingContext.ModelName
}; };
bindingContext.ModelBinder.BindModel(dtoBindingContext); bindingContext.ModelBinder.BindModelAsync(dtoBindingContext);
return (ComplexModelDto)dtoBindingContext.Model; return (ComplexModelDto)dtoBindingContext.Model;
} }

View File

@ -1,15 +1,13 @@
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts; using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal; using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public sealed class TypeConverterModelBinder : IModelBinder public sealed class TypeConverterModelBinder : IModelBinder
{ {
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception is recorded to be acted upon later.")] public async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
[SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.Web.Http.ValueProviders.ValueProviderResult.ConvertTo(System.Type)", Justification = "The ValueProviderResult already has the necessary context to perform a culture-aware conversion.")]
public bool BindModel(ModelBindingContext bindingContext)
{ {
ModelBindingHelper.ValidateBindingContext(bindingContext); ModelBindingHelper.ValidateBindingContext(bindingContext);
@ -19,7 +17,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return false; return false;
} }
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
if (valueProviderResult == null) if (valueProviderResult == null)
{ {
return false; // no entry return false; // no entry

View File

@ -1,13 +1,14 @@
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal; using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
public sealed class TypeMatchModelBinder : IModelBinder public sealed class TypeMatchModelBinder : IModelBinder
{ {
public bool BindModel(ModelBindingContext bindingContext) public async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{ {
ValueProviderResult valueProviderResult = GetCompatibleValueProviderResult(bindingContext); ValueProviderResult valueProviderResult = await GetCompatibleValueProviderResult(bindingContext);
if (valueProviderResult == null) if (valueProviderResult == null)
{ {
// conversion would have failed // conversion would have failed
@ -23,11 +24,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return true; return true;
} }
internal static ValueProviderResult GetCompatibleValueProviderResult(ModelBindingContext bindingContext) internal static async Task<ValueProviderResult> GetCompatibleValueProviderResult(ModelBindingContext bindingContext)
{ {
ModelBindingHelper.ValidateBindingContext(bindingContext); ModelBindingHelper.ValidateBindingContext(bindingContext);
ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
if (valueProviderResult == null) if (valueProviderResult == null)
{ {
return null; // the value doesn't exist return null; // the value doesn't exist

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
@ -19,11 +20,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
} }
public virtual bool ContainsPrefix(string prefix) public virtual async Task<bool> ContainsPrefixAsync(string prefix)
{ {
for (int i = 0; i < Count; i++) for (int i = 0; i < Count; i++)
{ {
if (this[i].ContainsPrefix(prefix)) if (await this[i].ContainsPrefixAsync(prefix))
{ {
return true; return true;
} }
@ -31,7 +32,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return false; return false;
} }
public virtual ValueProviderResult GetValue(string key) public virtual async Task<ValueProviderResult> GetValueAsync(string key)
{ {
// Performance-sensitive // Performance-sensitive
// Caching the count is faster for IList<T> // Caching the count is faster for IList<T>
@ -39,7 +40,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
for (int i = 0; i < itemCount; i++) for (int i = 0; i < itemCount; i++)
{ {
IValueProvider vp = Items[i]; IValueProvider vp = Items[i];
ValueProviderResult result = vp.GetValue(key); ValueProviderResult result = await vp.GetValueAsync(key);
if (result != null) if (result != null)
{ {
return result; return result;

View File

@ -1,6 +1,6 @@
 using System.Collections.Generic;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
@ -13,17 +13,18 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
_values = values; _values = values;
} }
public bool ContainsPrefix(string key) public Task<bool> ContainsPrefixAsync(string key)
{ {
return _values.ContainsKey(key); return Task.FromResult(_values.ContainsKey(key));
} }
public ValueProviderResult GetValue([NotNull] string key) public Task<ValueProviderResult> GetValueAsync([NotNull] string key)
{ {
object value; object value;
if (_values.TryGetValue(key, out value)) if (_values.TryGetValue(key, out value))
{ {
return new ValueProviderResult(value, value.ToString(), CultureInfo.InvariantCulture); var result = new ValueProviderResult(value, value.ToString(), CultureInfo.InvariantCulture);
return Task.FromResult(result);
} }
return null; return null;

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal; using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
@ -20,16 +21,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public object RawValue { get; private set; } public object RawValue { get; private set; }
public bool ContainsPrefix(string prefix) public Task<bool> ContainsPrefixAsync(string prefix)
{ {
return PrefixContainer.IsPrefixMatch(Name, prefix); return Task.FromResult(PrefixContainer.IsPrefixMatch(Name, prefix));
} }
public ValueProviderResult GetValue(string key) public Task<ValueProviderResult> GetValueAsync(string key)
{ {
return string.Equals(key, Name, StringComparison.OrdinalIgnoreCase) var result = string.Equals(key, Name, StringComparison.OrdinalIgnoreCase) ?
? new ValueProviderResult(RawValue, Convert.ToString(RawValue, Culture), Culture) new ValueProviderResult(RawValue, Convert.ToString(RawValue, Culture), Culture) :
: null; null;
return Task.FromResult(result);
} }
} }
} }

View File

@ -1,4 +1,5 @@
 using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding namespace Microsoft.AspNet.Mvc.ModelBinding
{ {
/// <summary> /// <summary>
@ -11,13 +12,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// </summary> /// </summary>
/// <param name="prefix">The prefix to search for.</param> /// <param name="prefix">The prefix to search for.</param>
/// <returns>true if the collection contains the specified prefix; otherwise, false.</returns> /// <returns>true if the collection contains the specified prefix; otherwise, false.</returns>
bool ContainsPrefix(string prefix); Task<bool> ContainsPrefixAsync(string prefix);
/// <summary> /// <summary>
/// Retrieves a value object using the specified key. /// Retrieves a value object using the specified key.
/// </summary> /// </summary>
/// <param name="key">The key of the value object to retrieve.</param> /// <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> /// <returns>The value object for the specified key. If the exact key is not found, null.</returns>
ValueProviderResult GetValue(string key); Task<ValueProviderResult> GetValueAsync(string key);
} }
} }

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions; using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.Mvc.ModelBinding.Internal; using Microsoft.AspNet.Mvc.ModelBinding.Internal;
@ -46,9 +47,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
} }
} }
public virtual bool ContainsPrefix(string prefix) public virtual Task<bool> ContainsPrefixAsync(string prefix)
{ {
return PrefixContainer.ContainsPrefix(prefix); return Task.FromResult(PrefixContainer.ContainsPrefix(prefix));
} }
public virtual IDictionary<string, string> GetKeysFromPrefix([NotNull] string prefix) public virtual IDictionary<string, string> GetKeysFromPrefix([NotNull] string prefix)
@ -56,21 +57,25 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return PrefixContainer.GetKeysFromPrefix(prefix); return PrefixContainer.GetKeysFromPrefix(prefix);
} }
public virtual Task<ValueProviderResult> GetValueAsync([NotNull] string key)
public virtual ValueProviderResult GetValue([NotNull] string key)
{ {
ValueProviderResult result;
var values = _values.GetValues(key); var values = _values.GetValues(key);
if (values == null) if (values == null)
{ {
return null; result = null;
} }
else if (values.Count == 1) else if (values.Count == 1)
{ {
var value = (string)values[0]; var value = (string)values[0];
return new ValueProviderResult(value, value, _culture); result = new ValueProviderResult(value, value, _culture);
}
else
{
result = new ValueProviderResult(values, _values.Get(key), _culture);
} }
return new ValueProviderResult(values, _values.Get(key), _culture); return Task.FromResult(result);
} }
} }
} }

View File

@ -1,4 +1,5 @@
#if NET45 #if NET45
using System.Threading.Tasks;
using Moq; using Moq;
using Xunit; using Xunit;
@ -7,7 +8,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public class ArrayModelBinderTest public class ArrayModelBinderTest
{ {
[Fact] [Fact]
public void BindModel() public async Task BindModel()
{ {
// Arrange // Arrange
var valueProvider = new SimpleHttpValueProvider var valueProvider = new SimpleHttpValueProvider
@ -19,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new ArrayModelBinder<int>(); var binder = new ArrayModelBinder<int>();
// Act // Act
bool retVal = binder.BindModel(bindingContext); var retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal);
@ -29,21 +30,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void GetBinder_ValueProviderDoesNotContainPrefix_ReturnsNull() public async Task GetBinder_ValueProviderDoesNotContainPrefix_ReturnsNull()
{ {
// Arrange // Arrange
ModelBindingContext bindingContext = GetBindingContext(new SimpleHttpValueProvider()); ModelBindingContext bindingContext = GetBindingContext(new SimpleHttpValueProvider());
var binder = new ArrayModelBinder<int>(); var binder = new ArrayModelBinder<int>();
// Act // Act
bool bound = binder.BindModel(bindingContext); var bound = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.False(bound); Assert.False(bound);
} }
[Fact] [Fact]
public void GetBinder_ModelMetadataReturnsReadOnly_ReturnsNull() public async Task GetBinder_ModelMetadataReturnsReadOnly_ReturnsNull()
{ {
// Arrange // Arrange
var valueProvider = new SimpleHttpValueProvider var valueProvider = new SimpleHttpValueProvider
@ -55,7 +56,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new ArrayModelBinder<int>(); var binder = new ArrayModelBinder<int>();
// Act // Act
bool bound = binder.BindModel(bindingContext); var bound = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.False(bound); Assert.False(bound);
@ -65,10 +66,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{ {
var mockIntBinder = new Mock<IModelBinder>(); var mockIntBinder = new Mock<IModelBinder>();
mockIntBinder mockIntBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns((ModelBindingContext mbc) => .Returns(async (ModelBindingContext mbc) =>
{ {
var value = mbc.ValueProvider.GetValue(mbc.ModelName); var value = await mbc.ValueProvider.GetValueAsync(mbc.ModelName);
if (value != null) if (value != null)
{ {
mbc.Model = value.ConvertTo(mbc.ModelType); mbc.Model = value.ConvertTo(mbc.ModelType);

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
#if NET45 #if NET45
using Moq; using Moq;
#endif #endif
@ -12,7 +13,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{ {
#if NET45 #if NET45
[Fact] [Fact]
public void BindComplexCollectionFromIndexes_FiniteIndexes() public async Task BindComplexCollectionFromIndexes_FiniteIndexes()
{ {
// Arrange // Arrange
var valueProvider = new SimpleHttpValueProvider var valueProvider = new SimpleHttpValueProvider
@ -24,7 +25,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new CollectionModelBinder<int>(); var binder = new CollectionModelBinder<int>();
// Act // Act
var boundCollection = binder.BindComplexCollectionFromIndexes(bindingContext, new[] { "foo", "bar", "baz" }); var boundCollection = await binder.BindComplexCollectionFromIndexes(bindingContext, new[] { "foo", "bar", "baz" });
// Assert // Assert
Assert.Equal(new[] { 42, 0, 200 }, boundCollection.ToArray()); Assert.Equal(new[] { 42, 0, 200 }, boundCollection.ToArray());
@ -32,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindComplexCollectionFromIndexes_InfiniteIndexes() public async Task BindComplexCollectionFromIndexes_InfiniteIndexes()
{ {
// Arrange // Arrange
var valueProvider = new SimpleHttpValueProvider var valueProvider = new SimpleHttpValueProvider
@ -45,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new CollectionModelBinder<int>(); var binder = new CollectionModelBinder<int>();
// Act // Act
var boundCollection = binder.BindComplexCollectionFromIndexes(bindingContext, indexNames: null); var boundCollection = await binder.BindComplexCollectionFromIndexes(bindingContext, indexNames: null);
// Assert // Assert
Assert.Equal(new[] { 42, 100 }, boundCollection.ToArray()); Assert.Equal(new[] { 42, 100 }, boundCollection.ToArray());
@ -53,7 +54,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_ComplexCollection() public async Task BindModel_ComplexCollection()
{ {
// Arrange // Arrange
var valueProvider = new SimpleHttpValueProvider var valueProvider = new SimpleHttpValueProvider
@ -67,14 +68,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new CollectionModelBinder<int>(); var binder = new CollectionModelBinder<int>();
// Act // Act
bool retVal = binder.BindModel(bindingContext); bool retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.Equal(new[] { 42, 100, 200 }, ((List<int>)bindingContext.Model).ToArray()); Assert.Equal(new[] { 42, 100, 200 }, ((List<int>)bindingContext.Model).ToArray());
} }
[Fact] [Fact]
public void BindModel_SimpleCollection() public async Task BindModel_SimpleCollection()
{ {
// Arrange // Arrange
var valueProvider = new SimpleHttpValueProvider var valueProvider = new SimpleHttpValueProvider
@ -85,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new CollectionModelBinder<int>(); var binder = new CollectionModelBinder<int>();
// Act // Act
bool retVal = binder.BindModel(bindingContext); bool retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal);
@ -94,13 +95,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
#endif #endif
[Fact] [Fact]
public void BindSimpleCollection_RawValueIsEmptyCollection_ReturnsEmptyList() public async Task BindSimpleCollection_RawValueIsEmptyCollection_ReturnsEmptyList()
{ {
// Arrange // Arrange
var binder = new CollectionModelBinder<int>(); var binder = new CollectionModelBinder<int>();
// Act // Act
var boundCollection = binder.BindSimpleCollection(bindingContext: null, rawValue: new object[0], culture: null); var boundCollection = await binder.BindSimpleCollection(bindingContext: null, rawValue: new object[0], culture: null);
// Assert // Assert
Assert.NotNull(boundCollection); Assert.NotNull(boundCollection);
@ -108,13 +109,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindSimpleCollection_RawValueIsNull_ReturnsNull() public async Task BindSimpleCollection_RawValueIsNull_ReturnsNull()
{ {
// Arrange // Arrange
var binder = new CollectionModelBinder<int>(); var binder = new CollectionModelBinder<int>();
// Act // Act
var boundCollection = binder.BindSimpleCollection(bindingContext: null, rawValue: null, culture: null); var boundCollection = await binder.BindSimpleCollection(bindingContext: null, rawValue: null, culture: null);
// Assert // Assert
Assert.Null(boundCollection); Assert.Null(boundCollection);
@ -122,7 +123,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
#if NET45 #if NET45
[Fact] [Fact]
public void BindSimpleCollection_SubBindingSucceeds() public async Task BindSimpleCollection_SubBindingSucceeds()
{ {
// Arrange // Arrange
var culture = new CultureInfo("fr-FR"); var culture = new CultureInfo("fr-FR");
@ -130,18 +131,18 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelValidationNode childValidationNode = null; ModelValidationNode childValidationNode = null;
Mock.Get<IModelBinder>(bindingContext.ModelBinder) Mock.Get<IModelBinder>(bindingContext.ModelBinder)
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns((ModelBindingContext mbc) => .Returns((ModelBindingContext mbc) =>
{ {
Assert.Equal("someName", mbc.ModelName); Assert.Equal("someName", mbc.ModelName);
childValidationNode = mbc.ValidationNode; childValidationNode = mbc.ValidationNode;
mbc.Model = 42; mbc.Model = 42;
return true; return Task.FromResult(true);
}); });
var modelBinder = new CollectionModelBinder<int>(); var modelBinder = new CollectionModelBinder<int>();
// Act // Act
var boundCollection = modelBinder.BindSimpleCollection(bindingContext, new int[1], culture); var boundCollection = await modelBinder.BindSimpleCollection(bindingContext, new int[1], culture);
// Assert // Assert
Assert.Equal(new[] { 42 }, boundCollection.ToArray()); Assert.Equal(new[] { 42 }, boundCollection.ToArray());
@ -166,10 +167,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{ {
Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>(); Mock<IModelBinder> mockIntBinder = new Mock<IModelBinder>();
mockIntBinder mockIntBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns((ModelBindingContext mbc) => .Returns(async (ModelBindingContext mbc) =>
{ {
var value = mbc.ValueProvider.GetValue(mbc.ModelName); var value = await mbc.ValueProvider.GetValueAsync(mbc.ModelName);
if (value != null) if (value != null)
{ {
mbc.Model = value.ConvertTo(mbc.ModelType); mbc.Model = value.ConvertTo(mbc.ModelType);

View File

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.DependencyInjection; using Microsoft.AspNet.DependencyInjection;
using Moq; using Moq;
using Xunit; using Xunit;
@ -12,7 +13,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public class CompositeModelBinderTest public class CompositeModelBinderTest
{ {
[Fact] [Fact]
public void BindModel_SuccessfulBind_RunsValidationAndReturnsModel() public async Task BindModel_SuccessfulBind_RunsValidationAndReturnsModel()
{ {
// Arrange // Arrange
var validationCalled = false; var validationCalled = false;
@ -23,7 +24,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)), ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
ModelName = "someName", ModelName = "someName",
ModelState = new ModelStateDictionary(), ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleValueProvider ValueProvider = new SimpleHttpValueProvider
{ {
{ "someName", "dummyValue" } { "someName", "dummyValue" }
}, },
@ -32,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var mockIntBinder = new Mock<IModelBinder>(); var mockIntBinder = new Mock<IModelBinder>();
mockIntBinder mockIntBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns( .Returns(
delegate(ModelBindingContext context) delegate(ModelBindingContext context)
{ {
@ -42,13 +43,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
context.Model = 42; context.Model = 42;
bindingContext.ValidationNode.Validating += delegate { validationCalled = true; }; bindingContext.ValidationNode.Validating += delegate { validationCalled = true; };
return true; return Task.FromResult(true);
}); });
var shimBinder = new CompositeModelBinder(mockIntBinder.Object); var shimBinder = new CompositeModelBinder(mockIntBinder.Object);
// Act // Act
var isBound = shimBinder.BindModel(bindingContext); var isBound = await shimBinder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(isBound); Assert.True(isBound);
@ -59,7 +60,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_SuccessfulBind_ComplexTypeFallback_RunsValidationAndReturnsModel() public async Task BindModel_SuccessfulBind_ComplexTypeFallback_RunsValidationAndReturnsModel()
{ {
// Arrange // Arrange
var validationCalled = false; var validationCalled = false;
@ -71,7 +72,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(List<int>)), ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(List<int>)),
ModelName = "someName", ModelName = "someName",
ModelState = new ModelStateDictionary(), ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleValueProvider ValueProvider = new SimpleHttpValueProvider
{ {
{ "someOtherName", "dummyValue" } { "someOtherName", "dummyValue" }
}, },
@ -80,13 +81,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var mockIntBinder = new Mock<IModelBinder>(); var mockIntBinder = new Mock<IModelBinder>();
mockIntBinder mockIntBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns( .Returns(
delegate(ModelBindingContext mbc) delegate(ModelBindingContext mbc)
{ {
if (!String.IsNullOrEmpty(mbc.ModelName)) if (!string.IsNullOrEmpty(mbc.ModelName))
{ {
return false; return Task.FromResult(false);
} }
Assert.Same(bindingContext.ModelMetadata, mbc.ModelMetadata); Assert.Same(bindingContext.ModelMetadata, mbc.ModelMetadata);
@ -95,13 +96,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
mbc.Model = expectedModel; mbc.Model = expectedModel;
mbc.ValidationNode.Validating += delegate { validationCalled = true; }; mbc.ValidationNode.Validating += delegate { validationCalled = true; };
return true; return Task.FromResult(true);
}); });
IModelBinder shimBinder = new CompositeModelBinder(mockIntBinder.Object); IModelBinder shimBinder = new CompositeModelBinder(mockIntBinder.Object);
// Act // Act
bool isBound = shimBinder.BindModel(bindingContext); var isBound = await shimBinder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(isBound); Assert.True(isBound);
@ -111,12 +112,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_UnsuccessfulBind_BinderFails_ReturnsNull() public async Task BindModel_UnsuccessfulBind_BinderFails_ReturnsNull()
{ {
// Arrange // Arrange
var mockListBinder = new Mock<IModelBinder>(); var mockListBinder = new Mock<IModelBinder>();
mockListBinder.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) mockListBinder.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(false) .Returns(Task.FromResult(false))
.Verifiable(); .Verifiable();
var shimBinder = (IModelBinder)mockListBinder.Object; var shimBinder = (IModelBinder)mockListBinder.Object;
@ -128,7 +129,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}; };
// Act // Act
var isBound = shimBinder.BindModel(bindingContext); var isBound = await shimBinder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.False(isBound); Assert.False(isBound);
@ -138,7 +139,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_UnsuccessfulBind_SimpleTypeNoFallback_ReturnsNull() public async Task BindModel_UnsuccessfulBind_SimpleTypeNoFallback_ReturnsNull()
{ {
// Arrange // Arrange
var innerBinder = Mock.Of<IModelBinder>(); var innerBinder = Mock.Of<IModelBinder>();
@ -152,7 +153,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}; };
// Act // Act
var isBound = shimBinder.BindModel(bindingContext); var isBound = await shimBinder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.False(isBound); Assert.False(isBound);
@ -160,12 +161,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_WithDefaultBinders_BindsSimpleType() public async Task BindModel_WithDefaultBinders_BindsSimpleType()
{ {
// Arrange // Arrange
var binder = CreateBinderWithDefaults(); var binder = CreateBinderWithDefaults();
var valueProvider = new SimpleValueProvider var valueProvider = new SimpleHttpValueProvider
{ {
{ "firstName", "firstName-value"}, { "firstName", "firstName-value"},
{ "lastName", "lastName-value"} { "lastName", "lastName-value"}
@ -173,7 +174,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var bindingContext = CreateBindingContext(binder, valueProvider, typeof(SimplePropertiesModel)); var bindingContext = CreateBindingContext(binder, valueProvider, typeof(SimplePropertiesModel));
// Act // Act
var isBound = binder.BindModel(bindingContext); var isBound = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(isBound); Assert.True(isBound);
@ -183,12 +184,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_WithDefaultBinders_BindsComplexType() public async Task BindModel_WithDefaultBinders_BindsComplexType()
{ {
// Arrange // Arrange
var binder = CreateBinderWithDefaults(); var binder = CreateBinderWithDefaults();
var valueProvider = new SimpleValueProvider var valueProvider = new SimpleHttpValueProvider
{ {
{ "firstName", "firstName-value"}, { "firstName", "firstName-value"},
{ "lastName", "lastName-value"}, { "lastName", "lastName-value"},
@ -201,7 +202,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var bindingContext = CreateBindingContext(binder, valueProvider, typeof(Person)); var bindingContext = CreateBindingContext(binder, valueProvider, typeof(Person));
// Act // Act
var isBound = binder.BindModel(bindingContext); var isBound = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(isBound); Assert.True(isBound);
@ -270,70 +271,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public List<Person> Friends { get; set; } public List<Person> Friends { get; set; }
} }
private class SimpleValueProvider : Dictionary<string, object>, IValueProvider
{
private readonly CultureInfo _culture;
public SimpleValueProvider()
: this(null)
{
}
public SimpleValueProvider(CultureInfo culture)
: base(StringComparer.OrdinalIgnoreCase)
{
_culture = culture ?? CultureInfo.InvariantCulture;
}
// copied from ValueProviderUtil
public bool ContainsPrefix(string prefix)
{
foreach (string key in Keys)
{
if (key != null)
{
if (prefix.Length == 0)
{
return true; // shortcut - non-null key matches empty prefix
}
if (key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{
if (key.Length == prefix.Length)
{
return true; // exact match
}
else
{
switch (key[prefix.Length])
{
case '.': // known separator characters
case '[':
return true;
}
}
}
}
}
return false; // nothing found
}
public ValueProviderResult GetValue(string key)
{
object rawValue;
if (TryGetValue(key, out rawValue))
{
return new ValueProviderResult(rawValue, Convert.ToString(rawValue, _culture), _culture);
}
else
{
// value not found
return null;
}
}
}
} }
} }
#endif #endif

View File

@ -1,5 +1,6 @@
#if NET45 #if NET45
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using Moq; using Moq;
using Xunit; using Xunit;
@ -8,7 +9,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public class DictionaryModelBinderTest public class DictionaryModelBinderTest
{ {
[Fact] [Fact]
public void BindModel() public async Task BindModel()
{ {
// Arrange // Arrange
var metadataProvider = new EmptyModelMetadataProvider(); var metadataProvider = new EmptyModelMetadataProvider();
@ -27,7 +28,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new DictionaryModelBinder<int, string>(); var binder = new DictionaryModelBinder<int, string>();
// Act // Act
bool retVal = binder.BindModel(bindingContext); bool retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal);
@ -43,10 +44,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{ {
Mock<IModelBinder> mockKvpBinder = new Mock<IModelBinder>(); Mock<IModelBinder> mockKvpBinder = new Mock<IModelBinder>();
mockKvpBinder mockKvpBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns((ModelBindingContext mbc) => .Returns(async (ModelBindingContext mbc) =>
{ {
var value = mbc.ValueProvider.GetValue(mbc.ModelName); var value = await mbc.ValueProvider.GetValueAsync(mbc.ModelName);
if (value != null) if (value != null)
{ {
mbc.Model = value.ConvertTo(mbc.ModelType); mbc.Model = value.ConvertTo(mbc.ModelType);

View File

@ -1,6 +1,7 @@
#if NET45 #if NET45
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Moq; using Moq;
using Xunit; using Xunit;
@ -9,7 +10,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public class KeyValuePairModelBinderTest public class KeyValuePairModelBinderTest
{ {
[Fact] [Fact]
public void BindModel_MissingKey_ReturnsFalse() public async Task BindModel_MissingKey_ReturnsFalse()
{ {
// Arrange // Arrange
var valueProvider = new SimpleHttpValueProvider(); var valueProvider = new SimpleHttpValueProvider();
@ -17,7 +18,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new KeyValuePairModelBinder<int, string>(); var binder = new KeyValuePairModelBinder<int, string>();
// Act // Act
bool retVal = binder.BindModel(bindingContext); bool retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.False(retVal); Assert.False(retVal);
@ -26,7 +27,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_MissingValue_ReturnsTrue() public async Task BindModel_MissingValue_ReturnsTrue()
{ {
// Arrange // Arrange
var valueProvider = new SimpleHttpValueProvider(); var valueProvider = new SimpleHttpValueProvider();
@ -34,7 +35,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new KeyValuePairModelBinder<int, string>(); var binder = new KeyValuePairModelBinder<int, string>();
// Act // Act
bool retVal = binder.BindModel(bindingContext); bool retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal);
@ -43,7 +44,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_SubBindingSucceeds() public async Task BindModel_SubBindingSucceeds()
{ {
// Arrange // Arrange
var innerBinder = new CompositeModelBinder(CreateStringBinder(), CreateIntBinder()); var innerBinder = new CompositeModelBinder(CreateStringBinder(), CreateIntBinder());
@ -53,7 +54,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new KeyValuePairModelBinder<int, string>(); var binder = new KeyValuePairModelBinder<int, string>();
// Act // Act
var retVal = binder.BindModel(bindingContext); var retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal);
@ -62,34 +63,33 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void TryBindStrongModel_BinderExists_BinderReturnsCorrectlyTypedObject_ReturnsTrue() public async Task TryBindStrongModel_BinderExists_BinderReturnsCorrectlyTypedObject_ReturnsTrue()
{ {
// Arrange // Arrange
ModelBindingContext bindingContext = GetBindingContext(new SimpleHttpValueProvider()); ModelBindingContext bindingContext = GetBindingContext(new SimpleHttpValueProvider());
var binder = new KeyValuePairModelBinder<int, string>(); var binder = new KeyValuePairModelBinder<int, string>();
// Act // Act
int model; var retVal = await binder.TryBindStrongModel<int>(bindingContext, "key");
var retVal = binder.TryBindStrongModel(bindingContext, "key", out model);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal.Success);
Assert.Equal(42, model); Assert.Equal(42, retVal.Model);
Assert.Single(bindingContext.ValidationNode.ChildNodes); Assert.Single(bindingContext.ValidationNode.ChildNodes);
Assert.Empty(bindingContext.ModelState); Assert.Empty(bindingContext.ModelState);
} }
[Fact] [Fact]
public void TryBindStrongModel_BinderExists_BinderReturnsIncorrectlyTypedObject_ReturnsTrue() public async Task TryBindStrongModel_BinderExists_BinderReturnsIncorrectlyTypedObject_ReturnsTrue()
{ {
// Arrange // Arrange
var innerBinder = new Mock<IModelBinder>(); var innerBinder = new Mock<IModelBinder>();
innerBinder innerBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns((ModelBindingContext mbc) => .Returns((ModelBindingContext mbc) =>
{ {
Assert.Equal("someName.key", mbc.ModelName); Assert.Equal("someName.key", mbc.ModelName);
return true; return Task.FromResult(true);
}); });
var bindingContext = GetBindingContext(new SimpleHttpValueProvider(), innerBinder.Object); var bindingContext = GetBindingContext(new SimpleHttpValueProvider(), innerBinder.Object);
@ -97,12 +97,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new KeyValuePairModelBinder<int, string>(); var binder = new KeyValuePairModelBinder<int, string>();
// Act // Act
int model; var retVal = await binder.TryBindStrongModel<int>(bindingContext, "key");
var retVal = binder.TryBindStrongModel(bindingContext, "key", out model);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal.Success);
Assert.Equal(default(int), model); Assert.Equal(default(int), retVal.Model);
Assert.Single(bindingContext.ValidationNode.ChildNodes); Assert.Single(bindingContext.ValidationNode.ChildNodes);
Assert.Empty(bindingContext.ModelState); Assert.Empty(bindingContext.ModelState);
} }
@ -126,15 +125,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{ {
var mockIntBinder = new Mock<IModelBinder>(); var mockIntBinder = new Mock<IModelBinder>();
mockIntBinder mockIntBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns((ModelBindingContext mbc) => .Returns((ModelBindingContext mbc) =>
{ {
if (mbc.ModelType == typeof(int)) if (mbc.ModelType == typeof(int))
{ {
mbc.Model = 42; mbc.Model = 42;
return true; return Task.FromResult(true);
} }
return false; return Task.FromResult(false);
}); });
return mockIntBinder.Object; return mockIntBinder.Object;
} }
@ -143,15 +142,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{ {
var mockStringBinder = new Mock<IModelBinder>(); var mockStringBinder = new Mock<IModelBinder>();
mockStringBinder mockStringBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns((ModelBindingContext mbc) => .Returns((ModelBindingContext mbc) =>
{ {
if (mbc.ModelType == typeof(string)) if (mbc.ModelType == typeof(string))
{ {
mbc.Model = "some-value"; mbc.Model = "some-value";
return true; return Task.FromResult(true);
} }
return false; return Task.FromResult(false);
}); });
return mockStringBinder.Object; return mockStringBinder.Object;
} }

View File

@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Testing; using Microsoft.AspNet.Testing;
using Moq; using Moq;
using Xunit; using Xunit;
@ -13,12 +14,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public class MutableObjectModelBinderTest public class MutableObjectModelBinderTest
{ {
[Fact] [Fact]
public void BindModel_InitsInstance() public async Task BindModel_InitsInstance()
{ {
// Arrange // Arrange
var mockValueProvider = new Mock<IValueProvider>(); var mockValueProvider = new Mock<IValueProvider>();
mockValueProvider.Setup(o => o.ContainsPrefix(It.IsAny<string>())) mockValueProvider.Setup(o => o.ContainsPrefixAsync(It.IsAny<string>()))
.Returns(true); .Returns(Task.FromResult(true));
var mockDtoBinder = new Mock<IModelBinder>(); var mockDtoBinder = new Mock<IModelBinder>();
var bindingContext = new ModelBindingContext var bindingContext = new ModelBindingContext
@ -32,11 +33,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}; };
mockDtoBinder mockDtoBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>())) .Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns((ModelBindingContext mbc) => .Returns((ModelBindingContext mbc) =>
{ {
// just return the DTO unchanged // just return the DTO unchanged
return true; return Task.FromResult(true);
}); });
var testableBinder = new Mock<TestableMutableObjectModelBinder> { CallBase = true }; var testableBinder = new Mock<TestableMutableObjectModelBinder> { CallBase = true };
@ -45,7 +46,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
.Returns(new ModelMetadata[0]).Verifiable(); .Returns(new ModelMetadata[0]).Verifiable();
// Act // Act
var retValue = testableBinder.Object.BindModel(bindingContext); var retValue = await testableBinder.Object.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retValue); Assert.True(retValue);

View File

@ -1,6 +1,7 @@
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.Threading.Tasks;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding.Test namespace Microsoft.AspNet.Mvc.ModelBinding.Test
@ -11,7 +12,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
[InlineData(typeof(object))] [InlineData(typeof(object))]
[InlineData(typeof(Calendar))] [InlineData(typeof(Calendar))]
[InlineData(typeof(TestClass))] [InlineData(typeof(TestClass))]
public void BindModel_ReturnsFalse_IfTypeCannotBeConverted(Type destinationType) public async Task BindModel_ReturnsFalse_IfTypeCannotBeConverted(Type destinationType)
{ {
// Arrange // Arrange
var bindingContext = GetBindingContext(destinationType); var bindingContext = GetBindingContext(destinationType);
@ -23,7 +24,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new TypeConverterModelBinder(); var binder = new TypeConverterModelBinder();
// Act // Act
var retVal = binder.BindModel(bindingContext); var retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.False(retVal); Assert.False(retVal);
@ -36,7 +37,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
[InlineData(typeof(DateTimeOffset))] [InlineData(typeof(DateTimeOffset))]
[InlineData(typeof(double))] [InlineData(typeof(double))]
[InlineData(typeof(DayOfWeek))] [InlineData(typeof(DayOfWeek))]
public void BindModel_ReturnsTrue_IfTypeCanBeConverted(Type destinationType) public async Task BindModel_ReturnsTrue_IfTypeCanBeConverted(Type destinationType)
{ {
// Arrange // Arrange
var bindingContext = GetBindingContext(destinationType); var bindingContext = GetBindingContext(destinationType);
@ -48,14 +49,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new TypeConverterModelBinder(); var binder = new TypeConverterModelBinder();
// Act // Act
var retVal = binder.BindModel(bindingContext); var retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal);
} }
[Fact] [Fact]
public void BindModel_Error_FormatExceptionsTurnedIntoStringsInModelState() public async Task BindModel_Error_FormatExceptionsTurnedIntoStringsInModelState()
{ {
// Arrange // Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(int)); ModelBindingContext bindingContext = GetBindingContext(typeof(int));
@ -67,7 +68,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
TypeConverterModelBinder binder = new TypeConverterModelBinder(); TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act // Act
bool retVal = binder.BindModel(bindingContext); bool retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal);
@ -77,7 +78,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_NullValueProviderResult_ReturnsFalse() public async Task BindModel_NullValueProviderResult_ReturnsFalse()
{ {
// Arrange // Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(int)); ModelBindingContext bindingContext = GetBindingContext(typeof(int));
@ -85,7 +86,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
TypeConverterModelBinder binder = new TypeConverterModelBinder(); TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act // Act
bool retVal = binder.BindModel(bindingContext); bool retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.False(retVal, "BindModel should have returned null."); Assert.False(retVal, "BindModel should have returned null.");
@ -93,7 +94,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_ValidValueProviderResult_ConvertEmptyStringsToNull() public async Task BindModel_ValidValueProviderResult_ConvertEmptyStringsToNull()
{ {
// Arrange // Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(string)); ModelBindingContext bindingContext = GetBindingContext(typeof(string));
@ -105,7 +106,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
TypeConverterModelBinder binder = new TypeConverterModelBinder(); TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act // Act
bool retVal = binder.BindModel(bindingContext); bool retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal);
@ -114,7 +115,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void BindModel_ValidValueProviderResult_ReturnsModel() public async Task BindModel_ValidValueProviderResult_ReturnsModel()
{ {
// Arrange // Arrange
ModelBindingContext bindingContext = GetBindingContext(typeof(int)); ModelBindingContext bindingContext = GetBindingContext(typeof(int));
@ -126,7 +127,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
TypeConverterModelBinder binder = new TypeConverterModelBinder(); TypeConverterModelBinder binder = new TypeConverterModelBinder();
// Act // Act
bool retVal = binder.BindModel(bindingContext); bool retVal = await binder.BindModelAsync(bindingContext);
// Assert // Assert
Assert.True(retVal); Assert.True(retVal);

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding.Test namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{ {
@ -20,7 +21,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
// copied from ValueProviderUtil // copied from ValueProviderUtil
public bool ContainsPrefix(string prefix) public Task<bool> ContainsPrefixAsync(string prefix)
{ {
foreach (string key in Keys) foreach (string key in Keys)
{ {
@ -28,14 +29,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{ {
if (prefix.Length == 0) if (prefix.Length == 0)
{ {
return true; // shortcut - non-null key matches empty prefix return Task.FromResult(true); // shortcut - non-null key matches empty prefix
} }
if (key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)) if (key.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{ {
if (key.Length == prefix.Length) if (key.Length == prefix.Length)
{ {
return true; // exact match return Task.FromResult(true); // exact match
} }
else else
{ {
@ -43,28 +44,26 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{ {
case '.': // known separator characters case '.': // known separator characters
case '[': case '[':
return true; return Task.FromResult(true);
} }
} }
} }
} }
} }
return false; // nothing found return Task.FromResult(false); // nothing found
} }
public ValueProviderResult GetValue(string key) public Task<ValueProviderResult> GetValueAsync(string key)
{ {
ValueProviderResult result = null;
object rawValue; object rawValue;
if (TryGetValue(key, out rawValue)) if (TryGetValue(key, out rawValue))
{ {
return new ValueProviderResult(rawValue, Convert.ToString(rawValue, _culture), _culture); result = new ValueProviderResult(rawValue, Convert.ToString(rawValue, _culture), _culture);
}
else
{
// value not found
return null;
} }
return Task.FromResult(result);
} }
} }
} }

View File

@ -1,6 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions; using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.PipelineCore.Collections; using Microsoft.AspNet.PipelineCore.Collections;
using Xunit; using Xunit;
@ -20,52 +21,52 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
[Fact] [Fact]
public void ContainsPrefix_WithEmptyCollection_ReturnsFalseForEmptyPrefix() public async Task ContainsPrefix_WithEmptyCollection_ReturnsFalseForEmptyPrefix()
{ {
// Arrange // Arrange
var backingStore = new ReadableStringCollection(new Dictionary<string, string[]>()); var backingStore = new ReadableStringCollection(new Dictionary<string, string[]>());
var valueProvider = new ReadableStringCollectionValueProvider(backingStore, null); var valueProvider = new ReadableStringCollectionValueProvider(backingStore, null);
// Act // Act
bool result = valueProvider.ContainsPrefix(""); var result = await valueProvider.ContainsPrefixAsync("");
// Assert // Assert
Assert.False(result); Assert.False(result);
} }
[Fact] [Fact]
public void ContainsPrefix_WithNonEmptyCollection_ReturnsTrueForEmptyPrefix() public async Task ContainsPrefix_WithNonEmptyCollection_ReturnsTrueForEmptyPrefix()
{ {
// Arrange // Arrange
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null); var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
// Act // Act
bool result = valueProvider.ContainsPrefix(""); var result = await valueProvider.ContainsPrefixAsync("");
// Assert // Assert
Assert.True(result); Assert.True(result);
} }
[Fact] [Fact]
public void ContainsPrefix_WithNonEmptyCollection_ReturnsTrueForKnownPrefixes() public async Task ContainsPrefix_WithNonEmptyCollection_ReturnsTrueForKnownPrefixes()
{ {
// Arrange // Arrange
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null); var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
// Act & Assert // Act & Assert
Assert.True(valueProvider.ContainsPrefix("foo")); Assert.True(await valueProvider.ContainsPrefixAsync("foo"));
Assert.True(valueProvider.ContainsPrefix("bar")); Assert.True(await valueProvider.ContainsPrefixAsync("bar"));
Assert.True(valueProvider.ContainsPrefix("bar.baz")); Assert.True(await valueProvider.ContainsPrefixAsync("bar.baz"));
} }
[Fact] [Fact]
public void ContainsPrefix_WithNonEmptyCollection_ReturnsFalseForUnknownPrefix() public async Task ContainsPrefix_WithNonEmptyCollection_ReturnsFalseForUnknownPrefix()
{ {
// Arrange // Arrange
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null); var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
// Act // Act
bool result = valueProvider.ContainsPrefix("biff"); var result = await valueProvider.ContainsPrefixAsync("biff");
// Assert // Assert
Assert.False(result); Assert.False(result);
@ -115,14 +116,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void GetValue_SingleValue() public async Task GetValue_SingleValue()
{ {
// Arrange // Arrange
var culture = new CultureInfo("fr-FR"); var culture = new CultureInfo("fr-FR");
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, culture); var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, culture);
// Act // Act
ValueProviderResult vpResult = valueProvider.GetValue("bar.baz"); var vpResult = await valueProvider.GetValueAsync("bar.baz");
// Assert // Assert
Assert.NotNull(vpResult); Assert.NotNull(vpResult);
@ -132,14 +133,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void GetValue_MultiValue() public async Task GetValue_MultiValue()
{ {
// Arrange // Arrange
var culture = new CultureInfo("fr-FR"); var culture = new CultureInfo("fr-FR");
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, culture); var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, culture);
// Act // Act
ValueProviderResult vpResult = valueProvider.GetValue("foo"); var vpResult = await valueProvider.GetValueAsync("foo");
// Assert // Assert
Assert.NotNull(vpResult); Assert.NotNull(vpResult);
@ -153,7 +154,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
//[Theory] //[Theory]
//[InlineData("null_value")] //[InlineData("null_value")]
//[InlineData("prefix.null_value")] //[InlineData("prefix.null_value")]
//public void GetValue_NullValue(string key) //public async Task GetValue_NullValue(string key)
//{ //{
// // Arrange // // Arrange
// var culture = new CultureInfo("fr-FR"); // var culture = new CultureInfo("fr-FR");
@ -170,7 +171,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
//} //}
[Fact] [Fact]
public void GetValue_NullMultipleValue() public async Task GetValue_NullMultipleValue()
{ {
// Arrange // Arrange
var backingStore = new ReadableStringCollection( var backingStore = new ReadableStringCollection(
@ -182,7 +183,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var valueProvider = new ReadableStringCollectionValueProvider(backingStore, culture); var valueProvider = new ReadableStringCollectionValueProvider(backingStore, culture);
// Act // Act
ValueProviderResult vpResult = valueProvider.GetValue("key"); var vpResult = await valueProvider.GetValueAsync("key");
// Assert // Assert
Assert.Equal(new[] { null, null, "value" }, vpResult.RawValue as IEnumerable<string>); Assert.Equal(new[] { null, null, "value" }, vpResult.RawValue as IEnumerable<string>);
@ -190,13 +191,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
} }
[Fact] [Fact]
public void GetValue_ReturnsNullIfKeyNotFound() public async Task GetValue_ReturnsNullIfKeyNotFound()
{ {
// Arrange // Arrange
var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null); var valueProvider = new ReadableStringCollectionValueProvider(_backingStore, null);
// Act // Act
ValueProviderResult vpResult = valueProvider.GetValue("bar"); var vpResult = await valueProvider.GetValueAsync("bar");
// Assert // Assert
Assert.Null(vpResult); Assert.Null(vpResult);