Add `ModelState` entries for greedy and type-matching model binders
- part II of II for #2445 - `FormCollectionModelBinder` is an exception because container is not user-provided - no `ModelState` entry added - enable tests that #2445 was blocking - fix these and other tests expecting different `ModelState` entries - simplify logic in `FormFileModelBinder` `ValueProviderResult` - remove `protected` setters and parameterless constructor - no scenario for their use in subclasses; however `ConvertTo()` remains `virtual` - add single-parameter constructor - use in most of the greedy and type-matching model binders - add doc comments throughout class nits: - use new `ValueProviderResult` constructor in many existing tests - `""` -> `string.Empty` and `vpr` -> `valueProviderResult` in `ValueProviderResultTest` - improve some test names in `BodyValidationIntegrationTests` - do not check `Message` of a Json.NET `Exception`
This commit is contained in:
parent
4a4b8ec87e
commit
715a0b6021
|
|
@ -12,45 +12,83 @@ using Microsoft.Framework.Internal;
|
|||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// Result of an <see cref="IValueProvider.GetValueAsync"/> operation.
|
||||
/// </summary>
|
||||
public class ValueProviderResult
|
||||
{
|
||||
private static readonly CultureInfo _staticCulture = CultureInfo.InvariantCulture;
|
||||
private CultureInfo _instanceCulture;
|
||||
|
||||
// default constructor so that subclassed types can set the properties themselves
|
||||
protected ValueProviderResult()
|
||||
/// <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"/>.
|
||||
/// </summary>
|
||||
/// <param name="rawValue">The <see cref="RawValue"/> value of the new instance.</param>
|
||||
public ValueProviderResult(object rawValue)
|
||||
: this(rawValue, attemptedValue: null, culture: _staticCulture)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instantiates a new instance of the <see cref="ValueProviderResult"/> class with given
|
||||
/// <paramref name="rawValue"/>, <paramref name="attemptedValue"/>, and <paramref name="culture"/>.
|
||||
/// </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)
|
||||
{
|
||||
RawValue = rawValue;
|
||||
AttemptedValue = attemptedValue;
|
||||
Culture = culture;
|
||||
Culture = culture ?? _staticCulture;
|
||||
}
|
||||
|
||||
public string AttemptedValue { get; protected set; }
|
||||
/// <summary>
|
||||
/// <see cref="string"/> conversion of <see cref="RawValue"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Used in helpers that generate <c><textarea></c> elements as well as some error messages.
|
||||
/// </remarks>
|
||||
public string AttemptedValue { get; }
|
||||
|
||||
public CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instanceCulture == null)
|
||||
{
|
||||
_instanceCulture = _staticCulture;
|
||||
}
|
||||
return _instanceCulture;
|
||||
}
|
||||
protected set { _instanceCulture = value; }
|
||||
}
|
||||
/// <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; }
|
||||
|
||||
public object RawValue { get; protected set; }
|
||||
/// <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;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ 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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -21,17 +21,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
return null;
|
||||
}
|
||||
|
||||
var valueProviderResult = await bindingContext.ValueProvider.GetValueAsync(bindingContext.ModelName);
|
||||
|
||||
// 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)
|
||||
{
|
||||
return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
|
||||
}
|
||||
|
||||
var value = valueProviderResult.AttemptedValue;
|
||||
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;
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return new ModelBindingResult(model: null, key: bindingContext.ModelName, isModelSet: false);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
return null;
|
||||
}
|
||||
|
||||
object model = null;
|
||||
object model;
|
||||
var request = bindingContext.OperationBindingContext.HttpContext.Request;
|
||||
if (request.HasFormContentType)
|
||||
{
|
||||
|
|
@ -36,8 +36,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
}
|
||||
else
|
||||
{
|
||||
var formValuesLookup = form.ToDictionary(p => p.Key,
|
||||
p => p.Value);
|
||||
var formValuesLookup = form.ToDictionary(p => p.Key, p => p.Value);
|
||||
model = new FormCollection(formValuesLookup, form.Files);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if DNXCORE50
|
||||
using System.Reflection;
|
||||
#endif
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
|
@ -20,33 +22,38 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
/// <inheritdoc />
|
||||
public async Task<ModelBindingResult> BindModelAsync([NotNull] ModelBindingContext bindingContext)
|
||||
{
|
||||
object value;
|
||||
if (bindingContext.ModelType == typeof(IFormFile))
|
||||
{
|
||||
var postedFiles = await GetFormFilesAsync(bindingContext);
|
||||
var value = postedFiles.FirstOrDefault();
|
||||
var validationNode =
|
||||
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value);
|
||||
return new ModelBindingResult(
|
||||
value,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: value != null,
|
||||
validationNode: validationNode);
|
||||
value = postedFiles.FirstOrDefault();
|
||||
}
|
||||
else if (typeof(IEnumerable<IFormFile>).GetTypeInfo().IsAssignableFrom(
|
||||
bindingContext.ModelType.GetTypeInfo()))
|
||||
else if (typeof(IEnumerable<IFormFile>).IsAssignableFrom(bindingContext.ModelType))
|
||||
{
|
||||
var postedFiles = await GetFormFilesAsync(bindingContext);
|
||||
var value = ModelBindingHelper.ConvertValuesToCollectionType(bindingContext.ModelType, postedFiles);
|
||||
var validationNode =
|
||||
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value);
|
||||
return new ModelBindingResult(
|
||||
value,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: value != null,
|
||||
validationNode: validationNode);
|
||||
value = ModelBindingHelper.ConvertValuesToCollectionType(bindingContext.ModelType, postedFiles);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This binder does not support the requested type.
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
ModelValidationNode validationNode = null;
|
||||
if (value != null)
|
||||
{
|
||||
validationNode =
|
||||
new ModelValidationNode(bindingContext.ModelName, bindingContext.ModelMetadata, value);
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: value);
|
||||
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
|
||||
}
|
||||
|
||||
return new ModelBindingResult(
|
||||
value,
|
||||
bindingContext.ModelName,
|
||||
isModelSet: value != null,
|
||||
validationNode: validationNode);
|
||||
}
|
||||
|
||||
private async Task<List<IFormFile>> GetFormFilesAsync(ModelBindingContext bindingContext)
|
||||
|
|
|
|||
|
|
@ -2,6 +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;
|
||||
#if DNXCORE50
|
||||
using System.Reflection;
|
||||
#endif
|
||||
|
|
@ -59,6 +60,10 @@ 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);
|
||||
}
|
||||
|
||||
return Task.FromResult(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// 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 Microsoft.Framework.Internal;
|
||||
using Xunit;
|
||||
|
|
@ -75,7 +74,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
// Act
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => source.MarkFieldSkipped("key"));
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
"A field previously marked invalid should not be marked skipped.",
|
||||
|
|
@ -138,7 +137,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
// Act
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => source.MarkFieldValid("key"));
|
||||
|
||||
|
||||
// Assert
|
||||
Assert.Equal(
|
||||
"A field previously marked invalid should not be marked valid.",
|
||||
|
|
@ -278,7 +277,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
// Arrange
|
||||
var validState = new ModelState
|
||||
{
|
||||
Value = new ValueProviderResult(null, null, null),
|
||||
Value = new ValueProviderResult(rawValue: null),
|
||||
ValidationState = ModelValidationState.Valid
|
||||
};
|
||||
var msd = new ModelStateDictionary
|
||||
|
|
@ -317,7 +316,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
// Arrange
|
||||
var validState = new ModelState
|
||||
{
|
||||
Value = new ValueProviderResult(null, null, null),
|
||||
Value = new ValueProviderResult(rawValue: null),
|
||||
ValidationState = ModelValidationState.Valid
|
||||
};
|
||||
var msd = new ModelStateDictionary
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
[Fact]
|
||||
public void ConvertTo_ReturnsNullForReferenceTypes_WhenValueIsNull()
|
||||
{
|
||||
var valueProviderResult = new ValueProviderResult(null, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: null);
|
||||
|
||||
var convertedValue = valueProviderResult.ConvertTo(typeof(string));
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
[Fact]
|
||||
public void ConvertTo_ReturnsDefaultForValueTypes_WhenValueIsNull()
|
||||
{
|
||||
var valueProviderResult = new ValueProviderResult(null, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: null);
|
||||
|
||||
var convertedValue = valueProviderResult.ConvertTo(typeof(int));
|
||||
|
||||
|
|
@ -34,10 +34,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToCanConvertArraysToSingleElements()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(new int[] { 1, 20, 42 }, "", CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
new int[] { 1, 20, 42 },
|
||||
string.Empty,
|
||||
CultureInfo.InvariantCulture);
|
||||
|
||||
// Act
|
||||
var converted = (string)vpr.ConvertTo(typeof(string));
|
||||
var converted = (string)valueProviderResult.ConvertTo(typeof(string));
|
||||
|
||||
// Assert
|
||||
Assert.Equal("1", converted);
|
||||
|
|
@ -47,10 +50,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToCanConvertSingleElementsToArrays()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(42, "", CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(42, string.Empty, CultureInfo.InvariantCulture);
|
||||
|
||||
// Act
|
||||
var converted = (string[])vpr.ConvertTo(typeof(string[]));
|
||||
var converted = (string[])valueProviderResult.ConvertTo(typeof(string[]));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(converted);
|
||||
|
|
@ -62,10 +65,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToCanConvertSingleElementsToSingleElements()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(42, "", CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(42, string.Empty, CultureInfo.InvariantCulture);
|
||||
|
||||
// Act
|
||||
var converted = (string)vpr.ConvertTo(typeof(string));
|
||||
var converted = (string)valueProviderResult.ConvertTo(typeof(string));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(converted);
|
||||
|
|
@ -77,10 +80,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
// Arrange
|
||||
object original = null;
|
||||
var vpr = new ValueProviderResult(original, "", CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(original, string.Empty, CultureInfo.InvariantCulture);
|
||||
|
||||
// Act
|
||||
var returned = (int?)vpr.ConvertTo(typeof(int?));
|
||||
var returned = (int?)valueProviderResult.ConvertTo(typeof(int?));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(returned, null);
|
||||
|
|
@ -91,10 +94,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
// Arrange
|
||||
var original = " ";
|
||||
var vpr = new ValueProviderResult(original, "", CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(original, string.Empty, CultureInfo.InvariantCulture);
|
||||
|
||||
// Act
|
||||
var returned = (int?)vpr.ConvertTo(typeof(int?));
|
||||
var returned = (int?)valueProviderResult.ConvertTo(typeof(int?));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(returned, null);
|
||||
|
|
@ -104,10 +107,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsNullIfArrayElementValueIsNull()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(new string[] { null }, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: new string[] { null });
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(int));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(int));
|
||||
|
||||
// Assert
|
||||
Assert.Null(outValue);
|
||||
|
|
@ -117,10 +120,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsNullIfTryingToConvertEmptyArrayToSingleElement()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(new int[0], "", CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(new int[0], string.Empty, CultureInfo.InvariantCulture);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(int));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(int));
|
||||
|
||||
// Assert
|
||||
Assert.Null(outValue);
|
||||
|
|
@ -132,10 +135,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsNullIfTrimmedValueIsEmptyString(object value)
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(value, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: value);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(int));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(int));
|
||||
|
||||
// Assert
|
||||
Assert.Null(outValue);
|
||||
|
|
@ -145,12 +148,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsNullIfTrimmedValueIsEmptyString()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(rawValue: null,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: null);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(int[]));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(int[]));
|
||||
|
||||
// Assert
|
||||
Assert.Null(outValue);
|
||||
|
|
@ -160,7 +161,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfArrayElementIsIntegerAndDestinationTypeIsEnum()
|
||||
{
|
||||
// Arrange
|
||||
var result = new ValueProviderResult(new object[] { 1 }, null, CultureInfo.InvariantCulture);
|
||||
var result = new ValueProviderResult(rawValue: new object[] { 1 });
|
||||
|
||||
// Act
|
||||
var outValue = result.ConvertTo(typeof(IntEnum));
|
||||
|
|
@ -194,7 +195,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
object expected)
|
||||
{
|
||||
// Arrange
|
||||
var result = new ValueProviderResult(new object[] { input }, null, CultureInfo.InvariantCulture);
|
||||
var result = new ValueProviderResult(rawValue: new object[] { input });
|
||||
|
||||
// Act
|
||||
var outValue = result.ConvertTo(enumType);
|
||||
|
|
@ -207,10 +208,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfArrayElementIsStringValueAndDestinationTypeIsEnum()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(new object[] { "1" }, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: new object[] { "1" });
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(IntEnum));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(IntEnum));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(outValue, IntEnum.Value1);
|
||||
|
|
@ -220,10 +221,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfArrayElementIsStringKeyAndDestinationTypeIsEnum()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(new object[] { "Value1" }, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: new object[] { "Value1" });
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(IntEnum));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(IntEnum));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(outValue, IntEnum.Value1);
|
||||
|
|
@ -233,10 +234,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfElementIsStringAndDestinationIsNullableInteger()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult("12", null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: "12");
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(int?));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(int?));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(12, outValue);
|
||||
|
|
@ -246,10 +247,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfElementIsStringAndDestinationIsNullableDouble()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult("12.5", null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: "12.5");
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(double?));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(double?));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(12.5, outValue);
|
||||
|
|
@ -259,10 +260,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfElementIsDecimalAndDestinationIsNullableInteger()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(12M, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: 12M);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(int?));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(int?));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(12, outValue);
|
||||
|
|
@ -272,10 +273,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfElementIsDecimalAndDestinationIsNullableDouble()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(12.5M, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: 12.5M);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(double?));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(double?));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(12.5, outValue);
|
||||
|
|
@ -285,10 +286,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfElementIsDecimalDoubleAndDestinationIsNullableInteger()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(12.5M, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: 12.5M);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(int?));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(int?));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(12, outValue);
|
||||
|
|
@ -298,10 +299,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfElementIsDecimalDoubleAndDestinationIsNullableLong()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(12.5M, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: 12.5M);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(long?));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(long?));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(12L, outValue);
|
||||
|
|
@ -311,10 +312,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToReturnsValueIfArrayElementInstanceOfDestinationType()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(new object[] { "some string" }, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: new object[] { "some string" });
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(string));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(string));
|
||||
|
||||
// Assert
|
||||
Assert.Equal("some string", outValue);
|
||||
|
|
@ -327,10 +328,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertTo_ConvertsEnumArrays(object value)
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(value, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: value);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(IntEnum[]));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(IntEnum[]));
|
||||
|
||||
// Assert
|
||||
var result = Assert.IsType<IntEnum[]>(outValue);
|
||||
|
|
@ -346,10 +347,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertTo_ConvertsFlagsEnumArrays(object value, FlagsEnum[] expected)
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(value, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: value);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(FlagsEnum[]));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(FlagsEnum[]));
|
||||
|
||||
// Assert
|
||||
var result = Assert.IsType<FlagsEnum[]>(outValue);
|
||||
|
|
@ -363,10 +364,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
// Arrange
|
||||
var original = new[] { "some string" };
|
||||
var vpr = new ValueProviderResult(original, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: original);
|
||||
|
||||
// Act
|
||||
var outValue = vpr.ConvertTo(typeof(string[]));
|
||||
var outValue = valueProviderResult.ConvertTo(typeof(string[]));
|
||||
|
||||
// Assert
|
||||
Assert.Same(original, outValue);
|
||||
|
|
@ -379,21 +380,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToThrowsIfConverterThrows(Type destinationType)
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult("this-is-not-a-valid-value", null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: "this-is-not-a-valid-value");
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws(typeof(FormatException), () => vpr.ConvertTo(destinationType));
|
||||
var ex = Assert.Throws(typeof(FormatException), () => valueProviderResult.ConvertTo(destinationType));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConvertToThrowsIfNoConverterExists()
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult("x", null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: "x");
|
||||
var destinationType = typeof(MyClassWithoutConverter);
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => vpr.ConvertTo(destinationType));
|
||||
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.",
|
||||
|
|
@ -405,22 +406,25 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
{
|
||||
// Arrange
|
||||
var original = "12,5";
|
||||
var vpr = new ValueProviderResult(original, null, new CultureInfo("en-GB"));
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue: original,
|
||||
attemptedValue: null,
|
||||
culture: new CultureInfo("en-GB"));
|
||||
var frCulture = new CultureInfo("fr-FR");
|
||||
|
||||
// Act
|
||||
var cultureResult = vpr.ConvertTo(typeof(decimal), frCulture);
|
||||
var cultureResult = valueProviderResult.ConvertTo(typeof(decimal), frCulture);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(12.5M, cultureResult);
|
||||
Assert.Throws<FormatException>(() => vpr.ConvertTo(typeof(decimal)));
|
||||
Assert.Throws<FormatException>(() => valueProviderResult.ConvertTo(typeof(decimal)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CulturePropertyDefaultsToInvariantCulture()
|
||||
{
|
||||
// Arrange
|
||||
var result = new ValueProviderResult(null, null, null);
|
||||
var result = new ValueProviderResult(rawValue: null, attemptedValue: null, culture: null);
|
||||
|
||||
// Act & assert
|
||||
Assert.Same(CultureInfo.InvariantCulture, result.Culture);
|
||||
|
|
@ -431,7 +435,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertToCanConvertIntrinsics<T>(object initialValue, T expectedValue)
|
||||
{
|
||||
// Arrange
|
||||
var result = new ValueProviderResult(initialValue, "", CultureInfo.InvariantCulture);
|
||||
var result = new ValueProviderResult(initialValue, string.Empty, CultureInfo.InvariantCulture);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Equal(expectedValue, result.ConvertTo(typeof(T)));
|
||||
|
|
@ -471,7 +475,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertTo_Throws_IfValueIsNotStringData(Type destinationType)
|
||||
{
|
||||
// Arrange
|
||||
var result = new ValueProviderResult(new MyClassWithoutConverter(), "", CultureInfo.InvariantCulture);
|
||||
var result = new ValueProviderResult(
|
||||
new MyClassWithoutConverter(),
|
||||
string.Empty,
|
||||
CultureInfo.InvariantCulture);
|
||||
|
||||
// Act
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => result.ConvertTo(destinationType));
|
||||
|
|
@ -489,7 +496,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
// Arrange
|
||||
var value = "Hello world";
|
||||
var destinationType = typeof(MyClassWithoutConverter);
|
||||
var result = new ValueProviderResult(value, "", CultureInfo.InvariantCulture);
|
||||
var result = new ValueProviderResult(value, string.Empty, CultureInfo.InvariantCulture);
|
||||
|
||||
// Act
|
||||
var ex = Assert.Throws<InvalidOperationException>(() => result.ConvertTo(destinationType));
|
||||
|
|
@ -513,10 +520,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
public void ConvertTo_ConvertsEnumFlags(object value, object expected)
|
||||
{
|
||||
// Arrange
|
||||
var vpr = new ValueProviderResult(value, null, CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: value);
|
||||
|
||||
// Act
|
||||
var outValue = (FlagsEnum)vpr.ConvertTo(typeof(FlagsEnum));
|
||||
var outValue = (FlagsEnum)valueProviderResult.ConvertTo(typeof(FlagsEnum));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, outValue);
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
// Assert
|
||||
|
||||
// Returns true because it understands the metadata type.
|
||||
// Returns non-null because it understands the metadata type.
|
||||
Assert.NotNull(binderResult);
|
||||
Assert.True(binderResult.IsFatalError);
|
||||
Assert.False(binderResult.IsModelSet);
|
||||
|
|
@ -171,7 +171,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
|
|||
|
||||
// Assert
|
||||
|
||||
// Returns true because it understands the metadata type.
|
||||
// Returns non-null because it understands the metadata type.
|
||||
Assert.NotNull(binderResult);
|
||||
Assert.True(binderResult.IsFatalError);
|
||||
Assert.False(binderResult.IsModelSet);
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
Assert.Equal("foo", binderResult.Key);
|
||||
Assert.Null(binderResult.Model);
|
||||
|
||||
Assert.Empty(bindingContext.ModelState); // No submitted value for "foo".
|
||||
var modelState = Assert.Single(bindingContext.ModelState);
|
||||
Assert.Equal("foo", modelState.Key);
|
||||
Assert.NotNull(modelState.Value.Value);
|
||||
Assert.Equal(value, modelState.Value.Value.RawValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -64,7 +67,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
|||
// Arrange
|
||||
var expected = TestPlatformHelper.IsMono ?
|
||||
"Invalid length." :
|
||||
"The supplied value is invalid for foo.";
|
||||
"The value '\"Fys1\"' is not valid for foo.";
|
||||
|
||||
var valueProvider = new SimpleHttpValueProvider()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -490,9 +490,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
var validationContext = testValidationContext.ModelValidationContext;
|
||||
|
||||
// Set the value on model state as a model binder would.
|
||||
validationContext.ModelState.SetModelValue(
|
||||
"user.Password",
|
||||
Mock.Of<ValueProviderResult>());
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: "password");
|
||||
validationContext.ModelState.SetModelValue("user.Password", valueProviderResult);
|
||||
var validator = new DefaultObjectValidator(
|
||||
testValidationContext.ExcludeFilters,
|
||||
testValidationContext.ModelMetadataProvider);
|
||||
|
|
@ -513,6 +512,7 @@ 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);
|
||||
}
|
||||
|
||||
private class Person2
|
||||
|
|
@ -536,7 +536,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
validationContext.ModelState.Add("person.Address", new ModelState());
|
||||
|
||||
var validator = new DefaultObjectValidator(
|
||||
testValidationContext.ExcludeFilters,
|
||||
testValidationContext.ExcludeFilters,
|
||||
testValidationContext.ModelMetadataProvider);
|
||||
var modelExplorer = testValidationContext.ModelValidationContext.ModelExplorer;
|
||||
var topLevelValidationNode = new ModelValidationNode(
|
||||
|
|
|
|||
|
|
@ -166,10 +166,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
viewContext.ViewData[nameof(Model.Name)] = "ignored ViewData value";
|
||||
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue);
|
||||
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
|
||||
|
||||
// Act
|
||||
|
|
@ -201,10 +198,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
|
||||
var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), "ignored model value");
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue);
|
||||
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
|
||||
|
||||
// Act
|
||||
|
|
@ -254,10 +248,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
|
||||
var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), rawValue);
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue: null,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: null);
|
||||
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
|
||||
|
||||
// Act
|
||||
|
|
@ -285,10 +276,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
var viewContext = GetViewContext<Model>(model, metadataProvider);
|
||||
viewContext.ViewData[nameof(Model.Name)] = rawValue;
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue: null,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: null);
|
||||
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
|
||||
|
||||
// Act
|
||||
|
|
@ -313,10 +301,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
|
||||
var viewContext = GetViewContext<Model>(model, metadataProvider);
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue: null,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: null);
|
||||
viewContext.ModelState.SetModelValue(nameof(Model.Name), valueProviderResult);
|
||||
|
||||
// Act
|
||||
|
|
@ -376,10 +361,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
var modelExplorer =
|
||||
metadataProvider.GetModelExplorerForType(typeof(List<string>), new List<string>(rawValue));
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue: null,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: null);
|
||||
viewContext.ModelState.SetModelValue(nameof(Model.Collection), valueProviderResult);
|
||||
|
||||
// Act
|
||||
|
|
@ -407,10 +389,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
var viewContext = GetViewContext<Model>(model, metadataProvider);
|
||||
viewContext.ViewData[nameof(Model.Collection)] = rawValue;
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue: null,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: null);
|
||||
viewContext.ModelState.SetModelValue(nameof(Model.Collection), valueProviderResult);
|
||||
|
||||
// Act
|
||||
|
|
@ -438,10 +417,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
|
||||
var viewContext = GetViewContext<Model>(model, metadataProvider);
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue: null,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue: null);
|
||||
viewContext.ModelState.SetModelValue(nameof(Model.Collection), valueProviderResult);
|
||||
|
||||
// Act
|
||||
|
|
@ -552,10 +528,7 @@ namespace Microsoft.AspNet.Mvc.Rendering
|
|||
var htmlGenerator = GetGenerator(metadataProvider);
|
||||
var viewContext = GetViewContext<Model>(model: null, metadataProvider: metadataProvider);
|
||||
|
||||
var valueProviderResult = new ValueProviderResult(
|
||||
rawValue,
|
||||
attemptedValue: null,
|
||||
culture: CultureInfo.InvariantCulture);
|
||||
var valueProviderResult = new ValueProviderResult(rawValue);
|
||||
viewContext.ModelState.SetModelValue(propertyName, valueProviderResult);
|
||||
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -3,12 +3,9 @@
|
|||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.IntegrationTests
|
||||
|
|
@ -71,10 +68,10 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
BindingSource = BindingSource.Body
|
||||
|
|
@ -99,8 +96,11 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.NotNull(modelBindingResult);
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
Assert.Null(modelBindingResult.Model);
|
||||
Assert.Empty(modelState.Keys);
|
||||
|
||||
Assert.True(modelState.IsValid);
|
||||
var entry = Assert.Single(modelState);
|
||||
Assert.Empty(entry.Key);
|
||||
Assert.Null(entry.Value.Value.RawValue);
|
||||
}
|
||||
|
||||
private class Person4
|
||||
|
|
@ -111,14 +111,14 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FromBodyAndRequiredOnValueTypeProperty_EmptyBody_AddsModelStateError()
|
||||
public async Task FromBodyAndRequiredOnValueTypeProperty_EmptyBody_JsonFormatterAddsModelStateError()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
|
@ -141,16 +141,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.NotNull(modelBindingResult);
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<Person4>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.False(modelState.IsValid);
|
||||
|
||||
// The error with an empty key is a bug(#2416) in our implementation which does not append the prefix and
|
||||
// use that along with the path. The expected key here would be CustomParameter.Address.
|
||||
var key = Assert.Single(modelState.Keys, k => k == "");
|
||||
var error = Assert.Single(modelState[""].Errors);
|
||||
Assert.StartsWith(
|
||||
"No JSON content found and type 'System.Int32' is not nullable.",
|
||||
error.Exception.Message);
|
||||
Assert.False(modelState.IsValid);
|
||||
var entry = Assert.Single(modelState);
|
||||
Assert.Equal(string.Empty, entry.Key);
|
||||
var error = Assert.Single(entry.Value.Errors);
|
||||
Assert.NotNull(error.Exception);
|
||||
|
||||
// Json.NET currently throws an exception starting with "No JSON content found and type 'System.Int32' is
|
||||
// not nullable." but do not tie test to a particular Json.NET build.
|
||||
Assert.NotEmpty(error.Exception.Message);
|
||||
}
|
||||
|
||||
private class Person2
|
||||
|
|
@ -167,16 +167,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
public int Zip { get; set; }
|
||||
}
|
||||
|
||||
[Theory(Skip = "There should be entries for all model properties which are bound. #2445")]
|
||||
[Theory]
|
||||
[InlineData("{ \"Zip\" : 123 }")]
|
||||
[InlineData("{}")]
|
||||
public async Task FromBodyOnTopLevelProperty_RequiredOnSubProperty_AddsModelStateError(string inputText)
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
BindingInfo = new BindingInfo()
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
|
@ -200,14 +200,15 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<Person2>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
|
||||
Assert.False(modelState.IsValid);
|
||||
Assert.Equal(2, modelState.Keys.Count);
|
||||
var zip = Assert.Single(modelState.Keys, k => k == "CustomParameter.Address.Zip");
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[zip].ValidationState);
|
||||
var address = Assert.Single(modelState, kvp => kvp.Key == "CustomParameter.Address").Value;
|
||||
Assert.Equal(ModelValidationState.Unvalidated, address.ValidationState);
|
||||
|
||||
var street = Assert.Single(modelState.Keys, k => k == "CustomParameter.Address.Street");
|
||||
Assert.Equal(ModelValidationState.Invalid, modelState[street].ValidationState);
|
||||
var error = Assert.Single(modelState[street].Errors);
|
||||
var street = Assert.Single(modelState, kvp => kvp.Key == "CustomParameter.Address.Street").Value;
|
||||
Assert.Equal(ModelValidationState.Invalid, street.ValidationState);
|
||||
var error = Assert.Single(street.Errors);
|
||||
Assert.Equal("The Street field is required.", error.ErrorMessage);
|
||||
}
|
||||
|
||||
|
|
@ -225,16 +226,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
public int Zip { get; set; }
|
||||
}
|
||||
|
||||
[Theory(Skip = "There should be entries for all model properties which are bound. #2445")]
|
||||
[Theory]
|
||||
[InlineData("{ \"Street\" : \"someStreet\" }")]
|
||||
[InlineData("{}")]
|
||||
public async Task FromBodyOnProperty_RequiredOnValueTypeSubProperty_AddsModelStateError(string inputText)
|
||||
public async Task FromBodyOnProperty_Succeeds_IgnoresRequiredOnValueTypeSubProperty(string inputText)
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
BindingInfo = new BindingInfo()
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
|
@ -255,20 +256,11 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
// Assert
|
||||
Assert.NotNull(modelBindingResult);
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
var boundPerson = Assert.IsType<Person3>(modelBindingResult.Model);
|
||||
Assert.NotNull(boundPerson);
|
||||
Assert.False(modelState.IsValid);
|
||||
var street = Assert.Single(modelState.Keys, k => k == "CustomParameter.Address.Street");
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[street].ValidationState);
|
||||
Assert.IsType<Person3>(modelBindingResult.Model);
|
||||
|
||||
// The error with an empty key is a bug(#2416) in our implementation which does not append the prefix and
|
||||
// use that along with the path. The expected key here would be Address.
|
||||
var zip = Assert.Single(modelState.Keys, k => k == "CustomParameter.Address.Zip");
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[zip].ValidationState);
|
||||
var error = Assert.Single(modelState[""].Errors);
|
||||
Assert.StartsWith(
|
||||
"Required property 'Zip' not found in JSON. Path ''",
|
||||
error.Exception.Message);
|
||||
Assert.True(modelState.IsValid);
|
||||
var entry = Assert.Single(modelState);
|
||||
Assert.Equal("CustomParameter.Address", entry.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
public byte[] Token { get; set; }
|
||||
}
|
||||
|
||||
[Theory(Skip = "ModelState.Value not set due to #2445")]
|
||||
[Theory]
|
||||
[InlineData(true)]
|
||||
[InlineData(false)]
|
||||
public async Task BindProperty_WithData_GetsBound(bool fallBackScenario)
|
||||
|
|
@ -61,19 +61,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
Assert.Equal(2, modelState.Keys.Count);
|
||||
Assert.Single(modelState.Keys, k => k == prefix);
|
||||
Assert.Single(modelState.Keys, k => k == queryStringKey);
|
||||
|
||||
var key = Assert.Single(modelState.Keys, k => k == queryStringKey + "[0]");
|
||||
Assert.NotNull(modelState[key].Value); // should be non null bug #2445.
|
||||
Assert.Empty(modelState[key].Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||
|
||||
key = Assert.Single(modelState.Keys, k => k == queryStringKey + "[1]");
|
||||
Assert.NotNull(modelState[key].Value); // should be non null bug #2445.
|
||||
Assert.Empty(modelState[key].Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||
var entry = Assert.Single(modelState);
|
||||
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);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -109,19 +102,18 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Empty(modelState.Keys);
|
||||
}
|
||||
|
||||
[Fact(Skip = "ModelState.Value not set due to #2445")]
|
||||
[Fact]
|
||||
public async Task BindParameter_WithData_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
||||
ParameterType = typeof(byte[])
|
||||
};
|
||||
|
||||
|
|
@ -151,16 +143,11 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
Assert.Equal(3, modelState.Count);
|
||||
Assert.Single(modelState.Keys, k => k == "CustomParameter[0]");
|
||||
Assert.Single(modelState.Keys, k => k == "CustomParameter[1]");
|
||||
var key = Assert.Single(modelState.Keys, k => k == "CustomParameter[2]");
|
||||
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Equal(value, modelState[key].Value.AttemptedValue);
|
||||
Assert.Equal(expectedValue, modelState[key].Value.RawValue);
|
||||
Assert.Empty(modelState[key].Errors);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,12 +27,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
public FormCollection FileCollection { get; set; }
|
||||
}
|
||||
|
||||
[Fact(Skip = "ModelState.Value not set due to #2445")]
|
||||
[Fact]
|
||||
public async Task BindProperty_WithData_WithEmptyPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo(),
|
||||
|
|
@ -69,12 +69,10 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
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); // should be non null bug #2445.
|
||||
Assert.Empty(modelState[key].Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||
var entry = Assert.Single(modelState);
|
||||
Assert.Equal("Address.Zip", entry.Key);
|
||||
Assert.Empty(entry.Value.Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, entry.Value.ValidationState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -82,15 +80,14 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
// Setting a custom parameter prevents it from falling back to an empty prefix.
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
||||
ParameterType = typeof(FormCollection)
|
||||
};
|
||||
|
||||
|
|
@ -113,7 +110,6 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// Model
|
||||
var formCollection = Assert.IsType<FormCollection>(modelBindingResult.Model);
|
||||
Assert.NotNull(formCollection);
|
||||
var file = Assert.Single(formCollection.Files);
|
||||
Assert.NotNull(file);
|
||||
Assert.Equal("form-data; name=CustomParameter; filename=text.txt", file.ContentDisposition);
|
||||
|
|
@ -122,10 +118,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
// Validation should be skipped because we do not validate any parameters and since IFormFile is not
|
||||
// IValidatableObject, we should have no entries in the model state dictionary.
|
||||
Assert.Empty(modelState.Keys);
|
||||
Assert.Empty(modelState);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -133,21 +126,18 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
||||
ParameterType = typeof(FormCollection)
|
||||
};
|
||||
|
||||
// No data is passed.
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
});
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext();
|
||||
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
|
|
@ -162,7 +152,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Empty(modelState.Keys);
|
||||
Assert.Empty(modelState);
|
||||
|
||||
// FormCollection
|
||||
Assert.Empty(collection);
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
public IFormFile File { get; set; }
|
||||
}
|
||||
|
||||
[Fact(Skip = "ModelState.Value not set due to #2445")]
|
||||
[Fact]
|
||||
public async Task BindProperty_WithData_WithEmptyPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -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); // should be non null bug #2445.
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Empty(modelState[key].Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, modelState[key].ValidationState);
|
||||
}
|
||||
|
|
@ -81,15 +81,14 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
{
|
||||
// Arrange
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
// Setting a custom parameter prevents it from falling back to an empty prefix.
|
||||
BinderModelName = "CustomParameter",
|
||||
},
|
||||
|
||||
ParameterType = typeof(IFormFile)
|
||||
};
|
||||
|
||||
|
|
@ -119,10 +118,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
// Validation should be skipped because we do not validate any parameters and since IFormFile is not
|
||||
// IValidatableObject, we should have no entries in the model state dictionary.
|
||||
Assert.Empty(modelState.Keys);
|
||||
var entry = Assert.Single(modelState);
|
||||
Assert.Equal("CustomParameter", entry.Key);
|
||||
Assert.Empty(entry.Value.Errors);
|
||||
Assert.Equal(ModelValidationState.Valid, entry.Value.ValidationState);
|
||||
Assert.Null(entry.Value.Value.AttemptedValue);
|
||||
Assert.Equal(file, entry.Value.Value.RawValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
// This isn't an especially useful scenario - but it exercises what happens when you
|
||||
// try to use a Collection of something that is bound greedily by model-type.
|
||||
//
|
||||
// In this example we choose IFormCollection - because IFormCollection has a dedicated
|
||||
// model binder.
|
||||
// In this example we choose IFormCollection because IFormCollection has a dedicated
|
||||
// model binder.
|
||||
[Fact]
|
||||
public async Task GenericModelBinder_BindsCollection_ElementTypeFromGreedyModelBinder_WithPrefix_Success()
|
||||
{
|
||||
|
|
@ -47,12 +47,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.True(modelBindingResult.IsModelSet);
|
||||
|
||||
var model = Assert.IsType<List<IFormCollection>>(modelBindingResult.Model);
|
||||
Assert.Equal(1, model.Count);
|
||||
Assert.NotNull(model[0]);
|
||||
var formCollection = Assert.Single(model);
|
||||
Assert.NotNull(formCollection);
|
||||
|
||||
Assert.Equal(0, modelState.Count);
|
||||
Assert.Equal(0, modelState.ErrorCount);
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Empty(modelState);
|
||||
}
|
||||
|
||||
// This isn't an especially useful scenario - but it exercises what happens when you
|
||||
|
|
@ -86,12 +86,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.True(modelBindingResult.IsModelSet);
|
||||
|
||||
var model = Assert.IsType<List<IFormCollection>>(modelBindingResult.Model);
|
||||
Assert.Equal(1, model.Count);
|
||||
Assert.NotNull(model[0]);
|
||||
var formCollection = Assert.Single(model);
|
||||
Assert.NotNull(formCollection);
|
||||
|
||||
Assert.Equal(0, modelState.Count);
|
||||
Assert.Equal(0, modelState.ErrorCount);
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Empty(modelState);
|
||||
}
|
||||
|
||||
// This isn't an especially useful scenario - but it exercises what happens when you
|
||||
|
|
@ -217,7 +217,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(Dictionary<string, int>[])
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext((request) =>
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?parameter[0][0].Key=key0¶meter[0][0].Value=10");
|
||||
});
|
||||
|
|
@ -263,7 +263,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(Dictionary<string, int>[])
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext((request) =>
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?[0][0].Key=key0&[0][0].Value=10");
|
||||
});
|
||||
|
|
@ -309,7 +309,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(Dictionary<string, int>[])
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext((request) =>
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?");
|
||||
});
|
||||
|
|
@ -345,7 +345,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(ICollection<KeyValuePair<string, int>>)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext((request) =>
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?parameter[0].Key=key0¶meter[0].Value=10");
|
||||
});
|
||||
|
|
@ -390,7 +390,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(ICollection<KeyValuePair<string, int>>)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext((request) =>
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?[0].Key=key0&[0].Value=10");
|
||||
});
|
||||
|
|
@ -435,7 +435,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(Collection<KeyValuePair<string, int>>)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext((request) =>
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?");
|
||||
});
|
||||
|
|
@ -471,7 +471,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(Dictionary<string, List<int>>)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext((request) =>
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString(
|
||||
"?parameter[0].Key=key0¶meter[0].Value[0]=10¶meter[0].Value[1]=11");
|
||||
|
|
@ -521,7 +521,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(Dictionary<string, List<int>>)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext((request) =>
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?[0].Key=key0&[0].Value[0]=10&[0].Value[1]=11");
|
||||
});
|
||||
|
|
@ -570,7 +570,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(Dictionary<string, List<int>>)
|
||||
};
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext((request) =>
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal("The Street field is required.", error.ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact(Skip = "ModelState.Value not set due to #2445")]
|
||||
[Fact]
|
||||
public async Task BindPropertyFromHeader_WithPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -104,19 +104,17 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Equal(3, modelState.Count);
|
||||
Assert.Single(modelState.Keys, k => k == "prefix.Address");
|
||||
Assert.Single(modelState.Keys, k => k == "prefix");
|
||||
|
||||
var key = Assert.Single(modelState.Keys, k => k == "prefix.Address.Header");
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Equal("someValue", modelState[key].Value.RawValue);
|
||||
Assert.Equal("someValue", modelState[key].Value.AttemptedValue);
|
||||
var entry = Assert.Single(modelState);
|
||||
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);
|
||||
}
|
||||
|
||||
// The scenario is interesting as we to bind the top level model we fallback to empty prefix,
|
||||
// and hence the model state keys have an empty prefix.
|
||||
[Fact(Skip = "ModelState.Value not set due to #2445.")]
|
||||
[Fact]
|
||||
public async Task BindPropertyFromHeader_WithData_WithEmptyPrefix_GetsBound()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -128,11 +126,8 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = typeof(Person)
|
||||
};
|
||||
|
||||
// Do not add any headers.
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request => {
|
||||
request.Headers.Add("Header", new[] { "someValue" });
|
||||
});
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request => request.Headers.Add("Header", new[] { "someValue" }));
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
||||
// Act
|
||||
|
|
@ -152,27 +147,29 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
Assert.Equal(2, modelState.Count);
|
||||
Assert.Single(modelState.Keys, k => k == "Address");
|
||||
var key = Assert.Single(modelState.Keys, k => k == "Address.Header");
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Equal("someValue", modelState[key].Value.RawValue);
|
||||
Assert.Equal("someValue", modelState[key].Value.AttemptedValue);
|
||||
var entry = Assert.Single(modelState);
|
||||
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);
|
||||
}
|
||||
|
||||
[Theory(Skip = "Greedy Model Binders should add a value in model state #2445.")]
|
||||
[Theory]
|
||||
[InlineData(typeof(string[]), "value1, value2, value3")]
|
||||
[InlineData(typeof(string), "value")]
|
||||
public async Task BindParameterFromHeader_WithData_WithPrefix_ModelGetsBound(Type modelType, string value)
|
||||
{
|
||||
// Arrange
|
||||
var expectedValue = value.Split(',').Select(v => v.Trim());
|
||||
var expectedValue = modelType == typeof(string) ?
|
||||
(object)value :
|
||||
(object)value.Split(',').Select(v => v.Trim()).ToArray();
|
||||
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder();
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "Parameter1",
|
||||
BindingInfo = new BindingInfo()
|
||||
BindingInfo = new BindingInfo
|
||||
{
|
||||
BinderModelName = "CustomParameter",
|
||||
BindingSource = BindingSource.Header
|
||||
|
|
@ -180,7 +177,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
ParameterType = modelType
|
||||
};
|
||||
|
||||
Action<HttpRequest> action = (r) => r.Headers.Add("CustomParameter", new[] { value });
|
||||
Action<HttpRequest> action = r => r.Headers.Add("CustomParameter", new[] { value });
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(action);
|
||||
|
||||
// Do not add any headers.
|
||||
|
|
@ -202,12 +199,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// ModelState
|
||||
Assert.True(modelState.IsValid);
|
||||
var key = Assert.Single(modelState.Keys);
|
||||
Assert.Equal("CustomParameter", key);
|
||||
|
||||
Assert.NotNull(modelState[key].Value);
|
||||
Assert.Equal(expectedValue, modelState[key].Value.RawValue);
|
||||
Assert.Equal(value, modelState[key].Value.AttemptedValue);
|
||||
var entry = Assert.Single(modelState);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -44,7 +44,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
public string Street { get; set; }
|
||||
}
|
||||
|
||||
[Fact(Skip = "ModelState.Value not set due to #2445.")]
|
||||
[Fact]
|
||||
public async Task MutableObjectModelBinder_BindsNestedPOCO_WithBodyModelBinder_WithPrefix_Success()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -85,13 +85,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal("bill", entry.Value.AttemptedValue);
|
||||
Assert.Equal("bill", entry.Value.RawValue);
|
||||
|
||||
// These fail due to #2445
|
||||
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);
|
||||
}
|
||||
|
||||
[Fact(Skip = "ModelState.Value not set due to #2445.")]
|
||||
[Fact]
|
||||
public async Task MutableObjectModelBinder_BindsNestedPOCO_WithBodyModelBinder_WithEmptyPrefix_Success()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -132,7 +131,6 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal("bill", entry.Value.AttemptedValue);
|
||||
Assert.Equal("bill", entry.Value.RawValue);
|
||||
|
||||
// These fail due to #2445
|
||||
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);
|
||||
|
|
@ -170,11 +168,14 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal("bill", model.Customer.Name);
|
||||
Assert.Null(model.Customer.Address);
|
||||
|
||||
Assert.Equal(1, modelState.Count);
|
||||
Assert.Equal(2, modelState.Count);
|
||||
Assert.Equal(0, modelState.ErrorCount);
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
|
||||
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Address").Value;
|
||||
Assert.Null(entry.Value.AttemptedValue);
|
||||
Assert.Null(entry.Value.RawValue);
|
||||
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
|
||||
Assert.Equal("bill", entry.Value.AttemptedValue);
|
||||
Assert.Equal("bill", entry.Value.RawValue);
|
||||
}
|
||||
|
|
@ -446,7 +447,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
public byte[] Token { get; set; }
|
||||
}
|
||||
|
||||
[Fact(Skip = "Greedy model binders should set value. #2445")]
|
||||
[Fact]
|
||||
public async Task MutableObjectModelBinder_BindsNestedPOCO_WithByteArrayModelBinder_WithPrefix_Success()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -478,7 +479,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal("bill", model.Customer.Name);
|
||||
Assert.Equal(ByteArrayContent, model.Customer.Token);
|
||||
|
||||
Assert.Equal(2, modelState.Count); // This fails due to #2445
|
||||
Assert.Equal(2, modelState.Count);
|
||||
Assert.Equal(0, modelState.ErrorCount);
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
|
|
@ -486,13 +487,12 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal("bill", entry.Value.AttemptedValue);
|
||||
Assert.Equal("bill", entry.Value.RawValue);
|
||||
|
||||
// These fail due to #2445
|
||||
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Token").Value;
|
||||
Assert.Equal(ByteArrayEncoded, entry.Value.AttemptedValue);
|
||||
Assert.Equal(ByteArrayEncoded, entry.Value.RawValue);
|
||||
}
|
||||
|
||||
[Fact(Skip = "Greedy model binders should set value. #2445")]
|
||||
[Fact]
|
||||
public async Task MutableObjectModelBinder_BindsNestedPOCO_WithByteArrayModelBinder_WithEmptyPrefix_Success()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -544,17 +544,13 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
var parameter = new ParameterDescriptor()
|
||||
{
|
||||
Name = "parameter",
|
||||
ParameterType = typeof(Order1)
|
||||
ParameterType = typeof(Order3)
|
||||
};
|
||||
|
||||
// Need to have a key here so that the MutableObjectModelBinder will recurse to bind elements.
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?parameter.Customer.Name=bill");
|
||||
|
||||
// This is set so that the input formatter does not add an error to model state.
|
||||
// Thus this prevents addition of an extra error unrelated to the test scenario.
|
||||
request.ContentType = "application/json";
|
||||
});
|
||||
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
|
@ -566,10 +562,10 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.NotNull(modelBindingResult);
|
||||
Assert.True(modelBindingResult.IsModelSet);
|
||||
|
||||
var model = Assert.IsType<Order1>(modelBindingResult.Model);
|
||||
var model = Assert.IsType<Order3>(modelBindingResult.Model);
|
||||
Assert.NotNull(model.Customer);
|
||||
Assert.Equal("bill", model.Customer.Name);
|
||||
Assert.Null(model.Customer.Address);
|
||||
Assert.Null(model.Customer.Token);
|
||||
|
||||
Assert.Equal(1, modelState.Count);
|
||||
Assert.Equal(0, modelState.ErrorCount);
|
||||
|
|
@ -594,7 +590,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
public IEnumerable<IFormFile> Documents { get; set; }
|
||||
}
|
||||
|
||||
[Fact(Skip = "Greedy model binders should set value. #2445")]
|
||||
[Fact]
|
||||
public async Task MutableObjectModelBinder_BindsNestedPOCO_WithFormFileModelBinder_WithPrefix_Success()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -626,7 +622,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal("bill", model.Customer.Name);
|
||||
Assert.Single(model.Customer.Documents);
|
||||
|
||||
Assert.Equal(2, modelState.Count); // This fails due to #2445
|
||||
Assert.Equal(2, modelState.Count);
|
||||
Assert.Equal(0, modelState.ErrorCount);
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
|
|
@ -639,7 +635,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Same(model.Customer.Documents, entry.Value.RawValue);
|
||||
}
|
||||
|
||||
[Fact(Skip = "Greedy model binders should set value. #2445")]
|
||||
[Fact]
|
||||
public async Task MutableObjectModelBinder_BindsNestedPOCO_WithFormFileModelBinder_WithEmptyPrefix_Success()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -717,11 +713,16 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal("bill", model.Customer.Name);
|
||||
Assert.Empty(model.Customer.Documents);
|
||||
|
||||
Assert.Equal(1, modelState.Count);
|
||||
Assert.Equal(2, modelState.Count);
|
||||
Assert.Equal(0, modelState.ErrorCount);
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
var entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
|
||||
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);
|
||||
|
||||
entry = Assert.Single(modelState, e => e.Key == "parameter.Customer.Name").Value;
|
||||
Assert.Equal("bill", entry.Value.AttemptedValue);
|
||||
Assert.Equal("bill", entry.Value.RawValue);
|
||||
}
|
||||
|
|
@ -1529,7 +1530,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
|
||||
// If a nested POCO object has all properties bound from a greedy source, then it should be populated
|
||||
// if the top-level object is created.
|
||||
[Fact(Skip = "ModelState.Value not set due to #2445.")]
|
||||
[Fact]
|
||||
public async Task MutableObjectModelBinder_BindsNestedPOCO_WithAllGreedyBoundProperties()
|
||||
{
|
||||
// Arrange
|
||||
|
|
@ -1567,7 +1568,7 @@ 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); // This fails due to #2445
|
||||
Assert.Null(entry.Value.AttemptedValue);
|
||||
Assert.Same(model.Customer.Address, entry.Value.RawValue);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Name = "parameter",
|
||||
ParameterType = typeof(Order1)
|
||||
};
|
||||
|
||||
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString = new QueryString("?parameter.CustomerName=bill");
|
||||
|
|
@ -1020,6 +1020,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
private class Address
|
||||
{
|
||||
public int Street { get; set; }
|
||||
|
||||
public string State { get; set; }
|
||||
|
||||
[Range(10000, 99999)]
|
||||
|
|
@ -1032,30 +1033,32 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TypeBasedExclusion_ForBodyAndNonBodyBoundModels()
|
||||
{
|
||||
// Arrange
|
||||
var parameter = new ParameterDescriptor()
|
||||
var parameter = new ParameterDescriptor
|
||||
{
|
||||
Name = "parameter",
|
||||
ParameterType = typeof(Order11)
|
||||
};
|
||||
|
||||
MvcOptions testOptions = null;
|
||||
var input = "{\"OfficeAddress.Zip\":\"45\"}";
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(request =>
|
||||
{
|
||||
request.QueryString =
|
||||
new QueryString("?HomeAddress.Country.Name=US&ShippingAddresses[0].Zip=45&HomeAddress.Zip=46");
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input));
|
||||
request.ContentType = "application/json";
|
||||
},
|
||||
options => {
|
||||
|
||||
options.ValidationExcludeFilters.Add(typeof(Address));
|
||||
testOptions = options;
|
||||
});
|
||||
var input = "{\"Zip\":\"47\"}";
|
||||
var operationContext = ModelBindingTestHelper.GetOperationBindingContext(
|
||||
request =>
|
||||
{
|
||||
request.QueryString =
|
||||
new QueryString("?HomeAddress.Country.Name=US&ShippingAddresses[0].Zip=45&HomeAddress.Zip=46");
|
||||
request.Body = new MemoryStream(Encoding.UTF8.GetBytes(input));
|
||||
request.ContentType = "application/json";
|
||||
},
|
||||
options =>
|
||||
{
|
||||
options.ValidationExcludeFilters.Add(typeof(Address));
|
||||
testOptions = options;
|
||||
});
|
||||
|
||||
var argumentBinder = ModelBindingTestHelper.GetArgumentBinder(testOptions);
|
||||
var modelState = new ModelStateDictionary();
|
||||
|
|
@ -1063,7 +1066,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
// Act
|
||||
var modelBindingResult = await argumentBinder.BindModelAsync(parameter, modelState, operationContext);
|
||||
|
||||
Assert.Equal(3, modelState.Count);
|
||||
Assert.Equal(4, modelState.Count);
|
||||
Assert.Equal(0, modelState.ErrorCount);
|
||||
Assert.True(modelState.IsValid);
|
||||
|
||||
|
|
@ -1081,6 +1084,14 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
Assert.Equal("46", entry.Value.AttemptedValue);
|
||||
Assert.Equal("46", entry.Value.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.Equal(47, address.Zip);
|
||||
|
||||
// Address itself is not excluded from validation.
|
||||
Assert.Equal(ModelValidationState.Valid, entry.ValidationState);
|
||||
}
|
||||
|
||||
private static void AssertRequiredError(string key, ModelError error)
|
||||
|
|
|
|||
Loading…
Reference in New Issue