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))
{
if (actionBindingContext.ValueProvider.ContainsPrefix(parameter.ParameterBindingInfo.Prefix))
if (await actionBindingContext.ValueProvider.ContainsPrefixAsync(parameter.ParameterBindingInfo.Prefix))
{
candidate.FoundParameters++;
if (parameter.IsOptional)

View File

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

View File

@ -1,18 +1,19 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
public class ArrayModelBinder<TElement> : CollectionModelBinder<TElement>
{
public override bool BindModel(ModelBindingContext bindingContext)
public override Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{
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)

View File

@ -3,36 +3,36 @@ using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
public class CollectionModelBinder<TElement> : IModelBinder
{
public virtual bool BindModel(ModelBindingContext bindingContext)
public virtual async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{
ModelBindingHelper.ValidateBindingContext(bindingContext);
if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
if (!await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
{
return false;
}
ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
List<TElement> boundCollection = (valueProviderResult != null)
? BindSimpleCollection(bindingContext, valueProviderResult.RawValue, valueProviderResult.Culture)
: BindComplexCollection(bindingContext);
var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
var boundCollection = await ((valueProviderResult != null) ?
BindSimpleCollection(bindingContext, valueProviderResult.RawValue, valueProviderResult.Culture) :
BindComplexCollection(bindingContext));
bool retVal = CreateOrReplaceCollection(bindingContext, boundCollection);
return retVal;
return CreateOrReplaceCollection(bindingContext, boundCollection);
}
// TODO: Make this method internal
// 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[].
public List<TElement> BindSimpleCollection(ModelBindingContext bindingContext,
object rawValue,
CultureInfo culture)
public async Task<List<TElement>> BindSimpleCollection(ModelBindingContext bindingContext,
object rawValue,
CultureInfo culture)
{
if (rawValue == null)
{
@ -57,7 +57,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
};
object boundValue = null;
if (bindingContext.ModelBinder.BindModel(innerBindingContext))
if (await bindingContext.ModelBinder.BindModelAsync(innerBindingContext))
{
boundValue = innerBindingContext.Model;
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].
private List<TElement> BindComplexCollection(ModelBindingContext bindingContext)
private async Task<List<TElement>> BindComplexCollection(ModelBindingContext bindingContext)
{
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);
return BindComplexCollectionFromIndexes(bindingContext, indexNames);
return await BindComplexCollectionFromIndexes(bindingContext, indexNames);
}
// TODO: Convert to internal
public List<TElement> BindComplexCollectionFromIndexes(ModelBindingContext bindingContext,
IEnumerable<string> indexNames)
public async Task<List<TElement>> BindComplexCollectionFromIndexes(ModelBindingContext bindingContext,
IEnumerable<string> indexNames)
{
bool indexNamesIsFinite;
if (indexNames != null)
@ -108,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Type modelType = bindingContext.ModelType;
if (bindingContext.ModelBinder.BindModel(childBindingContext))
if (await bindingContext.ModelBinder.BindModelAsync(childBindingContext))
{
didBind = true;
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
{
public sealed class ComplexModelDtoModelBinder : IModelBinder
{
public bool BindModel(ModelBindingContext bindingContext)
public async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(ComplexModelDto))
{
@ -21,8 +22,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// bind and propagate the values
// If we can't bind, then leave the result missing (don't add a null).
if (bindingContext.ModelBinder.BindModel(propertyBindingContext))
if (await bindingContext.ModelBinder.BindModelAsync(propertyBindingContext))
{
dto.Results[propertyMetadata] = new ComplexModelDtoResult(propertyBindingContext.Model, propertyBindingContext.ValidationNode);
}

View File

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

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.DependencyInjection;
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
@ -18,16 +19,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
_activator = activator;
}
public bool BindModel(ModelBindingContext bindingContext)
public Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{
Type binderType = ResolveBinderType(bindingContext.ModelType);
if (binderType != null)
{
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)

View File

@ -1,4 +1,4 @@
using Microsoft.AspNet.Abstractions;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
@ -7,6 +7,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// </summary>
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;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
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);
TKey key;
bool keyBindingSucceeded = TryBindStrongModel(bindingContext, "key", out key);
var keyResult = await TryBindStrongModel<TKey>(bindingContext, "key");
var valueResult = await TryBindStrongModel<TValue>(bindingContext, "value");
TValue value;
bool valueBindingSucceeded = TryBindStrongModel(bindingContext, "value", out value);
if (keyBindingSucceeded && valueBindingSucceeded)
if (keyResult.Success && valueResult.Success)
{
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
public bool TryBindStrongModel<TModel>(ModelBindingContext parentBindingContext,
string propertyName,
out TModel model)
internal async Task<BindResult<TModel>> TryBindStrongModel<TModel>(ModelBindingContext parentBindingContext,
string propertyName)
{
ModelBindingContext propertyBindingContext = new ModelBindingContext(parentBindingContext)
{
@ -33,16 +30,28 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ModelName = ModelBindingHelper.CreatePropertyModelName(parentBindingContext.ModelName, propertyName)
};
if (propertyBindingContext.ModelBinder.BindModel(propertyBindingContext))
if (await propertyBindingContext.ModelBinder.BindModelAsync(propertyBindingContext))
{
object untypedModel = propertyBindingContext.Model;
model = ModelBindingHelper.CastOrDefault<TModel>(untypedModel);
var model = ModelBindingHelper.CastOrDefault<TModel>(untypedModel);
parentBindingContext.ValidationNode.ChildNodes.Add(propertyBindingContext.ValidationNode);
return true;
return new BindResult<TModel>(true, model);
}
model = default(TModel);
return false;
return new BindResult<TModel>(false, default(TModel));
}
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.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
public class MutableObjectModelBinder : IModelBinder
{
public virtual bool BindModel(ModelBindingContext bindingContext)
public virtual async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{
ModelBindingHelper.ValidateBindingContext(bindingContext);
if (!CanBindType(bindingContext.ModelType) ||
!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName))
!await bindingContext.ValueProvider.ContainsPrefixAsync(bindingContext.ModelName))
{
return false;
}
@ -94,7 +95,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ModelName = bindingContext.ModelName
};
bindingContext.ModelBinder.BindModel(dtoBindingContext);
bindingContext.ModelBinder.BindModelAsync(dtoBindingContext);
return (ComplexModelDto)dtoBindingContext.Model;
}

View File

@ -1,15 +1,13 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
public sealed class TypeConverterModelBinder : IModelBinder
{
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The exception is recorded to be acted upon later.")]
[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)
public async Task<bool> BindModelAsync(ModelBindingContext bindingContext)
{
ModelBindingHelper.ValidateBindingContext(bindingContext);
@ -19,7 +17,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return false;
}
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
if (valueProviderResult == null)
{
return false; // no entry

View File

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

View File

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

View File

@ -1,6 +1,6 @@

using System.Collections.Generic;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
@ -13,17 +13,18 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
_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;
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;

View File

@ -1,5 +1,6 @@
using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
@ -20,16 +21,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
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)
? new ValueProviderResult(RawValue, Convert.ToString(RawValue, Culture), Culture)
: null;
var result = string.Equals(key, Name, StringComparison.OrdinalIgnoreCase) ?
new ValueProviderResult(RawValue, Convert.ToString(RawValue, Culture), Culture) :
null;
return Task.FromResult(result);
}
}
}

View File

@ -1,4 +1,5 @@

using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
/// <summary>
@ -11,13 +12,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>
bool ContainsPrefix(string prefix);
Task<bool> ContainsPrefixAsync(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>
ValueProviderResult GetValue(string key);
Task<ValueProviderResult> GetValueAsync(string key);
}
}

View File

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
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)
@ -56,21 +57,25 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return PrefixContainer.GetKeysFromPrefix(prefix);
}
public virtual ValueProviderResult GetValue([NotNull] string key)
public virtual Task<ValueProviderResult> GetValueAsync([NotNull] string key)
{
ValueProviderResult result;
var values = _values.GetValues(key);
if (values == null)
{
return null;
result = null;
}
else if (values.Count == 1)
{
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
using System.Threading.Tasks;
using Moq;
using Xunit;
@ -7,7 +8,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public class ArrayModelBinderTest
{
[Fact]
public void BindModel()
public async Task BindModel()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
@ -19,7 +20,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new ArrayModelBinder<int>();
// Act
bool retVal = binder.BindModel(bindingContext);
var retVal = await binder.BindModelAsync(bindingContext);
// Assert
Assert.True(retVal);
@ -29,21 +30,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
[Fact]
public void GetBinder_ValueProviderDoesNotContainPrefix_ReturnsNull()
public async Task GetBinder_ValueProviderDoesNotContainPrefix_ReturnsNull()
{
// Arrange
ModelBindingContext bindingContext = GetBindingContext(new SimpleHttpValueProvider());
var binder = new ArrayModelBinder<int>();
// Act
bool bound = binder.BindModel(bindingContext);
var bound = await binder.BindModelAsync(bindingContext);
// Assert
Assert.False(bound);
}
[Fact]
public void GetBinder_ModelMetadataReturnsReadOnly_ReturnsNull()
public async Task GetBinder_ModelMetadataReturnsReadOnly_ReturnsNull()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
@ -55,7 +56,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var binder = new ArrayModelBinder<int>();
// Act
bool bound = binder.BindModel(bindingContext);
var bound = await binder.BindModelAsync(bindingContext);
// Assert
Assert.False(bound);
@ -65,10 +66,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
var mockIntBinder = new Mock<IModelBinder>();
mockIntBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>()))
.Returns((ModelBindingContext mbc) =>
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(async (ModelBindingContext mbc) =>
{
var value = mbc.ValueProvider.GetValue(mbc.ModelName);
var value = await mbc.ValueProvider.GetValueAsync(mbc.ModelName);
if (value != null)
{
mbc.Model = value.ConvertTo(mbc.ModelType);

View File

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

View File

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.DependencyInjection;
using Moq;
using Xunit;
@ -12,7 +13,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public class CompositeModelBinderTest
{
[Fact]
public void BindModel_SuccessfulBind_RunsValidationAndReturnsModel()
public async Task BindModel_SuccessfulBind_RunsValidationAndReturnsModel()
{
// Arrange
var validationCalled = false;
@ -23,7 +24,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(int)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleValueProvider
ValueProvider = new SimpleHttpValueProvider
{
{ "someName", "dummyValue" }
},
@ -32,7 +33,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var mockIntBinder = new Mock<IModelBinder>();
mockIntBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>()))
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(
delegate(ModelBindingContext context)
{
@ -42,13 +43,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
context.Model = 42;
bindingContext.ValidationNode.Validating += delegate { validationCalled = true; };
return true;
return Task.FromResult(true);
});
var shimBinder = new CompositeModelBinder(mockIntBinder.Object);
// Act
var isBound = shimBinder.BindModel(bindingContext);
var isBound = await shimBinder.BindModelAsync(bindingContext);
// Assert
Assert.True(isBound);
@ -59,7 +60,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
[Fact]
public void BindModel_SuccessfulBind_ComplexTypeFallback_RunsValidationAndReturnsModel()
public async Task BindModel_SuccessfulBind_ComplexTypeFallback_RunsValidationAndReturnsModel()
{
// Arrange
var validationCalled = false;
@ -71,7 +72,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(null, typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleValueProvider
ValueProvider = new SimpleHttpValueProvider
{
{ "someOtherName", "dummyValue" }
},
@ -80,13 +81,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var mockIntBinder = new Mock<IModelBinder>();
mockIntBinder
.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>()))
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(
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);
@ -95,13 +96,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
mbc.Model = expectedModel;
mbc.ValidationNode.Validating += delegate { validationCalled = true; };
return true;
return Task.FromResult(true);
});
IModelBinder shimBinder = new CompositeModelBinder(mockIntBinder.Object);
// Act
bool isBound = shimBinder.BindModel(bindingContext);
var isBound = await shimBinder.BindModelAsync(bindingContext);
// Assert
Assert.True(isBound);
@ -111,12 +112,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
[Fact]
public void BindModel_UnsuccessfulBind_BinderFails_ReturnsNull()
public async Task BindModel_UnsuccessfulBind_BinderFails_ReturnsNull()
{
// Arrange
var mockListBinder = new Mock<IModelBinder>();
mockListBinder.Setup(o => o.BindModel(It.IsAny<ModelBindingContext>()))
.Returns(false)
mockListBinder.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(Task.FromResult(false))
.Verifiable();
var shimBinder = (IModelBinder)mockListBinder.Object;
@ -128,7 +129,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
};
// Act
var isBound = shimBinder.BindModel(bindingContext);
var isBound = await shimBinder.BindModelAsync(bindingContext);
// Assert
Assert.False(isBound);
@ -138,7 +139,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
[Fact]
public void BindModel_UnsuccessfulBind_SimpleTypeNoFallback_ReturnsNull()
public async Task BindModel_UnsuccessfulBind_SimpleTypeNoFallback_ReturnsNull()
{
// Arrange
var innerBinder = Mock.Of<IModelBinder>();
@ -152,7 +153,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
};
// Act
var isBound = shimBinder.BindModel(bindingContext);
var isBound = await shimBinder.BindModelAsync(bindingContext);
// Assert
Assert.False(isBound);
@ -160,12 +161,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
[Fact]
public void BindModel_WithDefaultBinders_BindsSimpleType()
public async Task BindModel_WithDefaultBinders_BindsSimpleType()
{
// Arrange
var binder = CreateBinderWithDefaults();
var valueProvider = new SimpleValueProvider
var valueProvider = new SimpleHttpValueProvider
{
{ "firstName", "firstName-value"},
{ "lastName", "lastName-value"}
@ -173,7 +174,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var bindingContext = CreateBindingContext(binder, valueProvider, typeof(SimplePropertiesModel));
// Act
var isBound = binder.BindModel(bindingContext);
var isBound = await binder.BindModelAsync(bindingContext);
// Assert
Assert.True(isBound);
@ -183,12 +184,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
}
[Fact]
public void BindModel_WithDefaultBinders_BindsComplexType()
public async Task BindModel_WithDefaultBinders_BindsComplexType()
{
// Arrange
var binder = CreateBinderWithDefaults();
var valueProvider = new SimpleValueProvider
var valueProvider = new SimpleHttpValueProvider
{
{ "firstName", "firstName-value"},
{ "lastName", "lastName-value"},
@ -201,7 +202,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var bindingContext = CreateBindingContext(binder, valueProvider, typeof(Person));
// Act
var isBound = binder.BindModel(bindingContext);
var isBound = await binder.BindModelAsync(bindingContext);
// Assert
Assert.True(isBound);
@ -270,70 +271,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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