Make ValueProviderResult a string-ish struct

This commit is contained in:
Ryan Nowak 2015-08-18 15:02:58 -07:00
parent 02cc82a055
commit 6d365e9a32
73 changed files with 2135 additions and 1806 deletions

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="AspNetVNext" value="https://www.myget.org/F/aspnetlitedev/api/v2" />

View File

@ -3,17 +3,29 @@
namespace Microsoft.AspNet.Mvc.ModelBinding
{
/// <summary>
/// An entry in a <see cref="ModelStateDictionary"/>.
/// </summary>
public class ModelState
{
private readonly ModelErrorCollection _errors = new ModelErrorCollection();
/// <summary>
/// Gets the raw value from the request associated with this entry.
/// </summary>
public object RawValue { get; set; }
public ValueProviderResult Value { get; set; }
/// <summary>
/// Gets the set of values contained in <see cref="RawValue"/>, joined into a comma-separated string.
/// </summary>
public string AttemptedValue { get; set; }
public ModelErrorCollection Errors
{
get { return _errors; }
}
/// <summary>
/// Gets the <see cref="ModelErrorCollection"/> for this entry.
/// </summary>
public ModelErrorCollection Errors { get; } = new ModelErrorCollection();
/// <summary>
/// Gets or sets the <see cref="ModelValidationState"/> for this entry.
/// </summary>
public ModelValidationState ValidationState { get; set; }
}
}

View File

@ -4,6 +4,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.Framework.Internal;
@ -213,6 +214,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Convert FormatExceptions to Invalid value messages.
ModelState modelState;
TryGetValue(key, out modelState);
string errorMessage;
if (modelState == null)
{
@ -221,7 +223,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
else
{
errorMessage = Resources.FormatModelError_InvalidValue_MessageWithModelValue(
modelState.Value.AttemptedValue,
modelState.AttemptedValue,
key);
}
@ -359,14 +361,50 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
/// <summary>
/// Sets the value for the <see cref="ModelState"/> with the specified <paramref name="key"/> to the
/// specified <paramref name="value"/>.
/// Sets the of <see cref="ModelState.RawValue"/> and <see cref="ModelState.AttemptedValue"/> for
/// the <see cref="ModelState"/> with the specified <paramref name="key"/>.
/// </summary>
/// <param name="key">The key for the <see cref="ModelState"/> entry.</param>
/// <param name="value">The value to assign.</param>
public void SetModelValue([NotNull] string key, [NotNull] ValueProviderResult value)
/// <param name="rawvalue">The raw value for the <see cref="ModelState"/> entry.</param>
/// <param name="attemptedValue">
/// The values of <param name="rawValue"/> in a comma-separated <see cref="string"/>.
/// </param>
public void SetModelValue([NotNull] string key, object rawValue, string attemptedValue)
{
GetModelStateForKey(key).Value = value;
var modelState = GetModelStateForKey(key);
modelState.RawValue = rawValue;
modelState.AttemptedValue = attemptedValue;
}
/// <summary>
/// Sets the value for the <see cref="ModelState"/> with the specified <paramref name="key"/>.
/// </summary>
/// <param name="key">The key for the <see cref="ModelState"/> entry</param>
/// <param name="valueProviderResult">
/// A <see cref="ValueProviderResult"/> with data for the <see cref="ModelState"/> entry.
/// </param>
public void SetModelValue([NotNull] string key, ValueProviderResult valueProviderResult)
{
// Avoid creating a new array for rawvalue if there's only one value.
object rawValue;
if (valueProviderResult == ValueProviderResult.None)
{
rawValue = null;
}
else if (valueProviderResult.Value != null)
{
rawValue = valueProviderResult.Value;
}
else if (valueProviderResult.Length == 1)
{
rawValue = valueProviderResult.Values[0];
}
else
{
rawValue = valueProviderResult.Values;
}
SetModelValue(key, rawValue, (string)valueProviderResult);
}
/// <summary>

View File

@ -3,227 +3,353 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.ExceptionServices;
using Microsoft.AspNet.Mvc.Abstractions;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
/// <summary>
/// Result of an <see cref="IValueProvider.GetValueAsync"/> operation.
/// Result of an <see cref="IValueProvider.GetValueAsync(string)"/> operation.
/// </summary>
public class ValueProviderResult
/// <remarks>
/// <para>
/// <see cref="ValueProviderResult"/> can represent a single submitted value or multiple submitted values.
/// </para>
/// <para>
/// Use <see cref="FirstValue"/> to consume only a single value, regardless of whether a single value or
/// multiple values were submitted.
/// </para>
/// <para>
/// Treat <see cref="ValueProviderResult"/> as an <see cref="IEnumerable{string}"/> to consume all values,
/// regardless of whether a single value or multiple values were submitted.
/// </para>
/// </remarks>
public struct ValueProviderResult : IEquatable<ValueProviderResult>, IEnumerable<string>
{
private static readonly CultureInfo _staticCulture = CultureInfo.InvariantCulture;
private static readonly CultureInfo _invariantCulture = CultureInfo.InvariantCulture;
/// <summary>
/// Instantiates a new instance of the <see cref="ValueProviderResult"/> class with given
/// <paramref name="rawValue"/>. Initializes <see cref="Culture"/> to
/// <see cref="CultureInfo.InvariantCulture"/>.
/// A <see cref="ValueProviderResult"/> that represents a lack of data.
/// </summary>
/// <param name="rawValue">The <see cref="RawValue"/> value of the new instance.</param>
public ValueProviderResult(object rawValue)
: this(rawValue, attemptedValue: null, culture: _staticCulture)
public static ValueProviderResult None = new ValueProviderResult(new string[0]);
/// <summary>
/// Creates a new <see cref="ValueProviderResult"/> using <see cref="CultureInfo.InvariantCulture"/>.
/// </summary>
/// <param name="value">The submitted value.</param>
public ValueProviderResult(string value)
: this(value, _invariantCulture)
{
}
/// <summary>
/// Instantiates a new instance of the <see cref="ValueProviderResult"/> class with given
/// <paramref name="rawValue"/>, <paramref name="attemptedValue"/>, and <paramref name="culture"/>.
/// Creates a new <see cref="ValueProviderResult"/>.
/// </summary>
/// <param name="rawValue">The <see cref="RawValue"/> value of the new instance.</param>
/// <param name="attemptedValue">The <see cref="AttemptedValue"/> value of the new instance.</param>
/// <param name="culture">The <see cref="Culture"/> value of the new instance.</param>
public ValueProviderResult(object rawValue, string attemptedValue, CultureInfo culture)
/// <param name="value">The submitted value.</param>
/// <param name="culture">The <see cref="CultureInfo"/> associated with this value.</param>
public ValueProviderResult(string value, CultureInfo culture)
{
RawValue = rawValue;
AttemptedValue = attemptedValue;
Culture = culture ?? _staticCulture;
}
/// <summary>
/// <see cref="string"/> conversion of <see cref="RawValue"/>.
/// </summary>
/// <remarks>
/// Used in helpers that generate <c>&lt;textarea&gt;</c> elements as well as some error messages.
/// </remarks>
public string AttemptedValue { get; }
/// <summary>
/// <see cref="CultureInfo"/> to use in <see cref="ConvertTo(Type)"/> or
/// <see cref="ConvertTo(Type, CultureInfo)"/> if passed <see cref="CultureInfo"/> is <c>null</c>.
/// </summary>
public CultureInfo Culture { get; }
/// <summary>
/// The provided <see cref="object"/>.
/// </summary>
public object RawValue { get; }
/// <summary>
/// Converts <see cref="RawValue"/> to the given <paramref name="type"/>. Uses <see cref="Culture"/> for
/// <see cref="TypeConverter"/> operations.
/// </summary>
/// <param name="type">The target <see cref="Type"/> of the conversion.</param>
/// <returns>
/// <see cref="RawValue"/> converted to the given <paramref name="type"/>. <c>null</c> if the conversion fails.
/// </returns>
public object ConvertTo(Type type)
{
return ConvertTo(type, culture: null);
}
/// <summary>
/// Converts <see cref="RawValue"/> to the given <paramref name="type"/> using the given
/// <paramref name="culture"/>.
/// </summary>
/// <param name="type">The target <see cref="Type"/> of the conversion.</param>
/// <param name="culture">
/// The <see cref="CultureInfo"/> to use for <see cref="TypeConverter"/> operations. Uses
/// <see cref="Culture"/> if this parameter is <c>null</c>.
/// </param>
/// <returns>
/// <see cref="RawValue"/> converted to the given <paramref name="type"/> using the given
/// <paramref name="culture"/>. <c>null</c> if the conversion fails.
/// </returns>
public virtual object ConvertTo([NotNull] Type type, CultureInfo culture)
{
var value = RawValue;
if (value == null)
{
// treat null route parameters as though they were the default value for the type
return type.GetTypeInfo().IsValueType ? Activator.CreateInstance(type) :
null;
Value = null;
Values = None.Values;
}
if (value.GetType().IsAssignableFrom(type))
else
{
return value;
Value = value;
Values = null;
}
var cultureToUse = culture ?? Culture;
return UnwrapPossibleArrayType(cultureToUse, value, type);
Culture = culture ?? _invariantCulture;
}
private object UnwrapPossibleArrayType(CultureInfo culture, object value, Type destinationType)
/// <summary>
/// Creates a new <see cref="ValueProviderResult"/> using <see cref="CultureInfo.InvariantCulture"/>.
/// </summary>
/// <param name="values">The submitted values.</param>
public ValueProviderResult(string[] values)
: this(values, _invariantCulture)
{
// array conversion results in four cases, as below
var valueAsArray = value as Array;
if (destinationType.IsArray)
}
/// <summary>
/// Creates a new <see cref="ValueProviderResult"/>.
/// </summary>
/// <param name="values">The submitted values.</param>
/// <param name="culture">The <see cref="CultureInfo"/> associated with these values.</param>
public ValueProviderResult(string[] values, CultureInfo culture)
{
if (values == null)
{
var destinationElementType = destinationType.GetElementType();
if (valueAsArray != null)
{
// case 1: both destination + source type are arrays, so convert each element
var converted = (IList)Array.CreateInstance(destinationElementType, valueAsArray.Length);
for (var i = 0; i < valueAsArray.Length; i++)
{
converted[i] = ConvertSimpleType(culture, valueAsArray.GetValue(i), destinationElementType);
}
return converted;
}
else
{
// case 2: destination type is array but source is single element, so wrap element in
// array + convert
var element = ConvertSimpleType(culture, value, destinationElementType);
var converted = (IList)Array.CreateInstance(destinationElementType, 1);
converted[0] = element;
return converted;
}
Value = null;
Values = None.Values;
}
else if (valueAsArray != null)
else
{
// case 3: destination type is single element but source is array, so extract first element + convert
if (valueAsArray.Length > 0)
Value = null;
Values = values;
}
Culture = culture;
}
/// <summary>
/// Gets or sets the <see cref="CultureInfo"/> associated with the values.
/// </summary>
public CultureInfo Culture { get; private set; }
/// <summary>
/// Gets or sets a single value. Will be <c>null</c> if multiple values are present.
/// </summary>
public string Value { get; private set; }
/// <summary>
/// Gets or sets an array of values. Will be <c>null</c> if only a single value was provided.
/// </summary>
public string[] Values { get; private set; }
/// <summary>
/// Gets the first value based on the order values were provided in the request. Use <see cref="FirstValue"/>
/// to get a single value for processing regarless of whether a single or multiple values were provided
/// in the request.
/// </summary>
public string FirstValue
{
get
{
if (Value != null)
{
value = valueAsArray.GetValue(0);
return ConvertSimpleType(culture, value, destinationType);
return Value;
}
else if (Values != null && Values.Length > 0)
{
return Values[0];
}
else
{
// case 3(a): source is empty array, so can't perform conversion
return null;
}
}
// case 4: both destination + source type are single elements, so convert
return ConvertSimpleType(culture, value, destinationType);
}
private object ConvertSimpleType(CultureInfo culture, object value, Type destinationType)
/// <summary>
/// Gets the number of submitted values.
/// </summary>
public int Length
{
if (value == null || value.GetType().IsAssignableFrom(destinationType))
get
{
return value;
}
// In case of a Nullable object, we try again with its underlying type.
destinationType = UnwrapNullableType(destinationType);
// if this is a user-input value but the user didn't type anything, return no value
var valueAsString = value as string;
if (valueAsString != null && string.IsNullOrWhiteSpace(valueAsString))
{
return null;
}
var converter = TypeDescriptor.GetConverter(destinationType);
var canConvertFrom = converter.CanConvertFrom(value.GetType());
if (!canConvertFrom)
{
converter = TypeDescriptor.GetConverter(value.GetType());
}
if (!(canConvertFrom || converter.CanConvertTo(destinationType)))
{
// EnumConverter cannot convert integer, so we verify manually
if (destinationType.GetTypeInfo().IsEnum &&
(value is int ||
value is uint ||
value is long ||
value is ulong ||
value is short ||
value is ushort ||
value is byte ||
value is sbyte))
if (Values != null)
{
return Enum.ToObject(destinationType, value);
return Values.Length;
}
throw new InvalidOperationException(
Resources.FormatValueProviderResult_NoConverterExists(value.GetType(), destinationType));
}
try
{
return canConvertFrom
? converter.ConvertFrom(null, culture, value)
: converter.ConvertTo(null, culture, value, destinationType);
}
catch (Exception ex)
{
if (ex is FormatException)
else if (Value != null)
{
throw ex;
return 1;
}
else
{
// TypeConverter throws System.Exception wrapping the FormatException,
// so we throw the inner exception.
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
// this code is never reached because the previous line is throwing;
throw;
return 0;
}
}
}
private static Type UnwrapNullableType(Type destinationType)
/// <inheritdoc />
public override bool Equals(object obj)
{
return Nullable.GetUnderlyingType(destinationType) ?? destinationType;
var other = obj as ValueProviderResult?;
return other.HasValue ? Equals(other.Value) : false;
}
/// <inheritdoc />
public bool Equals(ValueProviderResult other)
{
if (Length != other.Length)
{
return false;
}
else
{
var x = (string[])this;
var y = (string[])other;
for (var i = 0; i < x.Length; i++)
{
if (!string.Equals(x[i], y[i], StringComparison.Ordinal))
{
return false;
}
}
return true;
}
}
/// <inheritdoc />
public override int GetHashCode()
{
return ((string)this)?.GetHashCode() ?? 0;
}
/// <inheritdoc />
public override string ToString()
{
return (string)this;
}
/// <summary>
/// Gets an <see cref="Enumerator"/> for this <see cref="ValueProviderResult"/>.
/// </summary>
/// <returns>An <see cref="Enumerator"/>.</returns>
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
/// <inheritdoc />
IEnumerator<string> IEnumerable<string>.GetEnumerator()
{
return GetEnumerator();
}
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// Converts the provided <see cref="ValueProviderResult"/> into a comma-separated string containing all
/// submitted values.
/// </summary>
/// <param name="result">The <see cref="ValueProviderResult"/>.</param>
public static explicit operator string(ValueProviderResult result)
{
if (result.Values == null)
{
return result.Value;
}
else if (result.Values.Length == 0)
{
return null;
}
else if (result.Values.Length == 1)
{
return result.Values[0];
}
else
{
return string.Join(",", result.Values);
}
}
/// <summary>
/// Converts the provided <see cref="ValueProviderResult"/> into a an array of <see cref="string"/> containing
/// all submitted values.
/// </summary>
/// <param name="result">The <see cref="ValueProviderResult"/>.</param>
public static explicit operator string[](ValueProviderResult result)
{
if (result.Values != null)
{
return result.Values;
}
else if (result.Value != null)
{
return new string[] { result.Value };
}
else
{
return None.Values;
}
}
/// <summary>
/// Compares two <see cref="ValueProviderResult"/> objects for equality.
/// </summary>
/// <param name="x">A <see cref="ValueProviderResult"/>.</param>
/// <param name="y">A <see cref="ValueProviderResult"/>.</param>
/// <returns><c>true</c> if the values are equal, otherwise <c>false</c>.</returns>
public static bool operator ==(ValueProviderResult x, ValueProviderResult y)
{
return x.Equals(y);
}
/// <summary>
/// Compares two <see cref="ValueProviderResult"/> objects for inequality.
/// </summary>
/// <param name="x">A <see cref="ValueProviderResult"/>.</param>
/// <param name="y">A <see cref="ValueProviderResult"/>.</param>
/// <returns><c>false</c> if the values are equal, otherwise <c>true</c>.</returns>
public static bool operator !=(ValueProviderResult x, ValueProviderResult y)
{
return !x.Equals(y);
}
/// <summary>
/// An enumerator for <see cref="ValueProviderResult"/>.
/// </summary>
public struct Enumerator : IEnumerator<string>
{
private readonly ValueProviderResult _result;
private readonly int _length;
private int _index;
/// <summary>
/// Creates a new <see cref="Enumerator"/>.
/// </summary>
/// <param name="result">The <see cref="ValueProviderResult"/>.</param>
public Enumerator(ValueProviderResult result)
{
_result = result;
_index = -1;
_length = result.Length;
Current = null;
}
/// <inheritdoc />
public string Current { get; private set; }
/// <inheritdoc />
object IEnumerator.Current => Current;
/// <inheritdoc />
public void Dispose()
{
}
/// <inheritdoc />
public bool MoveNext()
{
++_index;
if (_index < _length)
{
if (_result.Values != null)
{
Debug.Assert(_index < _result.Values.Length);
Current = _result.Values[_index];
return true;
}
else if (_result.Value != null && _index == 0)
{
Current = _result.Value;
return true;
}
else
{
return false;
}
}
Current = null;
return false;
}
/// <inheritdoc />
public void Reset()
{
_index = -1;
}
}
}
}

View File

@ -74,38 +74,6 @@ namespace Microsoft.AspNet.Mvc.Abstractions
return GetString("Validation_InvalidFieldCannotBeReset_ToSkipped");
}
/// <summary>
/// Cannot convert value '{0}' to enum type '{1}'.
/// </summary>
internal static string ValueProviderResult_CannotConvertEnum
{
get { return GetString("ValueProviderResult_CannotConvertEnum"); }
}
/// <summary>
/// Cannot convert value '{0}' to enum type '{1}'.
/// </summary>
internal static string FormatValueProviderResult_CannotConvertEnum(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ValueProviderResult_CannotConvertEnum"), p0, p1);
}
/// <summary>
/// The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types.
/// </summary>
internal static string ValueProviderResult_NoConverterExists
{
get { return GetString("ValueProviderResult_NoConverterExists"); }
}
/// <summary>
/// The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types.
/// </summary>
internal static string FormatValueProviderResult_NoConverterExists(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ValueProviderResult_NoConverterExists"), p0, p1);
}
/// <summary>
/// The maximum number of allowed model errors has been reached.
/// </summary>

View File

@ -129,12 +129,6 @@
<data name="Validation_InvalidFieldCannotBeReset_ToSkipped" xml:space="preserve">
<value>A field previously marked invalid should not be marked skipped.</value>
</data>
<data name="ValueProviderResult_CannotConvertEnum" xml:space="preserve">
<value>Cannot convert value '{0}' to enum type '{1}'.</value>
</data>
<data name="ValueProviderResult_NoConverterExists" xml:space="preserve">
<value>The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types.</value>
</data>
<data name="ModelStateDictionary_MaxModelStateErrors" xml:space="preserve">
<value>The maximum number of allowed model errors has been reached.</value>
</data>

View File

@ -57,6 +57,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
var previousCount = bindingContext.ModelState.ErrorCount;
var model = await formatter.ReadAsync(formatterContext);
bindingContext.ModelState.SetModelValue(modelBindingKey, rawValue: model, attemptedValue: null);
if (bindingContext.ModelState.ErrorCount != previousCount)
{
@ -65,9 +67,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return new ModelBindingResult(modelBindingKey);
}
var valueProviderResult = new ValueProviderResult(rawValue: model);
bindingContext.ModelState.SetModelValue(modelBindingKey, valueProviderResult);
var validationNode = new ModelValidationNode(modelBindingKey, bindingContext.ModelMetadata, model)
{
ValidateAllProperties = true

View File

@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Check for missing data case 1: There was no <input ... /> element containing this data.
var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
if (valueProviderResult == null)
if (valueProviderResult == ValueProviderResult.None)
{
return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
}
@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
// Check for missing data case 2: There was an <input ... /> element but it was left blank.
var value = valueProviderResult.AttemptedValue;
var value = valueProviderResult.FirstValue;
if (string.IsNullOrEmpty(value))
{
return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);

View File

@ -56,31 +56,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
CollectionResult result;
if (valueProviderResult == null)
if (valueProviderResult == ValueProviderResult.None)
{
result = await BindComplexCollection(bindingContext);
}
else
{
if (valueProviderResult.RawValue == null)
{
// Value exists but is null. Handle similarly to fallback case above. This avoids a
// ModelBindingResult with IsModelSet = true but ValidationNode = null.
model = bindingContext.Model ?? CreateEmptyCollection(bindingContext.ModelType);
var validationNode =
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, model);
return new ModelBindingResult(
model,
bindingContext.ModelName,
isModelSet: true,
validationNode: validationNode);
}
result = await BindSimpleCollection(
bindingContext,
valueProviderResult.RawValue,
valueProviderResult.Culture);
result = await BindSimpleCollection(bindingContext, valueProviderResult);
}
var boundCollection = result.Model;
@ -94,6 +76,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
CopyToModel(model, boundCollection);
}
if (valueProviderResult != ValueProviderResult.None)
{
// If we did simple binding, then modelstate should be updated to reflect what we bound for ModelName.
// If we did complex binding, there will already be an entry for each index.
bindingContext.ModelState.SetModelValue(
bindingContext.ModelName,
valueProviderResult);
}
return new ModelBindingResult(
model,
bindingContext.ModelName,
@ -147,8 +138,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Internal for testing.
internal async Task<CollectionResult> BindSimpleCollection(
ModelBindingContext bindingContext,
object rawValue,
CultureInfo culture)
ValueProviderResult values)
{
var boundCollection = new List<TElement>();
@ -159,8 +149,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelName,
bindingContext.ModelMetadata,
boundCollection);
var rawValueArray = RawValueToObjectArray(rawValue);
foreach (var rawValueElement in rawValueArray)
foreach (var value in values)
{
var innerBindingContext = ModelBindingContext.GetChildModelBindingContext(
bindingContext,
@ -169,7 +158,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
innerBindingContext.ValueProvider = new CompositeValueProvider
{
// our temporary provider goes at the front of the list
new ElementalValueProvider(bindingContext.ModelName, rawValueElement, culture),
new ElementalValueProvider(bindingContext.ModelName, value, values.Culture),
bindingContext.ValueProvider
};
@ -183,8 +172,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
validationNode.ChildNodes.Add(result.ValidationNode);
}
boundCollection.Add(ModelBindingHelper.CastOrDefault<TElement>(boundValue));
}
boundCollection.Add(ModelBindingHelper.CastOrDefault<TElement>(boundValue));
}
return new CollectionResult
@ -364,7 +354,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
IEnumerable<string> indexNames = null;
if (valueProviderResult != null)
{
var indexes = (string[])valueProviderResult.ConvertTo(typeof(string[]));
var indexes = (string[])valueProviderResult;
if (indexes != null && indexes.Length > 0)
{
indexNames = indexes;

View File

@ -86,12 +86,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
var valueProvider = Items[i];
var result = await valueProvider.GetValueAsync(key);
if (result != null)
if (result != ValueProviderResult.None)
{
return result;
}
}
return null;
return ValueProviderResult.None;
}
/// <inheritdoc />

View File

@ -30,21 +30,23 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
_values = values;
}
protected PrefixContainer PrefixContainer
{
get
{
if (_prefixContainer == null)
{
_prefixContainer = new PrefixContainer(_values.Keys);
}
return _prefixContainer;
}
}
/// <inheritdoc />
public override Task<bool> ContainsPrefixAsync(string key)
{
var prefixContainer = GetOrCreatePrefixContainer();
return Task.FromResult(prefixContainer.ContainsPrefix(key));
}
private PrefixContainer GetOrCreatePrefixContainer()
{
if (_prefixContainer == null)
{
_prefixContainer = new PrefixContainer(_values.Keys);
}
return _prefixContainer;
return Task.FromResult(PrefixContainer.ContainsPrefix(key));
}
/// <inheritdoc />
@ -54,12 +56,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ValueProviderResult result;
if (_values.TryGetValue(key, out value))
{
var attemptedValue = value != null ? value.ToString() : null;
result = new ValueProviderResult(value, attemptedValue, CultureInfo.InvariantCulture);
var stringValue = value as string ?? value?.ToString() ?? string.Empty;
result = new ValueProviderResult(stringValue, CultureInfo.InvariantCulture);
}
else
{
result = null;
result = ValueProviderResult.None;
}
return Task.FromResult(result);

View File

@ -65,15 +65,18 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var modelBinder = bindingContext.OperationBindingContext.ModelBinder;
var validationNode = result.ValidationNode;
foreach (var key in keys)
foreach (var kvp in keys)
{
var dictionaryKey = ConvertFromString(key.Key);
valueBindingContext.ModelName = key.Value;
// Use InvariantCulture to convert the key since ExpressionHelper.GetExpressionText() would use
// that culture when rendering a form.
var convertedKey = ModelBindingHelper.ConvertTo<TKey>(kvp.Key, culture: null);
valueBindingContext.ModelName = kvp.Value;
var valueResult = await modelBinder.BindModelAsync(valueBindingContext);
// Always add an entry to the dictionary but validate only if binding was successful.
model[dictionaryKey] = ModelBindingHelper.CastOrDefault<TValue>(valueResult?.Model);
model[convertedKey] = ModelBindingHelper.CastOrDefault<TValue>(valueResult?.Model);
if (valueResult != null && valueResult.IsModelSet)
{
validationNode.ChildNodes.Add(valueResult.ValidationNode);
@ -116,14 +119,5 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return CreateInstance(targetType);
}
private static TKey ConvertFromString(string keyString)
{
// Use InvariantCulture to convert string since ExpressionHelper.GetExpressionText() used that culture.
var keyResult = new ValueProviderResult(keyString);
var keyObject = keyResult.ConvertTo(typeof(TKey));
return ModelBindingHelper.CastOrDefault<TKey>(keyObject);
}
}
}

View File

@ -7,33 +7,36 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
// Represents a value provider that contains a single value.
internal sealed class ElementalValueProvider : IValueProvider
public class ElementalValueProvider : IValueProvider
{
public ElementalValueProvider(string name, object rawValue, CultureInfo culture)
public ElementalValueProvider(string key, string value, CultureInfo culture)
{
Name = name;
RawValue = rawValue;
Key = key;
Value = value;
Culture = culture;
}
public CultureInfo Culture { get; private set; }
public CultureInfo Culture { get; }
public string Name { get; private set; }
public string Key { get; }
public object RawValue { get; private set; }
public string Value { get; }
public Task<bool> ContainsPrefixAsync(string prefix)
{
return Task.FromResult(PrefixContainer.IsPrefixMatch(prefix, Name));
return Task.FromResult(PrefixContainer.IsPrefixMatch(prefix, Key));
}
public Task<ValueProviderResult> GetValueAsync(string key)
{
var result = string.Equals(key, Name, StringComparison.OrdinalIgnoreCase) ?
new ValueProviderResult(RawValue, Convert.ToString(RawValue, Culture), Culture) :
null;
return Task.FromResult(result);
if (string.Equals(key, Key, StringComparison.OrdinalIgnoreCase))
{
return Task.FromResult(new ValueProviderResult(Value, Culture));
}
else
{
return Task.FromResult(ValueProviderResult.None);
}
}
}
}

View File

@ -48,8 +48,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
SuppressValidation = true,
};
var valueProviderResult = new ValueProviderResult(rawValue: value);
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
bindingContext.ModelState.SetModelValue(
bindingContext.ModelName,
rawValue: null,
attemptedValue: null);
}
return new ModelBindingResult(

View File

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
#if DNXCORE50
using System.Reflection;
#endif
@ -60,10 +60,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
bindingContext.ModelName,
bindingContext.ModelMetadata,
model);
var attemptedValue = (model as string) ?? request.Headers.Get(headerName);
var valueProviderResult = new ValueProviderResult(model, attemptedValue, CultureInfo.InvariantCulture);
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
bindingContext.ModelState.SetModelValue(
bindingContext.ModelName,
request.Headers.GetCommaSeparatedValues(headerName).ToArray(),
request.Headers.Get(headerName));
}
return Task.FromResult(

View File

@ -73,16 +73,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
string[] values;
if (dictionary.TryGetValue(key, out values) && values != null && values.Length > 0)
{
// Success.
if (values.Length == 1)
{
return new ValueProviderResult(values[0], values[0], Culture);
}
return new ValueProviderResult(values, string.Join(",", values), Culture);
return new ValueProviderResult(values, Culture);
}
return null;
return ValueProviderResult.None;
}
private async Task<IDictionary<string, string[]>> GetDictionary()

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.Framework.Internal;
@ -85,16 +86,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ValueProviderResult result;
if (values == null)
{
result = null;
}
else if (values.Count == 1)
{
var value = (string)values[0];
result = new ValueProviderResult(value, value, _culture);
result = ValueProviderResult.None;
}
else
{
result = new ValueProviderResult(values, _values.Get(key), _culture);
result = new ValueProviderResult(values.ToArray(), _culture);
}
return result;

View File

@ -8,12 +8,10 @@ using Microsoft.AspNet.Mvc.Core;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
public sealed class TypeConverterModelBinder : IModelBinder
public class SimpleTypeModelBinder : IModelBinder
{
public async Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
{
ModelBindingHelper.ValidateBindingContext(bindingContext);
if (bindingContext.ModelMetadata.IsComplexType)
{
// this type cannot be converted
@ -21,38 +19,48 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
if (valueProviderResult == null)
if (valueProviderResult == ValueProviderResult.None)
{
// no entry
return null;
}
object newModel;
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
try
{
newModel = valueProviderResult.ConvertTo(bindingContext.ModelType);
ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref newModel);
var model = valueProviderResult.ConvertTo(bindingContext.ModelType);
if (bindingContext.ModelType == typeof(string))
{
var modelAsString = model as string;
if (bindingContext.ModelMetadata.ConvertEmptyStringToNull &&
string.IsNullOrWhiteSpace(modelAsString))
{
model = null;
}
}
var isModelSet = true;
// When converting newModel a null value may indicate a failed conversion for an otherwise required
// model (can't set a ValueType to null). This detects if a null model value is acceptable given the
// current bindingContext. If not, an error is logged.
if (newModel == null && !AllowsNullValue(bindingContext.ModelType))
if (model == null && !AllowsNullValue(bindingContext.ModelType))
{
bindingContext.ModelState.TryAddModelError(
bindingContext.ModelName,
Resources.FormatCommon_ValueNotValidForProperty(newModel));
Resources.FormatCommon_ValueNotValidForProperty(model));
isModelSet = false;
}
// Include a ModelValidationNode if binding succeeded.
var validationNode = isModelSet ?
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, newModel) :
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, model) :
null;
return new ModelBindingResult(newModel, bindingContext.ModelName, isModelSet, validationNode);
return new ModelBindingResult(model, bindingContext.ModelName, isModelSet, validationNode);
}
catch (Exception ex)
{

View File

@ -1,67 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
public sealed class TypeMatchModelBinder : IModelBinder
{
public async Task<ModelBindingResult> BindModelAsync(ModelBindingContext bindingContext)
{
var valueProviderResult = await GetCompatibleValueProviderResult(bindingContext);
if (valueProviderResult == null)
{
// conversion would have failed
return null;
}
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
var model = valueProviderResult.RawValue;
ModelBindingHelper.ReplaceEmptyStringWithNull(bindingContext.ModelMetadata, ref model);
var validationNode = new ModelValidationNode(
bindingContext.ModelName,
bindingContext.ModelMetadata,
model);
return new ModelBindingResult(
model,
bindingContext.ModelName,
isModelSet: true,
validationNode: validationNode);
}
internal static async Task<ValueProviderResult> GetCompatibleValueProviderResult(ModelBindingContext context)
{
ModelBindingHelper.ValidateBindingContext(context);
var valueProviderResult = await context.ValueProvider.GetValueAsync(context.ModelName);
if (valueProviderResult == null)
{
return null; // the value doesn't exist
}
if (!IsCompatibleWith(context.ModelType, valueProviderResult.RawValue))
{
return null; // value is of incompatible type
}
return valueProviderResult;
}
private static bool IsCompatibleWith([NotNull] Type type, object value)
{
if (value == null)
{
return !type.GetTypeInfo().IsValueType || Nullable.GetUnderlyingType(type) != null;
}
else
{
return type.GetTypeInfo().IsAssignableFrom(value.GetType().GetTypeInfo());
}
}
}
}

View File

@ -0,0 +1,42 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Mvc.ModelBinding
{
/// <summary>
/// Extensions methods for <see cref="ValueProviderResult"/>.
/// </summary>
public static class ValueProviderResultExtensions
{
/// <summary>
/// Attempts to convert the values in <paramref name="result"/> to the specified type.
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> for conversion.</typeparam>
/// <param name="result">The <see cref="ValueProviderResult"/>.</param>
/// <returns>
/// The converted value, or the default value of <typeparamref name="T"/> if the value could not be converted.
/// </returns>
public static T ConvertTo<T>(this ValueProviderResult result)
{
var valueToConvert = (object)result.Values ?? (object)result.Value;
return ModelBindingHelper.ConvertTo<T>(valueToConvert, result.Culture);
}
/// <summary>
/// Attempts to convert the values in <paramref name="result"/> to the specified type.
/// </summary>
/// <param name="result">The <see cref="ValueProviderResult"/>.</param>
/// <param name="type">The <see cref="Type"/> for conversion.</param>
/// <returns>
/// The converted value, or the default value of <paramref name="type"/> if the value could not be converted.
/// </returns>
public static object ConvertTo(this ValueProviderResult result, [NotNull] Type type)
{
var valueToConvert = (object)result.Values ?? (object)result.Value;
return ModelBindingHelper.ConvertTo(valueToConvert, type, result.Culture);
}
}
}

View File

@ -2,10 +2,14 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.Core;
@ -488,16 +492,6 @@ namespace Microsoft.AspNet.Mvc
return (model is TModel) ? (TModel)model : default(TModel);
}
internal static void ReplaceEmptyStringWithNull(ModelMetadata modelMetadata, ref object model)
{
if (model is string &&
modelMetadata.ConvertEmptyStringToNull &&
string.IsNullOrWhiteSpace(model as string))
{
model = null;
}
}
public static object ConvertValuesToCollectionType<T>(Type modelType, IList<T> values)
{
// There's a limited set of collection types we can support here.
@ -539,5 +533,196 @@ namespace Microsoft.AspNet.Mvc
return null;
}
}
/// <summary>
/// Converts the provided <paramref name="value"/> to a value of <see cref="Type"/> <typeparamref name="T"/>
/// using the <see cref="CultureInfo.InvariantCulture"/>.
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> for conversion.</typeparam>
/// <param name="value">The value to convert."/></param>
/// <returns>
/// The converted value or the default value of <typeparamref name="T"/> if the value could not be converted.
/// </returns>
public static T ConvertTo<T>(object value)
{
return ConvertTo<T>(value, culture: null);
}
/// <summary>
/// Converts the provided <paramref name="value"/> to a value of <see cref="Type"/> <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The <see cref="Type"/> for conversion.</typeparam>
/// <param name="value">The value to convert."/></param>
/// <param name="culture">The <see cref="CultureInfo"/> for conversion.</param>
/// <returns>
/// The converted value or the default value of <typeparamref name="T"/> if the value could not be converted.
/// </returns>
public static T ConvertTo<T>(object value, CultureInfo culture)
{
var converted = ConvertTo(value, typeof(T), culture);
return converted == null ? default(T) : (T)converted;
}
/// <summary>
/// Converts the provided <paramref name="value"/> to a value of <see cref="Type"/> <param name="type"/>
/// using the <see cref="CultureInfo.InvariantCulture"/>.
/// </summary>
/// <param name="value">The value to convert."/></param>
/// <param name="type">The <see cref="Type"/> for conversion.</param>
/// <returns>
/// The converted value or <c>null</c> if the value could not be converted.
/// </returns>
public static object ConvertTo(object value, [NotNull] Type type)
{
return ConvertTo(value, type, culture: null);
}
/// <summary>
/// Converts the provided <paramref name="value"/> to a value of <see cref="Type"/> <paramref name="type"/>.
/// </summary>
/// <param name="value">The value to convert."/></param>
/// <param name="type">The <see cref="Type"/> for conversion.</param>
/// <param name="culture">The <see cref="CultureInfo"/> for conversion.</param>
/// <returns>
/// The converted value or <c>null</c> if the value could not be converted.
/// </returns>
public static object ConvertTo(object value, [NotNull] Type type, CultureInfo culture)
{
if (value == null)
{
// For value types, treat null values as though they were the default value for the type.
return type.GetTypeInfo().IsValueType ? Activator.CreateInstance(type) : null;
}
if (value.GetType().IsAssignableFrom(type))
{
return value;
}
var cultureToUse = culture ?? CultureInfo.InvariantCulture;
return UnwrapPossibleArrayType(value, type, cultureToUse);
}
private static object UnwrapPossibleArrayType(object value, Type destinationType, CultureInfo culture)
{
// array conversion results in four cases, as below
var valueAsArray = value as Array;
if (destinationType.IsArray)
{
var destinationElementType = destinationType.GetElementType();
if (valueAsArray != null)
{
// case 1: both destination + source type are arrays, so convert each element
var converted = (IList)Array.CreateInstance(destinationElementType, valueAsArray.Length);
for (var i = 0; i < valueAsArray.Length; i++)
{
converted[i] = ConvertSimpleType(valueAsArray.GetValue(i), destinationElementType, culture);
}
return converted;
}
else
{
// case 2: destination type is array but source is single element, so wrap element in
// array + convert
var element = ConvertSimpleType(value, destinationElementType, culture);
var converted = (IList)Array.CreateInstance(destinationElementType, 1);
converted[0] = element;
return converted;
}
}
else if (valueAsArray != null)
{
// case 3: destination type is single element but source is array, so extract first element + convert
if (valueAsArray.Length > 0)
{
value = valueAsArray.GetValue(0);
return ConvertSimpleType(value, destinationType, culture);
}
else
{
// case 3(a): source is empty array, so can't perform conversion
return null;
}
}
// case 4: both destination + source type are single elements, so convert
return ConvertSimpleType(value, destinationType, culture);
}
private static object ConvertSimpleType(object value, Type destinationType, CultureInfo culture)
{
if (value == null || value.GetType().IsAssignableFrom(destinationType))
{
return value;
}
// In case of a Nullable object, we try again with its underlying type.
destinationType = UnwrapNullableType(destinationType);
// if this is a user-input value but the user didn't type anything, return no value
var valueAsString = value as string;
if (valueAsString != null && string.IsNullOrWhiteSpace(valueAsString))
{
return null;
}
var converter = TypeDescriptor.GetConverter(destinationType);
var canConvertFrom = converter.CanConvertFrom(value.GetType());
if (!canConvertFrom)
{
converter = TypeDescriptor.GetConverter(value.GetType());
}
if (!(canConvertFrom || converter.CanConvertTo(destinationType)))
{
// EnumConverter cannot convert integer, so we verify manually
if (destinationType.GetTypeInfo().IsEnum &&
(value is int ||
value is uint ||
value is long ||
value is ulong ||
value is short ||
value is ushort ||
value is byte ||
value is sbyte))
{
return Enum.ToObject(destinationType, value);
}
throw new InvalidOperationException(
Resources.FormatValueProviderResult_NoConverterExists(value.GetType(), destinationType));
}
try
{
return canConvertFrom
? converter.ConvertFrom(null, culture, value)
: converter.ConvertTo(null, culture, value, destinationType);
}
catch (FormatException)
{
throw;
}
catch (Exception ex)
{
if (ex.InnerException == null)
{
throw;
}
else
{
// TypeConverter throws System.Exception wrapping the FormatException,
// so we throw the inner exception.
ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
// This code is never reached because the previous line will always throw.
throw;
}
}
}
private static Type UnwrapNullableType(Type destinationType)
{
return Nullable.GetUnderlyingType(destinationType) ?? destinationType;
}
}
}

View File

@ -28,8 +28,7 @@ namespace Microsoft.AspNet.Mvc
options.ModelBinders.Add(new ServicesModelBinder());
options.ModelBinders.Add(new BodyModelBinder());
options.ModelBinders.Add(new HeaderModelBinder());
options.ModelBinders.Add(new TypeConverterModelBinder());
options.ModelBinders.Add(new TypeMatchModelBinder());
options.ModelBinders.Add(new SimpleTypeModelBinder());
options.ModelBinders.Add(new CancellationTokenModelBinder());
options.ModelBinders.Add(new ByteArrayModelBinder());
options.ModelBinders.Add(new FormFileModelBinder());

View File

@ -1162,6 +1162,38 @@ namespace Microsoft.AspNet.Mvc.Core
return string.Format(CultureInfo.CurrentCulture, GetString("ValidatableObjectAdapter_IncompatibleType"), p0, p1);
}
/// <summary>
/// Cannot convert value '{0}' to enum type '{1}'.
/// </summary>
internal static string ValueProviderResult_CannotConvertEnum
{
get { return GetString("ValueProviderResult_CannotConvertEnum"); }
}
/// <summary>
/// Cannot convert value '{0}' to enum type '{1}'.
/// </summary>
internal static string FormatValueProviderResult_CannotConvertEnum(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ValueProviderResult_CannotConvertEnum"), p0, p1);
}
/// <summary>
/// The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types.
/// </summary>
internal static string ValueProviderResult_NoConverterExists
{
get { return GetString("ValueProviderResult_NoConverterExists"); }
}
/// <summary>
/// The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types.
/// </summary>
internal static string FormatValueProviderResult_NoConverterExists(object p0, object p1)
{
return string.Format(CultureInfo.CurrentCulture, GetString("ValueProviderResult_NoConverterExists"), p0, p1);
}
private static string GetString(string name, params string[] formatterNames)
{
var value = _resourceManager.GetString(name);

View File

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@ -342,4 +342,10 @@
<data name="ValidatableObjectAdapter_IncompatibleType" xml:space="preserve">
<value>The model object inside the metadata claimed to be compatible with '{0}', but was actually '{1}'.</value>
</data>
<data name="ValueProviderResult_CannotConvertEnum" xml:space="preserve">
<value>Cannot convert value '{0}' to enum type '{1}'.</value>
</data>
<data name="ValueProviderResult_NoConverterExists" xml:space="preserve">
<value>The parameter conversion from type '{0}' to type '{1}' failed because no type converter can convert between these types.</value>
</data>
</root>

View File

@ -506,9 +506,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
viewContext.ViewData.ModelState.TryGetValue(fullName, out modelState);
var value = string.Empty;
if (modelState != null && modelState.Value != null)
if (modelState != null && modelState.AttemptedValue != null)
{
value = modelState.Value.AttemptedValue;
value = modelState.AttemptedValue;
}
else if (modelExplorer.Model != null)
{
@ -940,9 +940,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
internal static object GetModelStateValue(ViewContext viewContext, string key, Type destinationType)
{
ModelState modelState;
if (viewContext.ViewData.ModelState.TryGetValue(key, out modelState) && modelState.Value != null)
if (viewContext.ViewData.ModelState.TryGetValue(key, out modelState) && modelState.RawValue != null)
{
return modelState.Value.ConvertTo(destinationType, culture: null);
return ModelBindingHelper.ConvertTo(modelState.RawValue, destinationType, culture: null);
}
return null;

View File

@ -24,8 +24,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
return string.Empty;
}
var attemptedValue = (modelState.Value != null) ? modelState.Value.AttemptedValue : "null";
var attemptedValue = modelState.AttemptedValue ?? "null";
return Resources.FormatCommon_ValueNotValidForProperty(attemptedValue);
}

View File

@ -18,7 +18,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var modelState = new ModelState
{
Value = GetValueProviderResult("value"),
ValidationState = validationState
};
@ -40,7 +39,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var modelState = new ModelState
{
Value = GetValueProviderResult("value"),
ValidationState = ModelValidationState.Valid
};
@ -63,7 +61,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var modelState = new ModelState
{
Value = GetValueProviderResult("value"),
ValidationState = ModelValidationState.Invalid
};
@ -89,7 +86,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var modelState = new ModelState
{
Value = GetValueProviderResult("value"),
ValidationState = validationState
};
@ -126,7 +122,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var modelState = new ModelState
{
Value = GetValueProviderResult("value"),
ValidationState = ModelValidationState.Invalid
};
@ -148,10 +143,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public void CopyConstructor_CopiesModelStateData()
{
// Arrange
var modelState = new ModelState
{
Value = GetValueProviderResult("value")
};
var modelState = new ModelState();
var source = new ModelStateDictionary
{
{ "key", modelState }
@ -211,7 +203,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var oldDictionary = new ModelStateDictionary()
{
{ "foo", new ModelState() { Value = GetValueProviderResult("bar", "bar") } }
{ "foo", new ModelState() { RawValue = "bar" } }
};
// Act
@ -219,7 +211,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Assert
Assert.Single(newDictionary);
Assert.Equal("bar", newDictionary["foo"].Value.ConvertTo(typeof(string)));
Assert.Equal("bar", newDictionary["foo"].RawValue);
}
[Fact]
@ -238,7 +230,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
[Fact]
public void GetValidationState_ReturnsValidationStateForKey_IgnoresChildren()
{
// Arrange
// Arrange
var msd = new ModelStateDictionary();
msd.AddModelError("foo.bar", "error text");
@ -277,7 +269,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var validState = new ModelState
{
Value = new ValueProviderResult(rawValue: null),
ValidationState = ModelValidationState.Valid
};
var msd = new ModelStateDictionary
@ -316,7 +307,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var validState = new ModelState
{
Value = new ValueProviderResult(rawValue: null),
ValidationState = ModelValidationState.Valid
};
var msd = new ModelStateDictionary
@ -337,12 +327,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var errorState = new ModelState
{
Value = GetValueProviderResult("quux", "quux"),
ValidationState = ModelValidationState.Invalid
};
var validState = new ModelState
{
Value = GetValueProviderResult("bar", "bar"),
ValidationState = ModelValidationState.Valid
};
errorState.Errors.Add("some error");
@ -370,13 +358,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{ "foo", new ModelState
{
ValidationState = ModelValidationState.Valid,
Value = GetValueProviderResult("bar", "bar")
}
},
{ "baz", new ModelState
{
ValidationState = ModelValidationState.Skipped,
Value = GetValueProviderResult("quux", "bar")
}
}
};
@ -396,12 +382,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var errorState = new ModelState
{
Value = GetValueProviderResult("quux", "quux"),
ValidationState = ModelValidationState.Invalid
};
var validState = new ModelState
{
Value = GetValueProviderResult("bar", "bar"),
ValidationState = ModelValidationState.Valid
};
errorState.Errors.Add("some error");
@ -409,7 +393,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
{ "foo", validState },
{ "baz", errorState },
{ "qux", new ModelState { Value = GetValueProviderResult() }}
{ "qux", new ModelState() }
};
// Act
@ -457,14 +441,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var dictionary = new ModelStateDictionary();
// Act
dictionary.SetModelValue("some key", GetValueProviderResult("some value", "some value"));
dictionary.SetModelValue("some key", new string[] { "some value" }, "some value");
// Assert
Assert.Single(dictionary);
var modelState = dictionary["some key"];
Assert.Empty(modelState.Errors);
Assert.Equal("some value", modelState.Value.ConvertTo(typeof(string)));
Assert.Equal(new string[] { "some value" }, modelState.RawValue);
Assert.Equal("some value", modelState.AttemptedValue);
}
[Fact]
@ -476,7 +461,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var ex = new Exception();
// Act
dictionary.SetModelValue("some key", GetValueProviderResult("some value", "some value"));
dictionary.SetModelValue("some key", new string[] { "some value" }, "some value");
// Assert
Assert.Single(dictionary);
@ -484,7 +469,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Assert.Single(modelState.Errors);
Assert.Equal("some error", modelState.Errors[0].ErrorMessage);
Assert.Equal("some value", modelState.Value.ConvertTo(typeof(string)));
Assert.Equal(new string[] { "some value" }, modelState.RawValue);
Assert.Equal("some value", modelState.AttemptedValue);
}
[Fact]
@ -492,7 +478,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
// Arrange
var dictionary = new ModelStateDictionary();
dictionary.SetModelValue("user.Name", GetValueProviderResult());
dictionary.SetModelValue("user.Name", new string[] { "some value" }, "some value");
// Act
var validationState = dictionary.GetFieldValidationState("not-user");
@ -507,7 +493,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var dictionary = new ModelStateDictionary();
dictionary["user.Address"] = new ModelState { ValidationState = ModelValidationState.Valid };
dictionary.SetModelValue("user.Name", GetValueProviderResult());
dictionary.SetModelValue("user.Name", new string[] { "some value" }, "some value");
dictionary.AddModelError("user.Age", "Age is not a valid int");
// Act
@ -745,7 +731,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var expected = "The value 'some value' is not valid for key.";
var dictionary = new ModelStateDictionary();
dictionary.SetModelValue("key", GetValueProviderResult());
dictionary.SetModelValue("key", new string[] { "some value" }, "some value");
// Act
dictionary.TryAddModelError("key", new FormatException());
@ -760,7 +746,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
// Arrange
var dictionary = new ModelStateDictionary();
dictionary.SetModelValue("key", GetValueProviderResult());
dictionary.SetModelValue("key", new string[] { "some value" }, "some value");
// Act
dictionary.TryAddModelError("key", new InvalidOperationException());
@ -905,12 +891,5 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Assert.Equal(0, dictionary["Property4"].Errors.Count);
Assert.Equal(ModelValidationState.Unvalidated, dictionary["Property4"].ValidationState);
}
private static ValueProviderResult GetValueProviderResult(object rawValue = null, string attemptedValue = null)
{
return new ValueProviderResult(rawValue ?? "some value",
attemptedValue ?? "some value",
CultureInfo.InvariantCulture);
}
}
}

View File

@ -1,9 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding
@ -11,563 +8,190 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public class ValueProviderResultTest
{
[Fact]
public void ConvertTo_ReturnsNullForReferenceTypes_WhenValueIsNull()
public void Construct_With_NullString()
{
var valueProviderResult = new ValueProviderResult(rawValue: null);
// Arrange & Act
var result = new ValueProviderResult((string)null);
var convertedValue = valueProviderResult.ConvertTo(typeof(string));
Assert.Null(convertedValue);
// Assert
Assert.Equal(0, result.Length);
Assert.Null(result.Value);
Assert.Empty(result.Values);
Assert.Null(result.FirstValue);
Assert.Equal(ValueProviderResult.None, result);
Assert.Null((string)result);
Assert.Empty((string[])result);
}
[Fact]
public void ConvertTo_ReturnsDefaultForValueTypes_WhenValueIsNull()
public void Construct_With_NullArray()
{
var valueProviderResult = new ValueProviderResult(rawValue: null);
// Arrange & Act
var result = new ValueProviderResult((string[])null);
var convertedValue = valueProviderResult.ConvertTo(typeof(int));
Assert.Equal(0, convertedValue);
// Assert
Assert.Equal(0, result.Length);
Assert.Null(result.Value);
Assert.Empty(result.Values);
Assert.Null(result.FirstValue);
Assert.Equal(ValueProviderResult.None, result);
Assert.Null((string)result);
Assert.Empty((string[])result);
}
[Fact]
public void ConvertToCanConvertArraysToSingleElements()
public void Construct_With_None()
{
// Arrange
var valueProviderResult = new ValueProviderResult(
new int[] { 1, 20, 42 },
string.Empty,
CultureInfo.InvariantCulture);
// Act
var converted = (string)valueProviderResult.ConvertTo(typeof(string));
// Arrange & Act
var result = ValueProviderResult.None;
// Assert
Assert.Equal("1", converted);
Assert.Equal(0, result.Length);
Assert.Null(result.Value);
Assert.Empty(result.Values);
Assert.Null(result.FirstValue);
Assert.Equal(ValueProviderResult.None, result);
Assert.Null((string)result);
Assert.Empty((string[])result);
}
[Fact]
public void ConvertToCanConvertSingleElementsToArrays()
public void Construct_With_String()
{
// Arrange
var valueProviderResult = new ValueProviderResult(42, string.Empty, CultureInfo.InvariantCulture);
// Act
var converted = (string[])valueProviderResult.ConvertTo(typeof(string[]));
// Arrange & Act
var result = new ValueProviderResult("Hi There");
// Assert
Assert.NotNull(converted);
var result = Assert.Single(converted);
Assert.Equal("42", result);
Assert.Equal(1, result.Length);
Assert.Equal("Hi There", result.Value);
Assert.Null(result.Values);
Assert.Equal("Hi There", result.FirstValue);
Assert.NotEqual(ValueProviderResult.None, result);
Assert.Equal("Hi There", (string)result);
Assert.Equal(new string[] { "Hi There" }, (string[])result);
}
[Fact]
public void ConvertToCanConvertSingleElementsToSingleElements()
public void Construct_With_Array()
{
// Arrange
var valueProviderResult = new ValueProviderResult(42, string.Empty, CultureInfo.InvariantCulture);
// Act
var converted = (string)valueProviderResult.ConvertTo(typeof(string));
// Arrange & Act
var result = new ValueProviderResult(new string[] { "Hi", "There" });
// Assert
Assert.NotNull(converted);
Assert.Equal("42", converted);
}
[Fact]
public void ConvertingNullStringToNullableIntReturnsNull()
{
// Arrange
object original = null;
var valueProviderResult = new ValueProviderResult(original, string.Empty, CultureInfo.InvariantCulture);
// Act
var returned = (int?)valueProviderResult.ConvertTo(typeof(int?));
// Assert
Assert.Equal(returned, null);
}
[Fact]
public void ConvertingWhiteSpaceStringToNullableIntReturnsNull()
{
// Arrange
var original = " ";
var valueProviderResult = new ValueProviderResult(original, string.Empty, CultureInfo.InvariantCulture);
// Act
var returned = (int?)valueProviderResult.ConvertTo(typeof(int?));
// Assert
Assert.Equal(returned, null);
}
[Fact]
public void ConvertToReturnsNullIfArrayElementValueIsNull()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: new string[] { null });
// Act
var outValue = valueProviderResult.ConvertTo(typeof(int));
// Assert
Assert.Null(outValue);
}
[Fact]
public void ConvertToReturnsNullIfTryingToConvertEmptyArrayToSingleElement()
{
// Arrange
var valueProviderResult = new ValueProviderResult(new int[0], string.Empty, CultureInfo.InvariantCulture);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(int));
// Assert
Assert.Null(outValue);
}
[Theory]
[InlineData("")]
[InlineData(" \t \r\n ")]
public void ConvertToReturnsNullIfTrimmedValueIsEmptyString(object value)
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: value);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(int));
// Assert
Assert.Null(outValue);
}
[Fact]
public void ConvertToReturnsNullIfTrimmedValueIsEmptyString()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: null);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(int[]));
// Assert
Assert.Null(outValue);
}
[Fact]
public void ConvertToReturnsValueIfArrayElementIsIntegerAndDestinationTypeIsEnum()
{
// Arrange
var result = new ValueProviderResult(rawValue: new object[] { 1 });
// Act
var outValue = result.ConvertTo(typeof(IntEnum));
// Assert
Assert.Equal(outValue, IntEnum.Value1);
}
[Theory]
[InlineData(1, typeof(IntEnum), IntEnum.Value1)]
[InlineData(1L, typeof(LongEnum), LongEnum.Value1)]
[InlineData(long.MaxValue, typeof(LongEnum), LongEnum.MaxValue)]
[InlineData(1U, typeof(UnsignedIntEnum), UnsignedIntEnum.Value1)]
[InlineData(1UL, typeof(IntEnum), IntEnum.Value1)]
[InlineData((byte)1, typeof(ByteEnum), ByteEnum.Value1)]
[InlineData(byte.MaxValue, typeof(ByteEnum), ByteEnum.MaxValue)]
[InlineData((sbyte)1, typeof(ByteEnum), ByteEnum.Value1)]
[InlineData((short)1, typeof(IntEnum), IntEnum.Value1)]
[InlineData((ushort)1, typeof(IntEnum), IntEnum.Value1)]
[InlineData(int.MaxValue, typeof(IntEnum?), IntEnum.MaxValue)]
[InlineData(null, typeof(IntEnum?), null)]
[InlineData(1L, typeof(LongEnum?), LongEnum.Value1)]
[InlineData(null, typeof(LongEnum?), null)]
[InlineData(uint.MaxValue, typeof(UnsignedIntEnum?), UnsignedIntEnum.MaxValue)]
[InlineData((byte)1, typeof(ByteEnum?), ByteEnum.Value1)]
[InlineData(null, typeof(ByteEnum?), null)]
[InlineData((ushort)1, typeof(LongEnum?), LongEnum.Value1)]
public void ConvertToReturnsValueIfArrayElementIsAnyIntegerTypeAndDestinationTypeIsEnum(
object input,
Type enumType,
object expected)
{
// Arrange
var result = new ValueProviderResult(rawValue: new object[] { input });
// Act
var outValue = result.ConvertTo(enumType);
// Assert
Assert.Equal(expected, outValue);
}
[Fact]
public void ConvertToReturnsValueIfArrayElementIsStringValueAndDestinationTypeIsEnum()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: new object[] { "1" });
// Act
var outValue = valueProviderResult.ConvertTo(typeof(IntEnum));
// Assert
Assert.Equal(outValue, IntEnum.Value1);
}
[Fact]
public void ConvertToReturnsValueIfArrayElementIsStringKeyAndDestinationTypeIsEnum()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: new object[] { "Value1" });
// Act
var outValue = valueProviderResult.ConvertTo(typeof(IntEnum));
// Assert
Assert.Equal(outValue, IntEnum.Value1);
}
[Fact]
public void ConvertToReturnsValueIfElementIsStringAndDestinationIsNullableInteger()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: "12");
// Act
var outValue = valueProviderResult.ConvertTo(typeof(int?));
// Assert
Assert.Equal(12, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsStringAndDestinationIsNullableDouble()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: "12.5");
// Act
var outValue = valueProviderResult.ConvertTo(typeof(double?));
// Assert
Assert.Equal(12.5, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsDecimalAndDestinationIsNullableInteger()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: 12M);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(int?));
// Assert
Assert.Equal(12, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsDecimalAndDestinationIsNullableDouble()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: 12.5M);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(double?));
// Assert
Assert.Equal(12.5, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsDecimalDoubleAndDestinationIsNullableInteger()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: 12.5M);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(int?));
// Assert
Assert.Equal(12, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsDecimalDoubleAndDestinationIsNullableLong()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: 12.5M);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(long?));
// Assert
Assert.Equal(12L, outValue);
}
[Fact]
public void ConvertToReturnsValueIfArrayElementInstanceOfDestinationType()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: new object[] { "some string" });
// Act
var outValue = valueProviderResult.ConvertTo(typeof(string));
// Assert
Assert.Equal("some string", outValue);
}
[Theory]
[InlineData(new object[] { new[] { 1, 0 } })]
[InlineData(new object[] { new[] { "Value1", "Value0" } })]
[InlineData(new object[] { new[] { "Value1", "value0" } })]
public void ConvertTo_ConvertsEnumArrays(object value)
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: value);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(IntEnum[]));
// Assert
var result = Assert.IsType<IntEnum[]>(outValue);
Assert.Equal(2, result.Length);
Assert.Equal(IntEnum.Value1, result[0]);
Assert.Equal(IntEnum.Value0, result[1]);
}
[Theory]
[InlineData(new object[] { new[] { 1, 2 }, new[] { FlagsEnum.Value1, FlagsEnum.Value2 } })]
[InlineData(new object[] { new[] { "Value1", "Value2" }, new[] { FlagsEnum.Value1, FlagsEnum.Value2 } })]
[InlineData(new object[] { new[] { 5, 2 }, new[] { FlagsEnum.Value1 | FlagsEnum.Value4, FlagsEnum.Value2 } })]
public void ConvertTo_ConvertsFlagsEnumArrays(object value, FlagsEnum[] expected)
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: value);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(FlagsEnum[]));
// Assert
var result = Assert.IsType<FlagsEnum[]>(outValue);
Assert.Equal(2, result.Length);
Assert.Equal(expected[0], result[0]);
Assert.Equal(expected[1], result[1]);
Assert.Null(result.Value);
Assert.Equal(new string[] { "Hi", "There" }, result.Values);
Assert.Equal("Hi", result.FirstValue);
Assert.NotEqual(ValueProviderResult.None, result);
Assert.Equal("Hi,There", (string)result);
Assert.Equal(new string[] { "Hi", "There" }, (string[])result);
}
[Fact]
public void ConvertToReturnsValueIfInstanceOfDestinationType()
public void Enumerator_WithString()
{
// Arrange
var original = new[] { "some string" };
var valueProviderResult = new ValueProviderResult(rawValue: original);
// Act
var outValue = valueProviderResult.ConvertTo(typeof(string[]));
// Assert
Assert.Same(original, outValue);
}
[Theory]
[InlineData(typeof(int))]
[InlineData(typeof(double?))]
[InlineData(typeof(IntEnum?))]
public void ConvertToThrowsIfConverterThrows(Type destinationType)
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: "this-is-not-a-valid-value");
var result = new ValueProviderResult("Hi There");
// Act & Assert
var ex = Assert.Throws(typeof(FormatException), () => valueProviderResult.ConvertTo(destinationType));
Assert.Equal<string>(new string[] { "Hi There", }, result);
}
[Fact]
public void ConvertToThrowsIfNoConverterExists()
public void Enumerator_WithArray()
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: "x");
var destinationType = typeof(MyClassWithoutConverter);
var result = new ValueProviderResult(new string[] { "Hi", "There" });
// Act & Assert
var ex = Assert.Throws<InvalidOperationException>(() => valueProviderResult.ConvertTo(destinationType));
Assert.Equal("The parameter conversion from type 'System.String' to type " +
"'Microsoft.AspNet.Mvc.ModelBinding.ValueProviderResultTest+MyClassWithoutConverter' " +
"failed because no type converter can convert between these types.",
ex.Message);
Assert.Equal<string>(new string[] { "Hi", "There" }, result);
}
[Fact]
public void ConvertToUsesProvidedCulture()
{
// Arrange
var original = "12,5";
var valueProviderResult = new ValueProviderResult(
rawValue: original,
attemptedValue: null,
culture: new CultureInfo("en-GB"));
var frCulture = new CultureInfo("fr-FR");
// Act
var cultureResult = valueProviderResult.ConvertTo(typeof(decimal), frCulture);
// Assert
Assert.Equal(12.5M, cultureResult);
Assert.Throws<FormatException>(() => valueProviderResult.ConvertTo(typeof(decimal)));
}
[Fact]
public void CulturePropertyDefaultsToInvariantCulture()
{
// Arrange
var result = new ValueProviderResult(rawValue: null, attemptedValue: null, culture: null);
// Act & assert
Assert.Same(CultureInfo.InvariantCulture, result.Culture);
}
[Theory]
[MemberData(nameof(IntrinsicConversionData))]
public void ConvertToCanConvertIntrinsics<T>(object initialValue, T expectedValue)
{
// Arrange
var result = new ValueProviderResult(initialValue, string.Empty, CultureInfo.InvariantCulture);
// Act & Assert
Assert.Equal(expectedValue, result.ConvertTo(typeof(T)));
}
public static IEnumerable<object[]> IntrinsicConversionData
public static TheoryData<ValueProviderResult, ValueProviderResult, bool> EqualsData
{
get
{
yield return new object[] { 42, 42L };
yield return new object[] { 42, (short)42 };
yield return new object[] { 42, (float)42.0 };
yield return new object[] { 42, (double)42.0 };
yield return new object[] { 42M, 42 };
yield return new object[] { 42L, 42 };
yield return new object[] { 42, (byte)42 };
yield return new object[] { (short)42, 42 };
yield return new object[] { (float)42.0, 42 };
yield return new object[] { (double)42.0, 42 };
yield return new object[] { (byte)42, 42 };
yield return new object[] { "2008-01-01", new DateTime(2008, 01, 01) };
yield return new object[] { "00:00:20", TimeSpan.FromSeconds(20) };
yield return new object[]
return new TheoryData<ValueProviderResult, ValueProviderResult, bool>()
{
"c6687d3a-51f9-4159-8771-a66d2b7d7038",
Guid.Parse("c6687d3a-51f9-4159-8771-a66d2b7d7038")
{
new ValueProviderResult("Hi"),
new ValueProviderResult("Hi"),
true
},
{
new ValueProviderResult("Hi"),
new ValueProviderResult(new string[] { "Hi"}),
true
},
{
new ValueProviderResult(new string[] { "Hi"}),
new ValueProviderResult("Hi"),
true
},
{
new ValueProviderResult(new string[] { "Hi"}),
new ValueProviderResult(new string[] { "Hi"}),
true
},
{
new ValueProviderResult(new string[] { "Hi", "There"}),
new ValueProviderResult(new string[] { "Hi", "There"}),
true
},
{
new ValueProviderResult("Hi,There"),
new ValueProviderResult(new string[] { "Hi", "There"}),
false
},
{
new ValueProviderResult(new string[] { "Hi", string.Empty }),
new ValueProviderResult(new string[] { "Hi", "There"}),
false
},
{
new ValueProviderResult(new string[] { "Hi", "There" }),
new ValueProviderResult(new string[] { "Hi", "ThEre"}),
false
},
{
new ValueProviderResult(new string[] { "Hi", }),
new ValueProviderResult(new string[] { "Hi", string.Empty }),
false
},
{
new ValueProviderResult(),
new ValueProviderResult((string)null),
true
},
{
new ValueProviderResult(),
new ValueProviderResult("hi"),
false
},
};
}
}
[Theory]
[InlineData(typeof(TimeSpan))]
[InlineData(typeof(DateTime))]
[InlineData(typeof(DateTimeOffset))]
[InlineData(typeof(Guid))]
[InlineData(typeof(IntEnum))]
public void ConvertTo_Throws_IfValueIsNotStringData(Type destinationType)
[MemberData(nameof(EqualsData))]
public void Operator_Equals(ValueProviderResult x, ValueProviderResult y, bool expected)
{
// Arrange
var result = new ValueProviderResult(
new MyClassWithoutConverter(),
string.Empty,
CultureInfo.InvariantCulture);
var result = x == y;
// Act
var ex = Assert.Throws<InvalidOperationException>(() => result.ConvertTo(destinationType));
// Assert
var expectedMessage = string.Format("The parameter conversion from type '{0}' to type '{1}' " +
"failed because no type converter can convert between these types.",
typeof(MyClassWithoutConverter), destinationType);
Assert.Equal(expectedMessage, ex.Message);
}
[Fact]
public void ConvertTo_Throws_IfDestinationTypeIsNotConvertible()
{
// Arrange
var value = "Hello world";
var destinationType = typeof(MyClassWithoutConverter);
var result = new ValueProviderResult(value, string.Empty, CultureInfo.InvariantCulture);
// Act
var ex = Assert.Throws<InvalidOperationException>(() => result.ConvertTo(destinationType));
// Assert
var expectedMessage = string.Format("The parameter conversion from type '{0}' to type '{1}' " +
"failed because no type converter can convert between these types.",
value.GetType(), typeof(MyClassWithoutConverter));
Assert.Equal(expectedMessage, ex.Message);
// Act & Assert
Assert.Equal(expected, result);
}
[Theory]
[InlineData(new object[] { 2, FlagsEnum.Value2 })]
[InlineData(new object[] { 5, FlagsEnum.Value1 | FlagsEnum.Value4 })]
[InlineData(new object[] { 15, FlagsEnum.Value1 | FlagsEnum.Value2 | FlagsEnum.Value4 | FlagsEnum.Value8 })]
[InlineData(new object[] { 16, (FlagsEnum)16 })]
[InlineData(new object[] { 0, (FlagsEnum)0 })]
[InlineData(new object[] { null, (FlagsEnum)0 })]
[InlineData(new object[] { "Value1,Value2", (FlagsEnum)3 })]
[InlineData(new object[] { "Value1,Value2,value4, value8", (FlagsEnum)15 })]
public void ConvertTo_ConvertsEnumFlags(object value, object expected)
[MemberData(nameof(EqualsData))]
public void Operator_NotEquals(ValueProviderResult x, ValueProviderResult y, bool expected)
{
// Arrange
var valueProviderResult = new ValueProviderResult(rawValue: value);
var result = x != y;
// Act
var outValue = (FlagsEnum)valueProviderResult.ConvertTo(typeof(FlagsEnum));
// Assert
Assert.Equal(expected, outValue);
}
private class MyClassWithoutConverter
{
}
private enum IntEnum
{
Value0 = 0,
Value1 = 1,
MaxValue = int.MaxValue
}
private enum LongEnum : long
{
Value0 = 0L,
Value1 = 1L,
MaxValue = long.MaxValue
}
private enum UnsignedIntEnum : uint
{
Value0 = 0U,
Value1 = 1U,
MaxValue = uint.MaxValue
}
private enum ByteEnum : byte
{
Value0 = 0,
Value1 = 1,
MaxValue = byte.MaxValue
}
[Flags]
public enum FlagsEnum
{
Value1 = 1,
Value2 = 2,
Value4 = 4,
Value8 = 8
// Act & Assert
Assert.NotEqual(expected, result);
}
}
}
}

View File

@ -16,7 +16,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModelAsync_ValueProviderContainPrefix_Succeeds()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName[0]", "42" },
{ "someName[1]", "84" },
@ -138,7 +138,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModelAsync_ModelMetadataReadOnly_ReturnsNull(int[] model)
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName[0]", "42" },
{ "someName[1]", "84" },
@ -161,7 +161,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var arrayLength = model.Length;
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName[0]", "42" },
{ "someName[1]", "84" },
@ -196,7 +196,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
.Returns(async (ModelBindingContext mbc) =>
{
var value = await mbc.ValueProvider.GetValueAsync(mbc.ModelName);
if (value != null)
if (value != ValueProviderResult.None)
{
var model = value.ConvertTo(mbc.ModelType);
return new ModelBindingResult(model, key: null, isModelSet: true);

View File

@ -17,7 +17,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModelSetsModelToNullOnNullOrEmptyString(string value)
{
// Arrange
var valueProvider = new SimpleHttpValueProvider()
var valueProvider = new SimpleValueProvider()
{
{ "foo", value }
};
@ -36,15 +36,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var modelState = Assert.Single(bindingContext.ModelState);
Assert.Equal("foo", modelState.Key);
Assert.NotNull(modelState.Value.Value);
Assert.Equal(value, modelState.Value.Value.RawValue);
Assert.Equal(string.Empty, modelState.Value.RawValue);
}
[Fact]
public async Task BindModel()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider()
var valueProvider = new SimpleValueProvider()
{
{ "foo", "Fys1" }
};
@ -67,7 +66,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
// Arrange
var expected = "The value '\"Fys1\"' is not valid for foo.";
var valueProvider = new SimpleHttpValueProvider()
var valueProvider = new SimpleValueProvider()
{
{ "foo", "\"Fys1\"" }
};
@ -89,7 +88,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_ReturnsWithIsModelSetFalse_WhenValueNotFound()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider()
var valueProvider = new SimpleValueProvider()
{
{ "someName", "" }
};

View File

@ -53,7 +53,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
ModelMetadata = metadataProvider.GetMetadataForType(modelType),
ModelName = "someName",
ValueProvider = new SimpleHttpValueProvider(),
ValueProvider = new SimpleValueProvider(),
OperationBindingContext = new OperationBindingContext
{
ModelBinder = new CancellationTokenModelBinder(),

View File

@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindComplexCollectionFromIndexes_FiniteIndexes()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName[foo]", "42" },
{ "someName[baz]", "200" }
@ -45,7 +45,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindComplexCollectionFromIndexes_InfiniteIndexes()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName[0]", "42" },
{ "someName[1]", "100" },
@ -70,7 +70,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_ComplexCollection_Succeeds(bool isReadOnly)
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName.index", new[] { "foo", "bar", "baz" } },
{ "someName[foo]", "42" },
@ -100,7 +100,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_ComplexCollection_BindingContextModelNonNull_Succeeds(bool isReadOnly)
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName.index", new[] { "foo", "bar", "baz" } },
{ "someName[foo]", "42" },
@ -132,7 +132,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_SimpleCollection_Succeeds(bool isReadOnly)
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName", new[] { "42", "100", "200" } }
};
@ -149,8 +149,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var list = Assert.IsAssignableFrom<IList<int>>(result.Model);
Assert.Equal(new[] { 42, 100, 200 }, list.ToArray());
Assert.True(modelState.IsValid);
}
[Theory]
@ -159,7 +157,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_SimpleCollection_BindingContextModelNonNull_Succeeds(bool isReadOnly)
{
// Arrange
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName", new[] { "42", "100", "200" } }
};
@ -178,8 +176,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Assert.Same(list, result.Model);
Assert.Equal(new[] { 42, 100, 200 }, list.ToArray());
Assert.True(modelState.IsValid);
}
[Fact]
@ -187,7 +183,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var binder = new CollectionModelBinder<int>();
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "someName", null },
};
@ -205,8 +201,6 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var model = Assert.IsType<List<int>>(result.Model);
Assert.Empty(model);
Assert.True(modelState.IsValid);
}
#endif
@ -225,7 +219,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
};
// Act
var boundCollection = await binder.BindSimpleCollection(context, rawValue: new object[0], culture: null);
var boundCollection = await binder.BindSimpleCollection(context, new ValueProviderResult(new string[0]));
// Assert
Assert.NotNull(boundCollection.Model);
@ -392,7 +386,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var culture = new CultureInfo("fr-FR");
var bindingContext = GetModelBindingContext(new SimpleHttpValueProvider());
var bindingContext = GetModelBindingContext(new SimpleValueProvider());
ModelValidationNode childValidationNode = null;
Mock.Get<IModelBinder>(bindingContext.OperationBindingContext.ModelBinder)
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
@ -405,7 +399,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var modelBinder = new CollectionModelBinder<int>();
// Act
var boundCollection = await modelBinder.BindSimpleCollection(bindingContext, new int[1], culture);
var boundCollection = await modelBinder.BindSimpleCollection(
bindingContext,
new ValueProviderResult(new string[] { "0" }));
// Assert
Assert.Equal(new[] { 42 }, boundCollection.Model.ToArray());
@ -442,11 +438,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
.Returns(async (ModelBindingContext mbc) =>
{
var value = await mbc.ValueProvider.GetValueAsync(mbc.ModelName);
if (value != null)
if (value != ValueProviderResult.None)
{
var model = value.ConvertTo(mbc.ModelType);
var modelValidationNode = new ModelValidationNode(mbc.ModelName, mbc.ModelMetadata, model);
return new ModelBindingResult(model, mbc.ModelName, true, modelValidationNode);
return new ModelBindingResult(model, mbc.ModelName, model != null, modelValidationNode);
}
return null;

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(int)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider
ValueProvider = new SimpleValueProvider
{
{ "someName", "dummyValue" }
},
@ -71,7 +71,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
@ -121,7 +121,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
@ -155,7 +155,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
@ -201,7 +201,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
@ -238,7 +238,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
@ -276,7 +276,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(typeof(List<int>)),
ModelName = "someName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider
ValueProvider = new SimpleValueProvider
{
{ "someOtherName", "dummyValue" }
},
@ -357,7 +357,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
// Arrange
var binder = CreateBinderWithDefaults();
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "firstName", "firstName-value"},
{ "lastName", "lastName-value"}
@ -400,7 +400,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
// Arrange
var binder = CreateBinderWithDefaults();
var valueProvider = new SimpleHttpValueProvider
var valueProvider = new SimpleValueProvider
{
{ "firstName", "firstName-value"},
{ "lastName", "lastName-value"},
@ -436,7 +436,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_DoesNotAddAValidationNode_IfModelIsNotSet()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider();
var valueProvider = new SimpleValueProvider();
var mockBinder = new Mock<IModelBinder>();
mockBinder
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
@ -465,7 +465,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(Task.FromResult<ModelBindingResult>(null));
var binder = CreateCompositeBinder(mockBinder.Object);
var valueProvider = new SimpleHttpValueProvider();
var valueProvider = new SimpleValueProvider();
var bindingContext = CreateBindingContext(binder, valueProvider, typeof(SimplePropertiesModel));
// Act
@ -479,7 +479,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_UsesTheValidationNodeOnModelBindingResult_IfPresent()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider();
var valueProvider = new SimpleValueProvider();
ModelValidationNode validationNode = null;
var mockBinder = new Mock<IModelBinder>();
@ -531,10 +531,9 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
var binders = new IModelBinder[]
{
new TypeMatchModelBinder(),
new ByteArrayModelBinder(),
new GenericModelBinder(),
new TypeConverterModelBinder(),
new SimpleTypeModelBinder(),
new MutableObjectModelBinder()
};

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var result = await provider.GetValueAsync("not-test-key");
// Assert
Assert.Null(result);
Assert.Equal(ValueProviderResult.None, result);
}
[Fact]
@ -41,7 +41,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var result = await provider.GetValueAsync("test-key");
// Assert
Assert.Equal("test-value", result.RawValue);
Assert.Equal("test-value", (string)result);
}
[Fact]
@ -58,9 +58,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var result = await provider.GetValueAsync("test-key");
// Assert
Assert.NotNull(result);
Assert.Null(result.RawValue);
Assert.Null(result.AttemptedValue);
Assert.Equal(string.Empty, (string)result);
}
[Theory]
@ -103,7 +101,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var result = await valueProvider.GetValueAsync(prefix);
// Assert
Assert.Equal(expectedValue, (string)result.AttemptedValue);
Assert.Equal(expectedValue, (string)result);
}
[Fact]
@ -121,7 +119,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var result = await valueProvider.GetValueAsync("bar");
// Assert
Assert.Null(result);
Assert.Equal(ValueProviderResult.None, result);
}
[Fact]

View File

@ -21,7 +21,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_Succeeds(bool isReadOnly)
{
// Arrange
var bindingContext = GetModelBindingContext(isReadOnly);
var values = new Dictionary<string, KeyValuePair<int, string>>()
{
{ "someName[0]", new KeyValuePair<int, string>(42, "forty-two") },
{ "someName[1]", new KeyValuePair<int, string>(84, "eighty-four") },
};
var bindingContext = GetModelBindingContext(isReadOnly, values);
var modelState = bindingContext.ModelState;
var binder = new DictionaryModelBinder<int, string>();
@ -43,10 +49,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
[Theory]
[InlineData(false)]
[InlineData(true)]
public async Task BindModel_BindingContextModelNonNull_Succeeds(bool isReadOnly)
public async Task BindModel_WithExistingModel_Succeeds(bool isReadOnly)
{
// Arrange
var bindingContext = GetModelBindingContext(isReadOnly);
var values = new Dictionary<string, KeyValuePair<int, string>>()
{
{ "someName[0]", new KeyValuePair<int, string>(42, "forty-two") },
{ "someName[1]", new KeyValuePair<int, string>(84, "eighty-four") },
};
var bindingContext = GetModelBindingContext(isReadOnly, values);
var modelState = bindingContext.ModelState;
var dictionary = new Dictionary<int, string>();
bindingContext.Model = dictionary;
@ -430,8 +442,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new TypeMatchModelBinder(),
new SimpleTypeModelBinder(),
new MutableObjectModelBinder(),
};
@ -465,49 +476,51 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
return new TestValueProvider(BindingSource.Form, backingStore);
}
private static ModelBindingContext GetModelBindingContext(bool isReadOnly)
private static ModelBindingContext GetModelBindingContext(
bool isReadOnly,
IDictionary<string, KeyValuePair<int, string>> values)
{
var metadataProvider = new TestModelMetadataProvider();
metadataProvider.ForType<IDictionary<int, string>>().BindingDetails(bd => bd.IsReadOnly = isReadOnly);
var valueProvider = new SimpleHttpValueProvider
var binder = new Mock<IModelBinder>();
binder
.Setup(mb => mb.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns<ModelBindingContext>(mbc =>
{
KeyValuePair<int, string> value;
if (values.TryGetValue(mbc.ModelName, out value))
{
return Task.FromResult(new ModelBindingResult(value, mbc.ModelName, isModelSet: true));
}
else
{
return Task.FromResult<ModelBindingResult>(null);
}
});
var valueProvider = new SimpleValueProvider();
foreach (var kvp in values)
{
{ "someName[0]", new KeyValuePair<int, string>(42, "forty-two") },
{ "someName[1]", new KeyValuePair<int, string>(84, "eighty-four") },
};
valueProvider.Add(kvp.Key, string.Empty);
}
var bindingContext = new ModelBindingContext
{
ModelMetadata = metadataProvider.GetMetadataForType(typeof(IDictionary<int, string>)),
ModelName = "someName",
ValueProvider = valueProvider,
OperationBindingContext = new OperationBindingContext
{
ModelBinder = CreateKvpBinder(),
MetadataProvider = metadataProvider
}
ModelBinder = binder.Object,
MetadataProvider = metadataProvider,
ValueProvider = valueProvider,
},
ValueProvider = valueProvider,
};
return bindingContext;
}
private static IModelBinder CreateKvpBinder()
{
Mock<IModelBinder> mockKvpBinder = new Mock<IModelBinder>();
mockKvpBinder
.Setup(o => o.BindModelAsync(It.IsAny<ModelBindingContext>()))
.Returns(async (ModelBindingContext mbc) =>
{
var value = await mbc.ValueProvider.GetValueAsync(mbc.ModelName);
if (value != null)
{
var model = value.ConvertTo(mbc.ModelType);
return new ModelBindingResult(model, key: null, isModelSet: true);
}
return null;
});
return mockKvpBinder.Object;
}
private class ModelWithDictionaryProperties
{
// A Dictionary<string, string> instance cannot be assigned to this property.

View File

@ -19,9 +19,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
// Arrange
var culture = new CultureInfo("en-US");
var elementalValueProvider = new ElementalValueProvider(elementName,
new object(),
culture);
var elementalValueProvider = new ElementalValueProvider(
elementName,
"hi",
culture);
// Act
var containsPrefix = await elementalValueProvider.ContainsPrefixAsync(prefix);
@ -39,9 +40,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
// Arrange
var culture = new CultureInfo("en-US");
var elementalValueProvider = new ElementalValueProvider(elementName,
new object(),
culture);
var elementalValueProvider = new ElementalValueProvider(
elementName,
"hi",
culture);
// Act
var containsPrefix = await elementalValueProvider.ContainsPrefixAsync(prefix);
@ -51,18 +53,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
[Fact]
public async Task GetValueAsync_NameDoesNotMatch_ReturnsNull()
public async Task GetValueAsync_NameDoesNotMatch_ReturnsEmptyResult()
{
// Arrange
var culture = new CultureInfo("fr-FR");
var rawValue = new DateTime(2001, 1, 2);
var valueProvider = new ElementalValueProvider("foo", rawValue, culture);
var valueProvider = new ElementalValueProvider("foo", "hi", culture);
// Act
var vpResult = await valueProvider.GetValueAsync("bar");
var result = await valueProvider.GetValueAsync("bar");
// Assert
Assert.Null(vpResult);
Assert.Equal(ValueProviderResult.None, result);
}
[Theory]
@ -73,17 +74,15 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
// Arrange
var culture = new CultureInfo("fr-FR");
var rawValue = new DateTime(2001, 1, 2);
var valueProvider = new ElementalValueProvider("foo", rawValue, culture);
var valueProvider = new ElementalValueProvider("foo", "hi", culture);
// Act
var vpResult = await valueProvider.GetValueAsync(name);
var result = await valueProvider.GetValueAsync(name);
// Assert
Assert.NotNull(vpResult);
Assert.Equal(rawValue, vpResult.RawValue);
Assert.Equal("02/01/2001 00:00:00", vpResult.AttemptedValue);
Assert.Equal(culture, vpResult.Culture);
Assert.NotNull(result);
Assert.Equal("hi", (string)result);
Assert.Equal(culture, result.Culture);
}
}
}

View File

@ -167,8 +167,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Assert
Assert.NotNull(result);
Assert.Equal("someOtherValue", result.RawValue);
Assert.Equal("someOtherValue", result.AttemptedValue);
Assert.Equal("someOtherValue", (string)result);
Assert.Equal(culture, result.Culture);
}
@ -184,8 +183,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Assert
Assert.NotNull(result);
Assert.Equal(new[] { "someValue1", "someValue2" }, (IList<string>)result.RawValue);
Assert.Equal("someValue1,someValue2", result.AttemptedValue);
Assert.Equal(new[] { "someValue1", "someValue2" }, result.Values);
Assert.Equal("someValue1,someValue2", (string)result);
Assert.Equal(culture, result.Culture);
}
@ -202,7 +201,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var result = await valueProvider.GetValueAsync(key);
// Assert
Assert.Null(result);
Assert.Equal(ValueProviderResult.None, result);
}
[Fact]
@ -220,8 +219,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var result = await valueProvider.GetValueAsync("key");
// Assert
Assert.Equal(new[] { null, null, "value" }, result.RawValue as IEnumerable<string>);
Assert.Equal(",,value", result.AttemptedValue);
Assert.Equal(new[] { null, null, "value" }, result.Values);
Assert.Equal(",,value", (string)result);
}
[Fact]
@ -234,7 +233,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var result = await valueProvider.GetValueAsync("prefix");
// Assert
Assert.Null(result);
Assert.Equal(ValueProviderResult.None, result);
}
[Fact]

View File

@ -110,10 +110,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
var result = await valueProvider.GetValueAsync(key);
// Assert
Assert.NotNull(result);
Assert.NotNull(result.RawValue);
var value = Assert.IsType<string>(result.RawValue);
Assert.Equal("found", value);
Assert.Equal("found", (string)result);
}
private static ValueProviderFactoryContext CreateContext(

View File

@ -19,7 +19,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_MissingKey_ReturnsResult_AndAddsModelValidationError()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider();
var valueProvider = new SimpleValueProvider();
// Create string binder to create the value but not the key.
var bindingContext = GetBindingContext(valueProvider, CreateStringBinder());
@ -42,7 +42,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_MissingValue_ReturnsResult_AndAddsModelValidationError()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider();
var valueProvider = new SimpleValueProvider();
// Create int binder to create the value but not the key.
var bindingContext = GetBindingContext(valueProvider, CreateIntBinder());
@ -64,7 +64,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_MissingKeyAndMissingValue_DoNotAddModelStateError()
{
// Arrange
var valueProvider = new SimpleHttpValueProvider();
var valueProvider = new SimpleValueProvider();
// Create int binder to create the value but not the key.
var bindingContext = GetBindingContext(valueProvider);
@ -89,7 +89,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var innerBinder = new CompositeModelBinder(new[] { CreateStringBinder(), CreateIntBinder() });
var valueProvider = new SimpleHttpValueProvider();
var valueProvider = new SimpleValueProvider();
var bindingContext = GetBindingContext(valueProvider, innerBinder);
var binder = new KeyValuePairModelBinder<int, string>();
@ -134,7 +134,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
Assert.Equal("someName.key", context.ModelName);
return Task.FromResult(innerResult);
});
var bindingContext = GetBindingContext(new SimpleHttpValueProvider(), innerBinder.Object);
var bindingContext = GetBindingContext(new SimpleValueProvider(), innerBinder.Object);
var binder = new KeyValuePairModelBinder<int, string>();
var modelValidationNodeList = new List<ModelValidationNode>();
@ -238,7 +238,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
HttpContext = new DefaultHttpContext(),
MetadataProvider = new TestModelMetadataProvider(),
ModelBinder = new TypeMatchModelBinder(),
ModelBinder = new SimpleTypeModelBinder(),
}
};

View File

@ -18,7 +18,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
ModelMetadata = new TestModelMetadataProvider().GetMetadataForType(typeof(object)),
ModelName = "theName",
ModelState = new ModelStateDictionary(),
ValueProvider = new SimpleHttpValueProvider()
ValueProvider = new SimpleValueProvider()
};
var metadataProvider = new TestModelMetadataProvider();

View File

@ -9,7 +9,7 @@ using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
public class TypeConverterModelBinderTest
public class SimpleTypeModelBinderTest
{
[Theory]
[InlineData(typeof(object))]
@ -19,12 +19,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var bindingContext = GetBindingContext(destinationType);
bindingContext.ValueProvider = new SimpleHttpValueProvider
bindingContext.ValueProvider = new SimpleValueProvider
{
{ "theModelName", "some-value" }
};
var binder = new TypeConverterModelBinder();
var binder = new SimpleTypeModelBinder();
// Act
var retVal = await binder.BindModelAsync(bindingContext);
@ -53,12 +53,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
// Arrange
var bindingContext = GetBindingContext(destinationType);
bindingContext.ValueProvider = new SimpleHttpValueProvider
bindingContext.ValueProvider = new SimpleValueProvider
{
{ "theModelName", "some-value" }
};
var binder = new TypeConverterModelBinder();
var binder = new SimpleTypeModelBinder();
// Act
var retVal = await binder.BindModelAsync(bindingContext);
@ -79,11 +79,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var bindingContext = GetBindingContext(destinationType);
bindingContext.ValueProvider = new SimpleHttpValueProvider
bindingContext.ValueProvider = new SimpleValueProvider
{
{ "theModelName", string.Empty }
};
var binder = new TypeConverterModelBinder();
var binder = new SimpleTypeModelBinder();
// Act
var result = await binder.BindModelAsync(bindingContext);
@ -104,19 +104,19 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
// Arrange
var message = "The value 'not an integer' is not valid for theModelName.";
var bindingContext = GetBindingContext(typeof(int));
bindingContext.ValueProvider = new SimpleHttpValueProvider
bindingContext.ValueProvider = new SimpleValueProvider
{
{ "theModelName", "not an integer" }
};
var binder = new TypeConverterModelBinder();
var binder = new SimpleTypeModelBinder();
// Act
var retVal = await binder.BindModelAsync(bindingContext);
var result = await binder.BindModelAsync(bindingContext);
// Assert
Assert.NotNull(retVal);
Assert.Null(retVal.Model);
Assert.NotNull(result);
Assert.Null(result.Model);
Assert.False(bindingContext.ModelState.IsValid);
var error = Assert.Single(bindingContext.ModelState["theModelName"].Errors);
Assert.Equal(message, error.ErrorMessage);
@ -127,7 +127,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var bindingContext = GetBindingContext(typeof(int));
var binder = new TypeConverterModelBinder();
var binder = new SimpleTypeModelBinder();
// Act
var retVal = await binder.BindModelAsync(bindingContext);
@ -142,12 +142,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var bindingContext = GetBindingContext(typeof(string));
bindingContext.ValueProvider = new SimpleHttpValueProvider
bindingContext.ValueProvider = new SimpleValueProvider
{
{ "theModelName", string.Empty }
};
var binder = new TypeConverterModelBinder();
var binder = new SimpleTypeModelBinder();
// Act
var retVal = await binder.BindModelAsync(bindingContext);
@ -163,12 +163,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
// Arrange
var bindingContext = GetBindingContext(typeof(int));
bindingContext.ValueProvider = new SimpleHttpValueProvider
bindingContext.ValueProvider = new SimpleValueProvider
{
{ "theModelName", "42" }
};
var binder = new TypeConverterModelBinder();
var binder = new SimpleTypeModelBinder();
// Act
var retVal = await binder.BindModelAsync(bindingContext);
@ -185,7 +185,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(modelType),
ModelName = "theModelName",
ValueProvider = new SimpleHttpValueProvider() // empty
ValueProvider = new SimpleValueProvider() // empty
};
}

View File

@ -8,16 +8,16 @@ using System.Threading.Tasks;
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
public sealed class SimpleHttpValueProvider : Dictionary<string, object>, IValueProvider
public sealed class SimpleValueProvider : Dictionary<string, object>, IValueProvider
{
private readonly CultureInfo _culture;
public SimpleHttpValueProvider()
public SimpleValueProvider()
: this(null)
{
}
public SimpleHttpValueProvider(CultureInfo culture)
public SimpleValueProvider(CultureInfo culture)
: base(StringComparer.OrdinalIgnoreCase)
{
_culture = culture ?? CultureInfo.InvariantCulture;
@ -59,11 +59,28 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public Task<ValueProviderResult> GetValueAsync(string key)
{
ValueProviderResult result = null;
ValueProviderResult result = ValueProviderResult.None;
object rawValue;
if (TryGetValue(key, out rawValue))
{
result = new ValueProviderResult(rawValue, Convert.ToString(rawValue, _culture), _culture);
if (rawValue != null && rawValue.GetType().IsArray)
{
var array = (Array)rawValue;
var stringValues = new string[array.Length];
for (var i = 0; i < array.Length; i++)
{
stringValues[i] = array.GetValue(i) as string ?? Convert.ToString(array.GetValue(i), _culture);
}
result = new ValueProviderResult(stringValues, _culture);
}
else
{
var stringValue = rawValue as string ?? Convert.ToString(rawValue, _culture) ?? string.Empty;
result = new ValueProviderResult(stringValue, _culture);
}
}
return Task.FromResult(result);

View File

@ -1,121 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
using Xunit;
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
{
public class TypeMatchModelBinderTest
{
[Fact]
public async Task BindModel_InvalidValueProviderResult_ReturnsNull()
{
// Arrange
var bindingContext = GetBindingContext();
bindingContext.ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", "not an integer" }
};
var binder = new TypeMatchModelBinder();
var modelState = bindingContext.ModelState;
// Act
var result = await binder.BindModelAsync(bindingContext);
// Assert
Assert.Null(result);
Assert.Empty(modelState.Keys);
Assert.True(modelState.IsValid);
}
[Fact]
public async Task BindModel_ValidValueProviderResult_ReturnsNotNull()
{
// Arrange
var bindingContext = GetBindingContext();
bindingContext.ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", 42 }
};
var binder = new TypeMatchModelBinder();
var modelState = bindingContext.ModelState;
// Act
var result = await binder.BindModelAsync(bindingContext);
// Assert
Assert.NotNull(result);
Assert.True(result.IsModelSet);
Assert.Equal(42, result.Model);
var key = Assert.Single(modelState.Keys);
Assert.Equal("theModelName", key);
Assert.Equal("42", modelState[key].Value.AttemptedValue);
Assert.Equal(42, modelState[key].Value.RawValue);
}
[Fact]
public async Task GetCompatibleValueProviderResult_ValueProviderResultRawValueIncorrect_ReturnsNull()
{
// Arrange
var bindingContext = GetBindingContext();
bindingContext.ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", "not an integer" }
};
// Act
var vpResult = await TypeMatchModelBinder.GetCompatibleValueProviderResult(bindingContext);
// Assert
Assert.Null(vpResult); // Raw value is the wrong type
}
[Fact]
public async Task GetCompatibleValueProviderResult_ValueProviderResultValid_ReturnsValueProviderResult()
{
// Arrange
var bindingContext = GetBindingContext();
bindingContext.ValueProvider = new SimpleHttpValueProvider
{
{ "theModelName", 42 }
};
// Act
var vpResult = await TypeMatchModelBinder.GetCompatibleValueProviderResult(bindingContext);
// Assert
Assert.NotNull(vpResult);
}
[Fact]
public async Task GetCompatibleValueProviderResult_ValueProviderReturnsNull_ReturnsNull()
{
// Arrange
var bindingContext = GetBindingContext();
bindingContext.ValueProvider = new SimpleHttpValueProvider();
// Act
var vpResult = await TypeMatchModelBinder.GetCompatibleValueProviderResult(bindingContext);
// Assert
Assert.Null(vpResult); // No key matched
}
private static ModelBindingContext GetBindingContext()
{
return GetBindingContext(typeof(int));
}
private static ModelBindingContext GetBindingContext(Type modelType)
{
return new ModelBindingContext
{
ModelMetadata = new EmptyModelMetadataProvider().GetMetadataForType(modelType),
ModelName = "theModelName"
};
}
}
}

View File

@ -495,8 +495,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
var validationContext = testValidationContext.ModelValidationContext;
// Set the value on model state as a model binder would.
var valueProviderResult = new ValueProviderResult(rawValue: "password");
validationContext.ModelState.SetModelValue("user.Password", valueProviderResult);
validationContext.ModelState.SetModelValue("user.Password", new string[] { "password" }, "password");
var validator = new DefaultObjectValidator(
testValidationContext.ExcludeFilters,
testValidationContext.ModelMetadataProvider);
@ -517,7 +516,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
Assert.Equal("user.Password", entry.Key);
Assert.Empty(entry.Value.Errors);
Assert.Equal(entry.Value.ValidationState, ModelValidationState.Skipped);
Assert.Same(valueProviderResult, entry.Value.Value);
Assert.Equal(new string[] { "password" }, entry.Value.RawValue);
Assert.Same("password", entry.Value.AttemptedValue);
}
private class Person2

View File

@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
@ -68,7 +69,7 @@ namespace Microsoft.AspNet.Mvc.Test
var expectedMessage = PlatformNormalizer.NormalizeContent("The MyProperty field is required.");
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new SimpleTypeModelBinder(),
new MutableObjectModelBinder()
};
@ -107,7 +108,7 @@ namespace Microsoft.AspNet.Mvc.Test
// Arrange
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new SimpleTypeModelBinder(),
new MutableObjectModelBinder()
};
@ -181,7 +182,7 @@ namespace Microsoft.AspNet.Mvc.Test
// Arrange
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new SimpleTypeModelBinder(),
new MutableObjectModelBinder()
};
@ -270,7 +271,7 @@ namespace Microsoft.AspNet.Mvc.Test
// Arrange
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new SimpleTypeModelBinder(),
new MutableObjectModelBinder()
};
@ -322,7 +323,7 @@ namespace Microsoft.AspNet.Mvc.Test
// Arrange
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new SimpleTypeModelBinder(),
new MutableObjectModelBinder()
};
@ -528,7 +529,7 @@ namespace Microsoft.AspNet.Mvc.Test
// Arrange
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new SimpleTypeModelBinder(),
new MutableObjectModelBinder()
};
@ -619,7 +620,7 @@ namespace Microsoft.AspNet.Mvc.Test
// Arrange
var binders = new IModelBinder[]
{
new TypeConverterModelBinder(),
new SimpleTypeModelBinder(),
new MutableObjectModelBinder()
};
@ -876,6 +877,514 @@ namespace Microsoft.AspNet.Mvc.Test
public string Name { get; set; }
public Address Address { get; set; }
}
[Fact]
public void ConvertTo_ReturnsNullForReferenceTypes_WhenValueIsNull()
{
var convertedValue = ModelBindingHelper.ConvertTo(null, typeof(string));
Assert.Null(convertedValue);
}
[Fact]
public void ConvertTo_ReturnsDefaultForValueTypes_WhenValueIsNull()
{
var convertedValue = ModelBindingHelper.ConvertTo(null, typeof(int));
Assert.Equal(0, convertedValue);
}
[Fact]
public void ConvertToCanConvertArraysToSingleElements()
{
// Arrange
var value = new int[] { 1, 20, 42 };
// Act
var converted = ModelBindingHelper.ConvertTo(value, typeof(string));
// Assert
Assert.Equal("1", converted);
}
[Fact]
public void ConvertToCanConvertSingleElementsToArrays()
{
// Arrange
var value = 42;
// Act
var converted = ModelBindingHelper.ConvertTo<string[]>(value);
// Assert
Assert.NotNull(converted);
var result = Assert.Single(converted);
Assert.Equal("42", result);
}
[Fact]
public void ConvertToCanConvertSingleElementsToSingleElements()
{
// Arrange
// Act
var converted = ModelBindingHelper.ConvertTo<string>(42);
// Assert
Assert.NotNull(converted);
Assert.Equal("42", converted);
}
[Fact]
public void ConvertingNullStringToNullableIntReturnsNull()
{
// Arrange
// Act
var returned = ModelBindingHelper.ConvertTo<int?>(null);
// Assert
Assert.Equal(returned, null);
}
[Fact]
public void ConvertingWhiteSpaceStringToNullableIntReturnsNull()
{
// Arrange
var original = " ";
// Act
var returned = ModelBindingHelper.ConvertTo<int?>(original);
// Assert
Assert.Equal(returned, null);
}
[Fact]
public void ConvertToReturnsNullIfArrayElementValueIsNull()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(new string[] { null }, typeof(int));
// Assert
Assert.Null(outValue);
}
[Fact]
public void ConvertToReturnsNullIfTryingToConvertEmptyArrayToSingleElement()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(new int[0], typeof(int));
// Assert
Assert.Null(outValue);
}
[Theory]
[InlineData("")]
[InlineData(" \t \r\n ")]
public void ConvertToReturnsNullIfTrimmedValueIsEmptyString(object value)
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(value, typeof(int));
// Assert
Assert.Null(outValue);
}
[Fact]
public void ConvertToReturnsNullIfTrimmedValueIsEmptyString()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(null, typeof(int[]));
// Assert
Assert.Null(outValue);
}
[Fact]
public void ConvertToReturnsValueIfArrayElementIsIntegerAndDestinationTypeIsEnum()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(new object[] { 1 }, typeof(IntEnum));
// Assert
Assert.Equal(outValue, IntEnum.Value1);
}
[Theory]
[InlineData(1, typeof(IntEnum), IntEnum.Value1)]
[InlineData(1L, typeof(LongEnum), LongEnum.Value1)]
[InlineData(long.MaxValue, typeof(LongEnum), LongEnum.MaxValue)]
[InlineData(1U, typeof(UnsignedIntEnum), UnsignedIntEnum.Value1)]
[InlineData(1UL, typeof(IntEnum), IntEnum.Value1)]
[InlineData((byte)1, typeof(ByteEnum), ByteEnum.Value1)]
[InlineData(byte.MaxValue, typeof(ByteEnum), ByteEnum.MaxValue)]
[InlineData((sbyte)1, typeof(ByteEnum), ByteEnum.Value1)]
[InlineData((short)1, typeof(IntEnum), IntEnum.Value1)]
[InlineData((ushort)1, typeof(IntEnum), IntEnum.Value1)]
[InlineData(int.MaxValue, typeof(IntEnum?), IntEnum.MaxValue)]
[InlineData(null, typeof(IntEnum?), null)]
[InlineData(1L, typeof(LongEnum?), LongEnum.Value1)]
[InlineData(null, typeof(LongEnum?), null)]
[InlineData(uint.MaxValue, typeof(UnsignedIntEnum?), UnsignedIntEnum.MaxValue)]
[InlineData((byte)1, typeof(ByteEnum?), ByteEnum.Value1)]
[InlineData(null, typeof(ByteEnum?), null)]
[InlineData((ushort)1, typeof(LongEnum?), LongEnum.Value1)]
public void ConvertToReturnsValueIfArrayElementIsAnyIntegerTypeAndDestinationTypeIsEnum(
object input,
Type enumType,
object expected)
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(new object[] { input }, enumType);
// Assert
Assert.Equal(expected, outValue);
}
[Fact]
public void ConvertToReturnsValueIfArrayElementIsStringValueAndDestinationTypeIsEnum()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(new object[] { "1" }, typeof(IntEnum));
// Assert
Assert.Equal(outValue, IntEnum.Value1);
}
[Fact]
public void ConvertToReturnsValueIfArrayElementIsStringKeyAndDestinationTypeIsEnum()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(new object[] { "Value1" }, typeof(IntEnum));
// Assert
Assert.Equal(outValue, IntEnum.Value1);
}
[Fact]
public void ConvertToReturnsValueIfElementIsStringAndDestinationIsNullableInteger()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo("12", typeof(int?));
// Assert
Assert.Equal(12, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsStringAndDestinationIsNullableDouble()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo("12.5", typeof(double?));
// Assert
Assert.Equal(12.5, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsDecimalAndDestinationIsNullableInteger()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(12M, typeof(int?));
// Assert
Assert.Equal(12, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsDecimalAndDestinationIsNullableDouble()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(12.5M, typeof(double?));
// Assert
Assert.Equal(12.5, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsDecimalDoubleAndDestinationIsNullableInteger()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(12M, typeof(int?));
// Assert
Assert.Equal(12, outValue);
}
[Fact]
public void ConvertToReturnsValueIfElementIsDecimalDoubleAndDestinationIsNullableLong()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(12M, typeof(long?));
// Assert
Assert.Equal(12L, outValue);
}
[Fact]
public void ConvertToReturnsValueIfArrayElementInstanceOfDestinationType()
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(new object[] { "some string" }, typeof(string));
// Assert
Assert.Equal("some string", outValue);
}
[Theory]
[InlineData(new object[] { new[] { 1, 0 } })]
[InlineData(new object[] { new[] { "Value1", "Value0" } })]
[InlineData(new object[] { new[] { "Value1", "value0" } })]
public void ConvertTo_ConvertsEnumArrays(object value)
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(value, typeof(IntEnum[]));
// Assert
var result = Assert.IsType<IntEnum[]>(outValue);
Assert.Equal(2, result.Length);
Assert.Equal(IntEnum.Value1, result[0]);
Assert.Equal(IntEnum.Value0, result[1]);
}
[Theory]
[InlineData(new object[] { new[] { 1, 2 }, new[] { FlagsEnum.Value1, FlagsEnum.Value2 } })]
[InlineData(new object[] { new[] { "Value1", "Value2" }, new[] { FlagsEnum.Value1, FlagsEnum.Value2 } })]
[InlineData(new object[] { new[] { 5, 2 }, new[] { FlagsEnum.Value1 | FlagsEnum.Value4, FlagsEnum.Value2 } })]
public void ConvertTo_ConvertsFlagsEnumArrays(object value, FlagsEnum[] expected)
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo(value, typeof(FlagsEnum[]));
// Assert
var result = Assert.IsType<FlagsEnum[]>(outValue);
Assert.Equal(2, result.Length);
Assert.Equal(expected[0], result[0]);
Assert.Equal(expected[1], result[1]);
}
[Fact]
public void ConvertToReturnsValueIfInstanceOfDestinationType()
{
// Arrange
var original = new[] { "some string" };
// Act
var outValue = ModelBindingHelper.ConvertTo(original, typeof(string[]));
// Assert
Assert.Same(original, outValue);
}
[Theory]
[InlineData(typeof(int))]
[InlineData(typeof(double?))]
[InlineData(typeof(IntEnum?))]
public void ConvertToThrowsIfConverterThrows(Type destinationType)
{
// Arrange
// Act & Assert
var ex = Assert.Throws<FormatException>(
() => ModelBindingHelper.ConvertTo("this-is-not-a-valid-value", destinationType));
}
[Fact]
public void ConvertToThrowsIfNoConverterExists()
{
// Arrange
var destinationType = typeof(MyClassWithoutConverter);
// Act & Assert
var ex = Assert.Throws<InvalidOperationException>(
() => ModelBindingHelper.ConvertTo("x", destinationType));
Assert.Equal("The parameter conversion from type 'System.String' to type " +
$"'{typeof(MyClassWithoutConverter).FullName}' " +
"failed because no type converter can convert between these types.",
ex.Message);
}
[Fact]
public void ConvertToUsesProvidedCulture()
{
// Arrange
// Act
var cultureResult = ModelBindingHelper.ConvertTo("12,5", typeof(decimal), new CultureInfo("fr-FR"));
// Assert
Assert.Equal(12.5M, cultureResult);
Assert.Throws<FormatException>(
() => ModelBindingHelper.ConvertTo("12,5", typeof(decimal), new CultureInfo("en-GB")));
}
[Theory]
[MemberData(nameof(IntrinsicConversionData))]
public void ConvertToCanConvertIntrinsics<T>(object initialValue, T expectedValue)
{
// Arrange
// Act & Assert
Assert.Equal(expectedValue, ModelBindingHelper.ConvertTo(initialValue, typeof(T)));
}
public static IEnumerable<object[]> IntrinsicConversionData
{
get
{
yield return new object[] { 42, 42L };
yield return new object[] { 42, (short)42 };
yield return new object[] { 42, (float)42.0 };
yield return new object[] { 42, (double)42.0 };
yield return new object[] { 42M, 42 };
yield return new object[] { 42L, 42 };
yield return new object[] { 42, (byte)42 };
yield return new object[] { (short)42, 42 };
yield return new object[] { (float)42.0, 42 };
yield return new object[] { (double)42.0, 42 };
yield return new object[] { (byte)42, 42 };
yield return new object[] { "2008-01-01", new DateTime(2008, 01, 01) };
yield return new object[] { "00:00:20", TimeSpan.FromSeconds(20) };
yield return new object[]
{
"c6687d3a-51f9-4159-8771-a66d2b7d7038",
Guid.Parse("c6687d3a-51f9-4159-8771-a66d2b7d7038")
};
}
}
[Theory]
[InlineData(typeof(TimeSpan))]
[InlineData(typeof(DateTime))]
[InlineData(typeof(DateTimeOffset))]
[InlineData(typeof(Guid))]
[InlineData(typeof(IntEnum))]
public void ConvertTo_Throws_IfValueIsNotStringData(Type destinationType)
{
// Arrange
// Act
var ex = Assert.Throws<InvalidOperationException>(
() => ModelBindingHelper.ConvertTo(new MyClassWithoutConverter(), destinationType));
// Assert
var expectedMessage = string.Format("The parameter conversion from type '{0}' to type '{1}' " +
"failed because no type converter can convert between these types.",
typeof(MyClassWithoutConverter), destinationType);
Assert.Equal(expectedMessage, ex.Message);
}
[Fact]
public void ConvertTo_Throws_IfDestinationTypeIsNotConvertible()
{
// Arrange
var value = "Hello world";
var destinationType = typeof(MyClassWithoutConverter);
// Act
var ex = Assert.Throws<InvalidOperationException>(
() => ModelBindingHelper.ConvertTo(value, destinationType));
// Assert
var expectedMessage = string.Format("The parameter conversion from type '{0}' to type '{1}' " +
"failed because no type converter can convert between these types.",
value.GetType(), typeof(MyClassWithoutConverter));
Assert.Equal(expectedMessage, ex.Message);
}
[Theory]
[InlineData(new object[] { 2, FlagsEnum.Value2 })]
[InlineData(new object[] { 5, FlagsEnum.Value1 | FlagsEnum.Value4 })]
[InlineData(new object[] { 15, FlagsEnum.Value1 | FlagsEnum.Value2 | FlagsEnum.Value4 | FlagsEnum.Value8 })]
[InlineData(new object[] { 16, (FlagsEnum)16 })]
[InlineData(new object[] { 0, (FlagsEnum)0 })]
[InlineData(new object[] { null, (FlagsEnum)0 })]
[InlineData(new object[] { "Value1,Value2", (FlagsEnum)3 })]
[InlineData(new object[] { "Value1,Value2,value4, value8", (FlagsEnum)15 })]
public void ConvertTo_ConvertsEnumFlags(object value, object expected)
{
// Arrange
// Act
var outValue = ModelBindingHelper.ConvertTo<FlagsEnum>(value);
// Assert
Assert.Equal(expected, outValue);
}
private class MyClassWithoutConverter
{
}
private enum IntEnum
{
Value0 = 0,
Value1 = 1,
MaxValue = int.MaxValue
}
private enum LongEnum : long
{
Value0 = 0L,
Value1 = 1L,
MaxValue = long.MaxValue
}
private enum UnsignedIntEnum : uint
{
Value0 = 0U,
Value1 = 1U,
MaxValue = uint.MaxValue
}
private enum ByteEnum : byte
{
Value0 = 0,
Value1 = 1,
MaxValue = byte.MaxValue
}
[Flags]
public enum FlagsEnum
{
Value1 = 1,
Value2 = 2,
Value4 = 4,
Value8 = 8
}
}
}
#endif

View File

@ -72,10 +72,10 @@ namespace Microsoft.AspNet.Mvc
var modelState = new ModelStateDictionary();
modelState.Add(
"key1",
new ModelState() { Value = new ValueProviderResult("foo", "foo", CultureInfo.InvariantCulture) });
new ModelState());
modelState.Add(
"key2",
new ModelState() { Value = new ValueProviderResult("bar", "bar", CultureInfo.InvariantCulture) });
new ModelState());
// Act
var serializableError = new SerializableError(modelState);

View File

@ -2086,13 +2086,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert
var result = await ReadValue<UserWithAddress>(response);
// Though posted content did not contain any valid Addresses, it is bound as a single-element List
// containing null. Slightly odd behavior is specific to this unusual error case: CollectionModelBinder
// attempted to bind a comma-separated string as a collection and Address lacks a from-string conversion.
// MutableObjectModelBinder does not create model when value providers have no data (unless at top level).
var address = Assert.Single(result.Addresses);
Assert.Null(address);
Assert.Empty(result.Addresses);
}
[Fact]
@ -2153,12 +2147,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert
var result = await ReadValue<PeopleModel>(response);
// Though posted content did not contain any valid People, it is bound as a single-element List
// containing null. Slightly odd behavior is specific to this unusual error case: CollectionModelBinder
// attempted to bind a comma-separated string as a collection and Address lacks a from-string conversion.
// MutableObjectModelBinder does not create model when value providers have no data (unless at top level).
var person = Assert.Single(result.People);
Assert.Null(person);
Assert.Empty(result.People);
}
[Theory]

View File

@ -65,9 +65,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys, k => k == "Address[0].Street");
Assert.NotNull(modelState[key].Value);
Assert.Equal("SomeStreet", modelState[key].Value.AttemptedValue);
Assert.Equal("SomeStreet", modelState[key].Value.RawValue);
Assert.Equal("SomeStreet", modelState[key].AttemptedValue);
Assert.Equal("SomeStreet", modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
}
@ -116,7 +115,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var state = entry.Value;
Assert.NotNull(state);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
}
private class Person4
@ -161,9 +161,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys, k => k == "Address[0].Street");
Assert.NotNull(modelState[key].Value);
Assert.Equal("SomeStreet", modelState[key].Value.AttemptedValue);
Assert.Equal("SomeStreet", modelState[key].Value.RawValue);
Assert.Equal("SomeStreet", modelState[key].AttemptedValue);
Assert.Equal("SomeStreet", modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
}
@ -250,9 +249,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys, k => k == "prefix.Address[0].Street");
Assert.NotNull(modelState[key].Value);
Assert.Equal("SomeStreet", modelState[key].Value.AttemptedValue);
Assert.Equal("SomeStreet", modelState[key].Value.RawValue);
Assert.Equal("SomeStreet", modelState[key].AttemptedValue);
Assert.Equal("SomeStreet", modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
}
@ -300,7 +298,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var state = entry.Value;
Assert.NotNull(state);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
}
[Fact]
@ -343,9 +342,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys, k => k == "prefix.Address[0].Street");
Assert.NotNull(modelState[key].Value);
Assert.Equal("SomeStreet", modelState[key].Value.AttemptedValue);
Assert.Equal("SomeStreet", modelState[key].Value.RawValue);
Assert.Equal("SomeStreet", modelState[key].AttemptedValue);
Assert.Equal("SomeStreet", modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
}

View File

@ -44,12 +44,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -89,12 +89,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -130,12 +130,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -208,12 +208,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[0].Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[1].Name").Value;
Assert.Equal("lang", entry.Value.AttemptedValue);
Assert.Equal("lang", entry.Value.RawValue);
Assert.Equal("lang", entry.AttemptedValue);
Assert.Equal("lang", entry.RawValue);
}
[Fact]
@ -254,12 +254,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[0].Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[1].Name").Value;
Assert.Equal("lang", entry.Value.AttemptedValue);
Assert.Equal("lang", entry.Value.RawValue);
Assert.Equal("lang", entry.AttemptedValue);
Assert.Equal("lang", entry.RawValue);
}
[Fact]
@ -296,12 +296,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "[0].Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "[1].Name").Value;
Assert.Equal("lang", entry.Value.AttemptedValue);
Assert.Equal("lang", entry.Value.RawValue);
Assert.Equal("lang", entry.AttemptedValue);
Assert.Equal("lang", entry.RawValue);
}
[Fact]

View File

@ -190,7 +190,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var key = Assert.Single(modelState.Keys);
Assert.Equal("CustomParameter", key);
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
Assert.NotNull(modelState[key].Value); // Value is set by test model binder, no need to validate it.
Assert.NotNull(modelState[key].RawValue); // Value is set by test model binder, no need to validate it.
}
private class Person
@ -239,7 +239,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys, k => k == "Parameter1.Address.Street");
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
Assert.NotNull(modelState[key].Value); // Value is set by test model binder, no need to validate it.
Assert.NotNull(modelState[key].RawValue); // Value is set by test model binder, no need to validate it.
}
[Fact]
@ -279,7 +279,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys, k => k == "CustomParameter.Address.Street");
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
Assert.NotNull(modelState[key].Value); // Value is set by test model binder, no need to validate it.
Assert.NotNull(modelState[key].RawValue); // Value is set by test model binder, no need to validate it.
}
private class AddressModelBinder : IModelBinder
@ -294,11 +294,9 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var address = new Address() { Street = "SomeStreet" };
bindingContext.ModelState.SetModelValue(
ModelNames.CreatePropertyModelName(bindingContext.ModelName, "Street"),
new ValueProviderResult(
address.Street,
address.Street,
CultureInfo.CurrentCulture));
ModelNames.CreatePropertyModelName(bindingContext.ModelName, "Street"),
new string[] { address.Street },
address.Street);
var validationNode = new ModelValidationNode(
bindingContext.ModelName,
@ -319,7 +317,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var model = "Success";
bindingContext.ModelState.SetModelValue(
bindingContext.ModelName,
new ValueProviderResult(model, model, CultureInfo.CurrentCulture));
new string[] { model },
model);
var modelValidationNode = new ModelValidationNode(
bindingContext.ModelName,

View File

@ -102,7 +102,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState);
Assert.Empty(entry.Key);
Assert.Null(entry.Value.Value.RawValue);
Assert.Null(entry.Value.RawValue);
}
private class Person4
@ -112,7 +112,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
public int Address { get; set; }
}
[Fact]
[Fact(Skip = "#2722 validation error from formatter is recorded with the wrong key.")]
public async Task FromBodyAndRequiredOnValueTypeProperty_EmptyBody_JsonFormatterAddsModelStateError()
{
// Arrange
@ -146,7 +146,9 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState);
Assert.Equal(string.Empty, entry.Key);
Assert.Equal("CustomParameter.Address", entry.Key);
Assert.Null(entry.Value.AttemptedValue);
Assert.Same(boundPerson, entry.Value.RawValue);
var error = Assert.Single(entry.Value.Errors);
Assert.NotNull(error.Exception);

View File

@ -65,8 +65,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(queryStringKey, entry.Key);
Assert.Empty(entry.Value.Errors);
Assert.Equal(ModelValidationState.Valid, entry.Value.ValidationState);
Assert.Equal(value, entry.Value.Value.AttemptedValue);
Assert.Equal(value, entry.Value.Value.RawValue);
Assert.Equal(value, entry.Value.AttemptedValue);
Assert.Equal(value, entry.Value.RawValue);
}
[Fact]
@ -146,8 +146,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("CustomParameter", entry.Key);
Assert.Empty(entry.Value.Errors);
Assert.Equal(value, entry.Value.Value.AttemptedValue);
Assert.Equal(value, entry.Value.Value.RawValue);
Assert.Equal(value, entry.Value.AttemptedValue);
Assert.Equal(value, entry.Value.RawValue);
}
}
}

View File

@ -51,12 +51,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -96,12 +96,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -137,12 +137,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -215,12 +215,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[0].Id").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[1].Id").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -261,12 +261,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[0].Id").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[1].Id").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -303,12 +303,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "[0].Id").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "[1].Id").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -386,21 +386,21 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[0].Id").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[1].Id").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[0].Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
var error = Assert.Single(entry.Errors);
Assert.Equal("A value for the 'Name' property was not provided.", error.ErrorMessage);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[1].Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
error = Assert.Single(entry.Errors);
Assert.Equal("A value for the 'Name' property was not provided.", error.ErrorMessage);
@ -446,19 +446,19 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[0].Id").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[1].Id").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[0].Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
entry = Assert.Single(modelState, kvp => kvp.Key == "prefix[1].Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
}
@ -498,19 +498,19 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "[0].Id").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "[1].Id").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "[0].Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
entry = Assert.Single(modelState, kvp => kvp.Key == "[1].Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
}
@ -595,12 +595,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(0, modelState.ErrorCount);
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "Addresses[Key1].Street").Value;
Assert.Equal("Street1", entry.Value.AttemptedValue);
Assert.Equal("Street1", entry.Value.RawValue);
Assert.Equal("Street1", entry.AttemptedValue);
Assert.Equal("Street1", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "Addresses[Key2].Street").Value;
Assert.Equal("Street2", entry.Value.AttemptedValue);
Assert.Equal("Street2", entry.Value.RawValue);
Assert.Equal("Street2", entry.AttemptedValue);
Assert.Equal("Street2", entry.RawValue);
}
private class Person5

View File

@ -45,12 +45,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[0].Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter[0].Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -87,8 +87,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var kvp = Assert.Single(modelState);
Assert.Equal("parameter[key0]", kvp.Key);
var entry = kvp.Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Theory]

View File

@ -71,7 +71,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(2, modelState.Count);
Assert.Single(modelState.Keys, k => k == "Address.Zip");
var key = Assert.Single(modelState.Keys, k => k == "Address.File");
Assert.NotNull(modelState[key].Value);
Assert.Null(modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
Assert.Equal(ModelValidationState.Skipped, modelState[key].ValidationState);
}
@ -122,8 +122,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal("CustomParameter", entry.Key);
Assert.Empty(entry.Value.Errors);
Assert.Equal(ModelValidationState.Skipped, entry.Value.ValidationState);
Assert.Null(entry.Value.Value.AttemptedValue);
Assert.Equal(file, entry.Value.Value.RawValue);
Assert.Null(entry.Value.AttemptedValue);
Assert.Null(entry.Value.RawValue);
}
[Fact]

View File

@ -276,12 +276,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter[0][0].Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter[0][0].Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
// This is part of a random sampling of scenarios where a GenericModelBinder is used
@ -322,12 +322,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "[0][0].Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "[0][0].Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
// This is part of a random sampling of scenarios where a GenericModelBinder is used
@ -403,12 +403,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter[0].Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter[0].Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
// This is part of a random sampling of scenarios where a GenericModelBinder is used
@ -448,12 +448,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "[0].Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "[0].Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
// This is part of a random sampling of scenarios where a GenericModelBinder is used
@ -530,16 +530,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter[0].Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter[0].Value[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter[0].Value[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
// This is part of a random sampling of scenarios where a GenericModelBinder is used
@ -579,16 +579,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "[0].Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "[0].Value[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "[0].Value[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
// This is part of a random sampling of scenarios where a GenericModelBinder is used

View File

@ -109,8 +109,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal("prefix.Address.Header", entry.Key);
Assert.Empty(entry.Value.Errors);
Assert.Equal(ModelValidationState.Valid, entry.Value.ValidationState);
Assert.Equal("someValue", entry.Value.Value.AttemptedValue);
Assert.Equal("someValue", entry.Value.Value.RawValue);
Assert.Equal("someValue", entry.Value.AttemptedValue);
Assert.Equal(new string[] { "someValue" }, entry.Value.RawValue);
}
// The scenario is interesting as we to bind the top level model we fallback to empty prefix,
@ -152,8 +152,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal("Address.Header", entry.Key);
Assert.Empty(entry.Value.Errors);
Assert.Equal(ModelValidationState.Valid, entry.Value.ValidationState);
Assert.Equal("someValue", entry.Value.Value.AttemptedValue);
Assert.Equal("someValue", entry.Value.Value.RawValue);
Assert.Equal("someValue", entry.Value.AttemptedValue);
Assert.Equal(new string[] { "someValue" }, entry.Value.RawValue);
}
[Theory]
@ -162,9 +162,18 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
public async Task BindParameterFromHeader_WithData_WithPrefix_ModelGetsBound(Type modelType, string value)
{
// Arrange
var expectedValue = modelType == typeof(string) ?
(object)value :
(object)value.Split(',').Select(v => v.Trim()).ToArray();
object expectedValue;
object expectedRawValue;
if (modelType == typeof(string))
{
expectedValue = value;
expectedRawValue = new string[] { value };
}
else
{
expectedValue = value.Split(',').Select(v => v.Trim()).ToArray();
expectedRawValue = expectedValue;
}
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
var parameter = new ParameterDescriptor
@ -204,8 +213,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal("CustomParameter", entry.Key);
Assert.Empty(entry.Value.Errors);
Assert.Equal(ModelValidationState.Valid, entry.Value.ValidationState);
Assert.Equal(value, entry.Value.Value.AttemptedValue);
Assert.Equal(expectedValue, entry.Value.Value.RawValue);
Assert.Equal(value, entry.Value.AttemptedValue);
Assert.Equal(expectedRawValue, entry.Value.RawValue);
}
}
}

View File

@ -45,12 +45,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter.Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter.Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -90,12 +90,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "prefix.Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "prefix.Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -131,12 +131,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -210,12 +210,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "parameter.Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "parameter.Value.Id").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal(model.Value.Id.ToString(), entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -256,12 +256,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "prefix.Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "prefix.Value.Id").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -298,12 +298,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, kvp => kvp.Key == "Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, kvp => kvp.Key == "Value.Id").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]

View File

@ -82,12 +82,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Address").Value;
Assert.Null(entry.Value.AttemptedValue); // ModelState entries for body don't include original text.
Assert.Same(model.Customer.Address, entry.Value.RawValue);
Assert.Null(entry.AttemptedValue); // ModelState entries for body don't include original text.
Assert.Same(model.Customer.Address, entry.RawValue);
}
[Fact]
@ -128,12 +128,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "Customer.Address").Value;
Assert.Null(entry.Value.AttemptedValue); // ModelState entries for body don't include original text.
Assert.Same(model.Customer.Address, entry.Value.RawValue);
Assert.Null(entry.AttemptedValue); // ModelState entries for body don't include original text.
Assert.Same(model.Customer.Address, entry.RawValue);
}
[Fact]
@ -173,11 +173,11 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Address").Value;
Assert.Null(entry.Value.AttemptedValue);
Assert.Null(entry.Value.RawValue);
Assert.Null(entry.AttemptedValue);
Assert.Null(entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
}
// We don't provide enough data in this test for the 'Person' model to be created. So even though there is
@ -218,8 +218,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.ProductId").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
// We don't provide enough data in this test for the 'Person' model to be created. So even though there is
@ -310,8 +310,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
}
[Fact]
@ -350,8 +350,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
}
// We don't provide enough data in this test for the 'Person' model to be created. So even though there is
@ -392,8 +392,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.ProductId").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
// We don't provide enough data in this test for the 'Person' model to be created. So even though there is
@ -484,12 +484,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Token").Value;
Assert.Equal(ByteArrayEncoded, entry.Value.AttemptedValue);
Assert.Equal(ByteArrayEncoded, entry.Value.RawValue);
Assert.Equal(ByteArrayEncoded, entry.AttemptedValue);
Assert.Equal(ByteArrayEncoded, entry.RawValue);
}
[Fact]
@ -528,12 +528,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "Customer.Token").Value;
Assert.Equal(ByteArrayEncoded, entry.Value.AttemptedValue);
Assert.Equal(ByteArrayEncoded, entry.Value.RawValue);
Assert.Equal(ByteArrayEncoded, entry.AttemptedValue);
Assert.Equal(ByteArrayEncoded, entry.RawValue);
}
[Fact]
@ -572,8 +572,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
}
private class Order4
@ -627,12 +627,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Documents").Value;
Assert.Null(entry.Value.AttemptedValue); // FormFile entries for body don't include original text.
Assert.Same(model.Customer.Documents, entry.Value.RawValue);
Assert.Null(entry.AttemptedValue); // FormFile entries for body don't include original text.
Assert.Null(entry.RawValue);
}
[Fact]
@ -672,12 +672,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "Customer.Documents").Value;
Assert.Null(entry.Value.AttemptedValue); // FormFile entries for body don't include original text.
Assert.Same(model.Customer.Documents, entry.Value.RawValue);
Assert.Null(entry.AttemptedValue); // FormFile entries don't include the model.
Assert.Null(entry.RawValue);
}
[Fact]
@ -718,13 +718,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Documents").Value;
Assert.Null(entry.Value.AttemptedValue);
var documents = Assert.IsAssignableFrom<IEnumerable<IFormFile>>(entry.Value.RawValue);
Assert.Empty(documents);
Assert.Null(entry.AttemptedValue); // FormFile entries don't include the model.
Assert.Null(entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
}
// We don't provide enough data in this test for the 'Person' model to be created. So even though there are
@ -765,8 +764,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.ProductId").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
// We don't provide enough data in this test for the 'Person' model to be created. So even though there is
@ -849,16 +848,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.ProductIds[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.ProductIds[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -897,16 +896,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "ProductIds[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "ProductIds[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -944,8 +943,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
}
[Fact]
@ -1026,16 +1025,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.ProductIds[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.ProductIds[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -1074,16 +1073,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "ProductIds[0]").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "ProductIds[1]").Value;
Assert.Equal("11", entry.Value.AttemptedValue);
Assert.Equal("11", entry.Value.RawValue);
Assert.Equal("11", entry.AttemptedValue);
Assert.Equal("11", entry.RawValue);
}
[Fact]
@ -1121,8 +1120,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
}
[Fact]
@ -1203,16 +1202,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.ProductIds[0].Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.ProductIds[0].Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -1251,16 +1250,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "ProductIds[0].Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "ProductIds[0].Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -1298,8 +1297,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
}
[Fact]
@ -1380,16 +1379,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.ProductId.Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.ProductId.Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -1428,16 +1427,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "ProductId.Key").Value;
Assert.Equal("key0", entry.Value.AttemptedValue);
Assert.Equal("key0", entry.Value.RawValue);
Assert.Equal("key0", entry.AttemptedValue);
Assert.Equal("key0", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "ProductId.Value").Value;
Assert.Equal("10", entry.Value.AttemptedValue);
Assert.Equal("10", entry.Value.RawValue);
Assert.Equal("10", entry.AttemptedValue);
Assert.Equal("10", entry.RawValue);
}
[Fact]
@ -1475,8 +1474,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
}
[Fact]
@ -1568,8 +1567,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Customer.Address").Value;
Assert.Null(entry.Value.AttemptedValue);
Assert.Same(model.Customer.Address, entry.Value.RawValue);
Assert.Null(entry.AttemptedValue);
Assert.Same(model.Customer.Address, entry.RawValue);
}
private class Order10
@ -1616,7 +1615,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Customer").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
var error = Assert.Single(modelState["Customer"].Errors);
Assert.Equal("A value for the 'Customer' property was not provided.", error.ErrorMessage);
}
@ -1670,12 +1670,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Id").Value;
Assert.NotNull(entry.Value);
Assert.Equal("123", entry.Value.RawValue);
Assert.Equal("123", entry.Value.AttemptedValue);
Assert.Equal("123", entry.RawValue);
Assert.Equal("123", entry.AttemptedValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
var error = Assert.Single(modelState["parameter.Customer.Name"].Errors);
Assert.Equal("A value for the 'Name' property was not provided.", error.ErrorMessage);
}
@ -1716,12 +1716,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Customer.Id").Value;
Assert.NotNull(entry.Value);
Assert.Equal("123", entry.Value.RawValue);
Assert.Equal("123", entry.Value.AttemptedValue);
Assert.Equal("123", entry.RawValue);
Assert.Equal("123", entry.AttemptedValue);
entry = Assert.Single(modelState, e => e.Key == "Customer.Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
var error = Assert.Single(modelState["Customer.Name"].Errors);
Assert.Equal("A value for the 'Name' property was not provided.", error.ErrorMessage);
}
@ -1766,12 +1766,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "customParameter.Customer.Id").Value;
Assert.NotNull(entry.Value);
Assert.Equal("123", entry.Value.RawValue);
Assert.Equal("123", entry.Value.AttemptedValue);
Assert.Equal("123", entry.RawValue);
Assert.Equal("123", entry.AttemptedValue);
entry = Assert.Single(modelState, e => e.Key == "customParameter.Customer.Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
var error = Assert.Single(modelState["customParameter.Customer.Name"].Errors);
Assert.Equal("A value for the 'Name' property was not provided.", error.ErrorMessage);
}
@ -1816,7 +1816,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "ProductName").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
var error = Assert.Single(modelState["ProductName"].Errors);
Assert.Equal("A value for the 'ProductName' property was not provided.", error.ErrorMessage);
}
@ -1859,7 +1860,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "customParameter.ProductName").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
var error = Assert.Single(modelState["customParameter.ProductName"].Errors);
Assert.Equal("A value for the 'ProductName' property was not provided.", error.ErrorMessage);
}
@ -1898,9 +1900,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "ProductName").Value;
Assert.NotNull(entry.Value);
Assert.Equal("abc", entry.Value.RawValue);
Assert.Equal("abc", entry.Value.AttemptedValue);
Assert.Equal("abc", entry.RawValue);
Assert.Equal("abc", entry.AttemptedValue);
}
private class Order13
@ -1943,7 +1944,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "OrderIds").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
var error = Assert.Single(modelState["OrderIds"].Errors);
Assert.Equal("A value for the 'OrderIds' property was not provided.", error.ErrorMessage);
}
@ -1986,7 +1988,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "customParameter.OrderIds").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
var error = Assert.Single(modelState["customParameter.OrderIds"].Errors);
Assert.Equal("A value for the 'OrderIds' property was not provided.", error.ErrorMessage);
}
@ -2025,9 +2028,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "OrderIds[0]").Value;
Assert.NotNull(entry.Value);
Assert.Equal("123", entry.Value.RawValue);
Assert.Equal("123", entry.Value.AttemptedValue);
Assert.Equal("123", entry.RawValue);
Assert.Equal("123", entry.AttemptedValue);
}
private class Order14
@ -2072,8 +2074,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.ProductId").Value;
Assert.Equal(string.Empty, entry.Value.AttemptedValue);
Assert.Equal(string.Empty, entry.Value.RawValue);
Assert.Equal(string.Empty, entry.AttemptedValue);
Assert.Equal(string.Empty, entry.RawValue);
var error = Assert.Single(entry.Errors);
Assert.Equal("The value '' is invalid.", error.ErrorMessage);

View File

@ -13,7 +13,7 @@ using Xunit;
namespace Microsoft.AspNet.Mvc.IntegrationTests
{
public class TypeConverterModelBinderIntegrationTest
public class SimpleTypeModelBinderIntegrationTest
{
[Fact]
public async Task BindProperty_WithData_WithPrefix_GetsBound()
@ -58,10 +58,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys, k => k == "CustomParameter.Address.Zip");
Assert.NotNull(modelState[key].Value);
Assert.Equal("1", modelState[key].Value.AttemptedValue);
Assert.Equal("1", modelState[key].Value.RawValue);
Assert.NotNull(modelState[key].Value);
Assert.Equal("1", modelState[key].AttemptedValue);
Assert.Equal("1", modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
}
@ -105,10 +103,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys, k => k == "Address.Zip");
Assert.NotNull(modelState[key].Value);
Assert.Equal("1", modelState[key].Value.AttemptedValue);
Assert.Equal("1", modelState[key].Value.RawValue);
Assert.NotNull(modelState[key].Value);
Assert.Equal("1", modelState[key].AttemptedValue);
Assert.Equal("1", modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
}
@ -152,13 +148,56 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys);
Assert.Equal("Parameter1", key);
Assert.NotNull(modelState[key].Value);
Assert.Equal("someValue", modelState[key].Value.AttemptedValue);
Assert.Equal("someValue", modelState[key].Value.RawValue);
Assert.Equal("someValue", modelState[key].AttemptedValue);
Assert.Equal("someValue", modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
}
[Fact]
public async Task BindParameter_WithMultipleValues_GetsBoundToFirstValue()
{
// Arrange
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
var parameter = new ParameterDescriptor()
{
Name = "Parameter1",
BindingInfo = new BindingInfo(),
ParameterType = typeof(string)
};
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
{
request.QueryString = new QueryString("?Parameter1=someValue&Parameter1=otherValue");
});
var modelState = new ModelStateDictionary();
// Act
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
// Assert
// ModelBindingResult
Assert.NotNull(modelBindingResult);
Assert.True(modelBindingResult.IsModelSet);
// Model
var model = Assert.IsType<string>(modelBindingResult.Model);
Assert.Equal("someValue", model);
// ModelState
Assert.True(modelState.IsValid);
Assert.Equal(1, modelState.Keys.Count);
var key = Assert.Single(modelState.Keys);
Assert.Equal("Parameter1", key);
Assert.Equal("someValue,otherValue", modelState[key].AttemptedValue);
Assert.Equal(new string[] { "someValue", "otherValue" }, modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
}
[Fact]
public async Task BindParameter_NonConvertableValue_GetsError()
@ -201,9 +240,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.Equal("Parameter1", key);
var entry = modelState[key];
Assert.NotNull(entry.Value);
Assert.Equal("abcd", entry.Value.AttemptedValue);
Assert.Equal("abcd", entry.Value.RawValue);
Assert.Equal("abcd", entry.RawValue);
Assert.Equal("abcd", entry.AttemptedValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
var error = Assert.Single(entry.Errors);
@ -247,8 +285,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var key = Assert.Single(modelState.Keys);
Assert.Equal("Parameter1", key);
Assert.Equal(string.Empty, modelState[key].Value.AttemptedValue);
Assert.Equal(string.Empty, modelState[key].Value.RawValue);
Assert.Equal(string.Empty, modelState[key].AttemptedValue);
Assert.Equal(string.Empty, modelState[key].RawValue);
var error = Assert.Single(modelState[key].Errors);
Assert.Equal(error.ErrorMessage, "The value '' is invalid.", StringComparer.Ordinal);
Assert.Null(error.Exception);
@ -292,8 +330,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var key = Assert.Single(modelState.Keys);
Assert.Equal("Parameter1", key);
Assert.Equal(string.Empty, modelState[key].Value.AttemptedValue);
Assert.Equal(string.Empty, modelState[key].Value.RawValue);
Assert.Equal(string.Empty, modelState[key].AttemptedValue);
Assert.Equal(new string[] { string.Empty }, modelState[key].RawValue);
Assert.Empty(modelState[key].Errors);
}
@ -393,10 +431,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.NotNull(entry);
Assert.Empty(entry.Errors);
Assert.Equal(ModelValidationState.Valid, entry.ValidationState);
var result = entry.Value;
Assert.NotNull(result);
Assert.Equal("line 1,line 2", result.AttemptedValue);
Assert.Equal(new[] { "line 1", "line 2" }, result.RawValue);
Assert.Equal("line 1,line 2", entry.AttemptedValue);
Assert.Equal(new[] { "line 1", "line 2" }, entry.RawValue);
}
private class Person

View File

@ -53,9 +53,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -88,9 +87,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -199,9 +197,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("Address.Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -241,9 +238,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -283,9 +279,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -345,9 +340,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -387,7 +381,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var state = entry.Value;
Assert.NotNull(state);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.RawValue);
}
private class Person4
@ -425,9 +419,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -474,9 +467,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -550,9 +542,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("prefix.Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -585,9 +576,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("prefix.Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -689,9 +679,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("prefix.Address.Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -726,9 +715,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("prefix.Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -768,9 +756,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("prefix.Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -820,9 +807,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("prefix.Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -857,7 +843,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var state = entry.Value;
Assert.NotNull(state);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.RawValue);
}
[Fact]
@ -890,9 +876,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("prefix.Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}
@ -939,9 +924,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var entry = Assert.Single(modelState);
Assert.Equal("prefix.Address[0].Street", entry.Key);
var state = entry.Value;
Assert.NotNull(state.Value);
Assert.Equal("SomeStreet", state.Value.AttemptedValue);
Assert.Equal("SomeStreet", state.Value.RawValue);
Assert.Equal("SomeStreet", state.AttemptedValue);
Assert.Equal("SomeStreet", state.RawValue);
Assert.Empty(state.Errors);
Assert.Equal(ModelValidationState.Valid, state.ValidationState);
}

View File

@ -53,8 +53,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.CustomerName").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -91,7 +91,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "CustomerName").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
var error = Assert.Single(entry.Errors);
@ -143,8 +144,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -181,7 +182,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Customer").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
var error = Assert.Single(entry.Errors);
@ -235,8 +237,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -276,7 +278,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
var error = Assert.Single(entry.Errors);
@ -328,8 +331,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Items[0].ItemId").Value;
Assert.Equal("17", entry.Value.AttemptedValue);
Assert.Equal("17", entry.Value.RawValue);
Assert.Equal("17", entry.AttemptedValue);
Assert.Equal("17", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -367,7 +370,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "Items").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
var error = Assert.Single(entry.Errors);
@ -415,8 +419,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter[0].ProductId").Value;
Assert.Equal("17", entry.Value.AttemptedValue);
Assert.Equal("17", entry.Value.RawValue);
Assert.Equal("17", entry.AttemptedValue);
Assert.Equal("17", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -456,7 +460,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter[0].ProductId").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
var error = Assert.Single(entry.Errors);
@ -502,8 +507,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -540,8 +545,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Name").Value;
Assert.Equal("billybob", entry.Value.AttemptedValue);
Assert.Equal("billybob", entry.Value.RawValue);
Assert.Equal("billybob", entry.AttemptedValue);
Assert.Equal("billybob", entry.RawValue);
var error = Assert.Single(entry.Errors);
Assert.Equal("Too Long.", error.ErrorMessage);
@ -592,8 +597,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -630,8 +635,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("billybob", entry.Value.AttemptedValue);
Assert.Equal("billybob", entry.Value.RawValue);
Assert.Equal("billybob", entry.AttemptedValue);
Assert.Equal("billybob", entry.RawValue);
var error = Assert.Single(entry.Errors);
Assert.Equal("Too Long.", error.ErrorMessage);
@ -730,8 +735,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -768,11 +773,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
Assert.Equal("billybob", entry.Value.AttemptedValue);
Assert.Equal("billybob", entry.Value.RawValue);
Assert.Equal("billybob", entry.AttemptedValue);
Assert.Equal("billybob", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
var error = Assert.Single(entry.Errors);
Assert.Equal("Invalid Person.", error.ErrorMessage);
@ -838,8 +844,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Products[0].Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -876,11 +882,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter.Products[0].Name").Value;
Assert.Equal("billybob", entry.Value.AttemptedValue);
Assert.Equal("billybob", entry.Value.RawValue);
Assert.Equal("billybob", entry.AttemptedValue);
Assert.Equal("billybob", entry.RawValue);
entry = Assert.Single(modelState, e => e.Key == "parameter.Products").Value;
Assert.Null(entry.Value);
Assert.Null(entry.RawValue);
Assert.Null(entry.AttemptedValue);
Assert.Equal(ModelValidationState.Invalid, entry.ValidationState);
var error = Assert.Single(entry.Errors);
@ -927,8 +934,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter[0].Name").Value;
Assert.Equal("bill", entry.Value.AttemptedValue);
Assert.Equal("bill", entry.Value.RawValue);
Assert.Equal("bill", entry.AttemptedValue);
Assert.Equal("bill", entry.RawValue);
Assert.Empty(entry.Errors);
}
@ -965,8 +972,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.False(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "parameter[0].Name").Value;
Assert.Equal("billybob", entry.Value.AttemptedValue);
Assert.Equal("billybob", entry.Value.RawValue);
Assert.Equal("billybob", entry.AttemptedValue);
Assert.Equal("billybob", entry.RawValue);
var error = Assert.Single(entry.Errors);
Assert.Equal("Too Long.", error.ErrorMessage);
@ -1070,23 +1077,23 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
Assert.True(modelState.IsValid);
var entry = Assert.Single(modelState, e => e.Key == "HomeAddress.Country.Name").Value;
Assert.Equal("US", entry.Value.AttemptedValue);
Assert.Equal("US", entry.Value.RawValue);
Assert.Equal("US", entry.AttemptedValue);
Assert.Equal("US", entry.RawValue);
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
entry = Assert.Single(modelState, e => e.Key == "ShippingAddresses[0].Zip").Value;
Assert.Equal("45", entry.Value.AttemptedValue);
Assert.Equal("45", entry.Value.RawValue);
Assert.Equal("45", entry.AttemptedValue);
Assert.Equal("45", entry.RawValue);
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
entry = Assert.Single(modelState, e => e.Key == "HomeAddress.Zip").Value;
Assert.Equal("46", entry.Value.AttemptedValue);
Assert.Equal("46", entry.Value.RawValue);
Assert.Equal("46", entry.AttemptedValue);
Assert.Equal("46", entry.RawValue);
Assert.Equal(ModelValidationState.Skipped, entry.ValidationState);
entry = Assert.Single(modelState, e => e.Key == "OfficeAddress").Value;
Assert.Null(entry.Value.AttemptedValue);
var address = Assert.IsType<Address>(entry.Value.RawValue);
Assert.Null(entry.AttemptedValue);
var address = Assert.IsType<Address>(entry.RawValue);
Assert.Equal(47, address.Zip);
// Address itself is not excluded from validation.

View File

@ -39,13 +39,12 @@ namespace Microsoft.AspNet.Mvc
// Assert
var i = 0;
Assert.Equal(12, options.ModelBinders.Count);
Assert.Equal(11, options.ModelBinders.Count);
Assert.IsType(typeof(BinderTypeBasedModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(ServicesModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(BodyModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(HeaderModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(TypeConverterModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(TypeMatchModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(SimpleTypeModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(CancellationTokenModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(ByteArrayModelBinder), options.ModelBinders[i++]);
Assert.IsType(typeof(FormFileModelBinder), options.ModelBinders[i++]);

View File

@ -216,17 +216,13 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
// rawValue, allowMultiple -> expected current values
public static TheoryData<object, bool, IReadOnlyCollection<string>> GetCurrentValues_StringAndCollectionData
public static TheoryData<string[], bool, IReadOnlyCollection<string>> GetCurrentValues_CollectionData
{
get
{
return new TheoryData<object, bool, IReadOnlyCollection<string>>
return new TheoryData<string[], bool, IReadOnlyCollection<string>>
{
// ModelStateDictionary converts single values to arrays and visa-versa.
{ string.Empty, false, new [] { string.Empty } },
{ string.Empty, true, new [] { string.Empty } },
{ "some string", false, new [] { "some string" } },
{ "some string", true, new [] { "some string" } },
// ModelStateDictionary converts arrays to single values if needed.
{ new [] { "some string" }, false, new [] { "some string" } },
{ new [] { "some string" }, true, new [] { "some string" } },
{ new [] { "some string", "some other string" }, false, new [] { "some string" } },
@ -261,9 +257,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
[Theory]
[MemberData(nameof(GetCurrentValues_StringAndCollectionData))]
[MemberData(nameof(GetCurrentValues_CollectionData))]
public void GetCurrentValues_WithModelStateEntryAndViewData_ReturnsModelStateEntry(
object rawValue,
string[] rawValue,
bool allowMultiple,
IReadOnlyCollection<string> expected)
{
@ -274,10 +270,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var viewContext = GetViewContext<Model>(model, metadataProvider);
viewContext.ViewData[nameof(Model.Name)] = "ignored ViewData value";
var valueProviderResult = new ValueProviderResult(rawValue);
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
viewContext.ModelState.SetModelValue(nameof(Model.Name), rawValue, attemptedValue: null);
// Act
var result = htmlGenerator.GetCurrentValues(
@ -292,9 +285,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
[Theory]
[MemberData(nameof(GetCurrentValues_StringAndCollectionData))]
[MemberData(nameof(GetCurrentValues_CollectionData))]
public void GetCurrentValues_WithModelStateEntryModelExplorerAndViewData_ReturnsModelStateEntry(
object rawValue,
string[] rawValue,
bool allowMultiple,
IReadOnlyCollection<string> expected)
{
@ -305,12 +298,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
var viewContext = GetViewContext<Model>(model, metadataProvider);
viewContext.ViewData[nameof(Model.Name)] = "ignored ViewData value";
viewContext.ModelState.SetModelValue(nameof(Model.Name), rawValue, attemptedValue: null);
var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), "ignored model value");
var valueProviderResult = new ValueProviderResult(rawValue);
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
// Act
var result = htmlGenerator.GetCurrentValues(
viewContext,
@ -324,11 +315,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
}
// rawValue -> expected current values
public static TheoryData<string, string[]> GetCurrentValues_StringData
public static TheoryData<string[], string[]> GetCurrentValues_StringData
{
get
{
return new TheoryData<string, string[]>
return new TheoryData<string[], string[]>
{
// 1. If given a ModelExplorer, GetCurrentValues does not use ViewData even if expression result is
// null.
@ -336,8 +327,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
// if entry is null.
// 3. Otherwise, GetCurrentValue does not fall back anywhere else even if ViewData.Model is null.
{ null, null },
{ string.Empty, new [] { string.Empty } },
{ "some string", new [] { "some string" } },
{ new string[] { string.Empty }, new [] { string.Empty } },
{ new string[] { "some string" }, new [] { "some string" } },
};
}
}
@ -345,7 +336,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
[Theory]
[MemberData(nameof(GetCurrentValues_StringData))]
public void GetCurrentValues_WithModelExplorerAndViewData_ReturnsExpressionResult(
string rawValue,
string[] rawValue,
IReadOnlyCollection<string> expected)
{
// Arrange
@ -355,12 +346,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
var viewContext = GetViewContext<Model>(model, metadataProvider);
viewContext.ViewData[nameof(Model.Name)] = "ignored ViewData value";
viewContext.ModelState.SetModelValue(nameof(Model.Name), rawValue, attemptedValue: null);
var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), rawValue);
var valueProviderResult = new ValueProviderResult(rawValue: null);
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
// Act
var result = htmlGenerator.GetCurrentValues(
viewContext,
@ -375,7 +364,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
[Theory]
[MemberData(nameof(GetCurrentValues_StringData))]
public void GetCurrentValues_WithViewData_ReturnsViewDataEntry(
object rawValue,
string[] rawValue,
IReadOnlyCollection<string> expected)
{
// Arrange
@ -385,9 +374,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var viewContext = GetViewContext<Model>(model, metadataProvider);
viewContext.ViewData[nameof(Model.Name)] = rawValue;
var valueProviderResult = new ValueProviderResult(rawValue: null);
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
viewContext.ModelState.SetModelValue(nameof(Model.Name), rawValue, attemptedValue: null);
// Act
var result = htmlGenerator.GetCurrentValues(
@ -402,17 +389,15 @@ namespace Microsoft.AspNet.Mvc.Rendering
[Theory]
[MemberData(nameof(GetCurrentValues_StringData))]
public void GetCurrentValues_WithModel_ReturnsModel(string rawValue, IReadOnlyCollection<string> expected)
public void GetCurrentValues_WithModel_ReturnsModel(string[] rawValue, IReadOnlyCollection<string> expected)
{
// Arrange
var metadataProvider = new TestModelMetadataProvider();
var htmlGenerator = GetGenerator(metadataProvider);
var model = new Model { Name = rawValue };
var model = new Model { Name = rawValue?[0] };
var viewContext = GetViewContext<Model>(model, metadataProvider);
var valueProviderResult = new ValueProviderResult(rawValue: null);
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
viewContext.ModelState.SetModelValue(nameof(Model.Name), rawValue, attemptedValue: null);
// Act
var result = htmlGenerator.GetCurrentValues(
@ -467,13 +452,11 @@ namespace Microsoft.AspNet.Mvc.Rendering
var viewContext = GetViewContext<Model>(model, metadataProvider);
viewContext.ViewData[nameof(Model.Collection)] = new[] { "ignored ViewData value" };
viewContext.ModelState.SetModelValue(nameof(Model.Collection), rawValue, attemptedValue: null);
var modelExplorer =
metadataProvider.GetModelExplorerForType(typeof(List<string>), new List<string>(rawValue));
var valueProviderResult = new ValueProviderResult(rawValue: null);
viewContext.ModelState.SetModelValue(nameof(Model.Collection), valueProviderResult);
// Act
var result = htmlGenerator.GetCurrentValues(
viewContext,
@ -488,7 +471,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
[Theory]
[MemberData(nameof(GetCurrentValues_StringCollectionData))]
public void GetCurrentValues_CollectionWithViewData_ReturnsViewDataEntry(
object[] rawValue,
string[] rawValue,
IReadOnlyCollection<string> expected)
{
// Arrange
@ -498,9 +481,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var viewContext = GetViewContext<Model>(model, metadataProvider);
viewContext.ViewData[nameof(Model.Collection)] = rawValue;
var valueProviderResult = new ValueProviderResult(rawValue: null);
viewContext.ModelState.SetModelValue(nameof(Model.Collection), valueProviderResult);
viewContext.ModelState.SetModelValue(nameof(Model.Collection), rawValue, attemptedValue: null);
// Act
var result = htmlGenerator.GetCurrentValues(
@ -526,9 +507,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
model.Collection.AddRange(rawValue);
var viewContext = GetViewContext<Model>(model, metadataProvider);
var valueProviderResult = new ValueProviderResult(rawValue: null);
viewContext.ModelState.SetModelValue(nameof(Model.Collection), valueProviderResult);
viewContext.ModelState.SetModelValue(
nameof(Model.Collection),
rawValue,
attemptedValue: null);
// Act
var result = htmlGenerator.GetCurrentValues(
@ -637,9 +619,10 @@ namespace Microsoft.AspNet.Mvc.Rendering
var metadataProvider = TestModelMetadataProvider.CreateDefaultProvider();
var htmlGenerator = GetGenerator(metadataProvider);
var viewContext = GetViewContext<Model>(model: null, metadataProvider: metadataProvider);
var valueProviderResult = new ValueProviderResult(rawValue);
viewContext.ModelState.SetModelValue(propertyName, valueProviderResult);
viewContext.ModelState.SetModelValue(
propertyName,
new string[] { rawValue.ToString() },
attemptedValue: null);
// Act
var result = htmlGenerator.GetCurrentValues(

View File

@ -134,9 +134,9 @@ namespace Microsoft.AspNet.Mvc.Rendering
@"<input data-val=""HtmlEncode[[true]]"" data-val-required=""HtmlEncode[[The Boolean field is required.]]"" " +
@"id=""HtmlEncode[[Property1]]"" name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[checkbox]]"" value=""HtmlEncode[[true]]"" />" +
@"<input name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />");
var valueProviderResult = new ValueProviderResult("false", "false", CultureInfo.InvariantCulture);
var helper = DefaultTemplatesUtilities.GetHtmlHelper(GetTestModelViewData());
helper.ViewData.ModelState.SetModelValue("Property1", valueProviderResult);
helper.ViewData.ModelState.SetModelValue("Property1", new string[] { "false" }, "false");
// Act
var html = helper.CheckBox("Property1", isChecked: null, htmlAttributes: null);
@ -438,8 +438,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
@"<input name=""HtmlEncode[[Property1]]"" type=""HtmlEncode[[hidden]]"" value=""HtmlEncode[[false]]"" />");
var viewData = GetTestModelViewData();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
var valueProviderResult = new ValueProviderResult("false", "false", CultureInfo.InvariantCulture);
viewData.ModelState.SetModelValue("Property1", valueProviderResult);
viewData.ModelState.SetModelValue("Property1", new string[] { "false" }, "false");
// Act
var html = helper.CheckBoxFor(m => m.Property1, htmlAttributes: null);
@ -533,9 +532,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
var viewData = GetTestModelViewData();
var helper = DefaultTemplatesUtilities.GetHtmlHelper(viewData);
var valueProviderResult =
new ValueProviderResult(attemptedValue, attemptedValue, CultureInfo.InvariantCulture);
viewData.ModelState.SetModelValue("Property1", valueProviderResult);
viewData.ModelState.SetModelValue("Property1", new string[] { attemptedValue }, attemptedValue);
// Act
var html = helper.CheckBoxFor(m => m.Property1, htmlAttributes: null);

View File

@ -261,10 +261,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
viewData.TemplateInfo.HtmlFieldPrefix = "FieldPrefix";
var modelState = new ModelState();
modelState.Value = new ValueProviderResult(
rawValue: new string[] { "Attempted name value" },
attemptedValue: "Attempted name value",
culture: CultureInfo.InvariantCulture);
modelState.RawValue = new string[] { "Attempted name value" };
modelState.AttemptedValue = "Attempted name value";
viewData.ModelState["FieldPrefix.Name"] = modelState;
// Act
@ -288,10 +286,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
viewData.TemplateInfo.HtmlFieldPrefix = "FieldPrefix";
var modelState = new ModelState();
modelState.Value = new ValueProviderResult(
rawValue: new string[] { "Attempted name value" },
attemptedValue: "Attempted name value",
culture: CultureInfo.InvariantCulture);
modelState.RawValue = new string[] { "Attempted name value" };
modelState.AttemptedValue = "Attempted name value";
viewData.ModelState["FieldPrefix.Name"] = modelState;
// Act

View File

@ -874,7 +874,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
{
return new ModelState
{
Value = new ValueProviderResult(value, value, CultureInfo.InvariantCulture)
RawValue = new string[] { value },
AttemptedValue = value,
};
}

View File

@ -371,7 +371,8 @@ namespace Microsoft.AspNet.Mvc.Rendering
{
return new ModelState
{
Value = new ValueProviderResult(value, value, CultureInfo.InvariantCulture)
RawValue = new string[] { value },
AttemptedValue = value,
};
}

View File

@ -410,18 +410,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
// Arrange
var expectedHtml = GetExpectedSelectElement(SelectSources.ModelStateEntry, allowMultiple: false);
var entryResult = new ValueProviderResult(
SelectSources.ModelStateEntry,
SelectSources.ModelStateEntry.ToString(),
culture: null);
var entryResultWithPrefix = new ValueProviderResult(
SelectSources.ModelStateEntryWithPrefix,
SelectSources.ModelStateEntryWithPrefix.ToString(),
culture: null);
var modelState = new ModelStateDictionary
{
["Property1"] = new ModelState { Value = entryResult },
["Prefix.Property1"] = new ModelState { Value = entryResultWithPrefix },
["Property1"] = new ModelState
{
RawValue = new string[] { SelectSources.ModelStateEntry.ToString() },
AttemptedValue = SelectSources.ModelStateEntry.ToString()
},
["Prefix.Property1"] = new ModelState
{
RawValue = new string[] { SelectSources.ModelStateEntryWithPrefix.ToString() },
AttemptedValue = SelectSources.ModelStateEntryWithPrefix.ToString()
},
};
var provider = TestModelMetadataProvider.CreateDefaultProvider();
@ -451,18 +451,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
SelectSources.ModelStateEntryWithPrefix,
allowMultiple: false);
var entryResult = new ValueProviderResult(
SelectSources.ModelStateEntry,
SelectSources.ModelStateEntry.ToString(),
culture: null);
var entryResultWithPrefix = new ValueProviderResult(
SelectSources.ModelStateEntryWithPrefix,
SelectSources.ModelStateEntryWithPrefix.ToString(),
culture: null);
var modelState = new ModelStateDictionary
{
["Property1"] = new ModelState { Value = entryResult },
["Prefix.Property1"] = new ModelState { Value = entryResultWithPrefix },
["Property1"] = new ModelState
{
RawValue = new string[] { SelectSources.ModelStateEntry.ToString() },
AttemptedValue = SelectSources.ModelStateEntry.ToString()
},
["Prefix.Property1"] = new ModelState
{
RawValue = new string[] { SelectSources.ModelStateEntryWithPrefix.ToString() },
AttemptedValue = SelectSources.ModelStateEntryWithPrefix.ToString()
},
};
var provider = TestModelMetadataProvider.CreateDefaultProvider();
@ -821,18 +821,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
// Arrange
var expectedHtml = GetExpectedSelectElement(SelectSources.ModelStateEntry, allowMultiple: true);
var entryResult = new ValueProviderResult(
SelectSources.ModelStateEntry,
SelectSources.ModelStateEntry.ToString(),
culture: null);
var entryResultWithPrefix = new ValueProviderResult(
SelectSources.ModelStateEntryWithPrefix,
SelectSources.ModelStateEntryWithPrefix.ToString(),
culture: null);
var modelState = new ModelStateDictionary
{
["Property1"] = new ModelState { Value = entryResult },
["Prefix.Property1"] = new ModelState { Value = entryResultWithPrefix },
["Property1"] = new ModelState
{
RawValue = new string[] { SelectSources.ModelStateEntry.ToString() },
AttemptedValue = SelectSources.ModelStateEntry.ToString()
},
["Prefix.Property1"] = new ModelState
{
RawValue = new string[] { SelectSources.ModelStateEntryWithPrefix.ToString() },
AttemptedValue = SelectSources.ModelStateEntryWithPrefix.ToString()
},
};
var provider = TestModelMetadataProvider.CreateDefaultProvider();
@ -862,18 +862,18 @@ namespace Microsoft.AspNet.Mvc.Rendering
SelectSources.ModelStateEntryWithPrefix,
allowMultiple: true);
var entryResult = new ValueProviderResult(
SelectSources.ModelStateEntry,
SelectSources.ModelStateEntry.ToString(),
culture: null);
var entryResultWithPrefix = new ValueProviderResult(
SelectSources.ModelStateEntryWithPrefix,
SelectSources.ModelStateEntryWithPrefix.ToString(),
culture: null);
var modelState = new ModelStateDictionary
{
["Property1"] = new ModelState { Value = entryResult },
["Prefix.Property1"] = new ModelState { Value = entryResultWithPrefix },
["Property1"] = new ModelState
{
RawValue = new string[] { SelectSources.ModelStateEntry.ToString() },
AttemptedValue = SelectSources.ModelStateEntry.ToString()
},
["Prefix.Property1"] = new ModelState
{
RawValue = new string[] { SelectSources.ModelStateEntryWithPrefix.ToString() },
AttemptedValue = SelectSources.ModelStateEntryWithPrefix.ToString()
},
};
var provider = TestModelMetadataProvider.CreateDefaultProvider();

View File

@ -164,17 +164,13 @@ namespace Microsoft.AspNet.Mvc.Core
viewData.TemplateInfo.HtmlFieldPrefix = "FieldPrefix";
var modelState = new ModelState();
modelState.Value = new ValueProviderResult(
rawValue: new string[] { "StringPropertyRawValue" },
attemptedValue: "StringPropertyAttemptedValue",
culture: CultureInfo.InvariantCulture);
modelState.AttemptedValue = "StringPropertyAttemptedValue";
modelState.RawValue = new string[] { "StringPropertyRawValue" };
viewData.ModelState["FieldPrefix.StringProperty"] = modelState;
modelState = new ModelState();
modelState.Value = new ValueProviderResult(
rawValue: new string[] { "ModelRawValue" },
attemptedValue: "ModelAttemptedValue",
culture: CultureInfo.InvariantCulture);
modelState.AttemptedValue = "ModelAttemptedValue";
modelState.RawValue = new string[] { "ModelRawValue" };
viewData.ModelState["FieldPrefix"] = modelState;
// Act & Assert
@ -225,10 +221,8 @@ namespace Microsoft.AspNet.Mvc.Core
viewData["StringProperty"] = "ViewDataValue <\"\">";
var modelState = new ModelState();
modelState.Value = new ValueProviderResult(
rawValue: new string[] { "ObjectPropertyRawValue <\"\">" },
attemptedValue: "ObjectPropertyAttemptedValue <\"\">",
culture: CultureInfo.InvariantCulture);
modelState.AttemptedValue = "ObjectPropertyAttemptedValue <\"\">";
modelState.RawValue = new string[] { "ObjectPropertyRawValue <\"\">" };
viewData.ModelState["ObjectProperty"] = modelState;
// Act & Assert

View File

@ -99,7 +99,7 @@ namespace ModelBindingWebSite.Controllers
bindingContext.ModelName + "." + "productId";
var value = await bindingContext.ValueProvider.GetValueAsync(key);
model.ProductId = (int)value.ConvertTo(typeof(int));
model.ProductId = value.ConvertTo<int>();
var validationNode =
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value);

View File

@ -218,7 +218,7 @@ namespace ModelBindingWebSite.Controllers
public Task<ValueProviderResult> GetValueAsync(string key)
{
return Task.FromResult<ValueProviderResult>(null);
return Task.FromResult<ValueProviderResult>(ValueProviderResult.None);
}
}
}

View File

@ -31,7 +31,7 @@ namespace ValueProvidersWebSite
public Task<ValueProviderResult> GetValueAsync(string key)
{
var value = "custom-value-provider-value";
var result = new ValueProviderResult(value, value, CultureInfo.CurrentCulture);
var result = new ValueProviderResult(value, CultureInfo.CurrentCulture);
return Task.FromResult(result);
}
}