diff --git a/src/Microsoft.AspNet.Mvc.Abstractions/Formatters/InputFormatterContext.cs b/src/Microsoft.AspNet.Mvc.Abstractions/Formatters/InputFormatterContext.cs
index 8314fb041e..ef3d4e8b80 100644
--- a/src/Microsoft.AspNet.Mvc.Abstractions/Formatters/InputFormatterContext.cs
+++ b/src/Microsoft.AspNet.Mvc.Abstractions/Formatters/InputFormatterContext.cs
@@ -29,7 +29,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
HttpContext httpContext,
string modelName,
ModelStateDictionary modelState,
- Type modelType)
+ ModelMetadata metadata)
{
if (httpContext == null)
{
@@ -46,15 +46,16 @@ namespace Microsoft.AspNet.Mvc.Formatters
throw new ArgumentNullException(nameof(modelState));
}
- if (modelType == null)
+ if (metadata == null)
{
- throw new ArgumentNullException(nameof(modelType));
+ throw new ArgumentNullException(nameof(metadata));
}
HttpContext = httpContext;
ModelName = modelName;
ModelState = modelState;
- ModelType = modelType;
+ Metadata = metadata;
+ ModelType = metadata.ModelType;
}
///
@@ -73,7 +74,12 @@ namespace Microsoft.AspNet.Mvc.Formatters
public ModelStateDictionary ModelState { get; }
///
- /// Gets the expected of the model represented by the request body.
+ /// Gets the requested of the request body deserialization.
+ ///
+ public ModelMetadata Metadata { get; }
+
+ ///
+ /// Gets the requested of the request body deserialization.
///
public Type ModelType { get; }
}
diff --git a/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ModelStateDictionary.cs b/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ModelStateDictionary.cs
index 8245161971..bb27c24dff 100644
--- a/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ModelStateDictionary.cs
+++ b/src/Microsoft.AspNet.Mvc.Abstractions/ModelBinding/ModelStateDictionary.cs
@@ -69,7 +69,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
///
///
/// tracks the number of model errors added by calls to
- /// or .
+ /// or
+ /// .
/// Once the value of MaxAllowedErrors - 1 is reached, if another attempt is made to add an error,
/// the error message will be ignored and a will be added.
///
@@ -202,7 +203,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
///
/// The key of the to add errors to.
/// The to add.
- public void AddModelError(string key, Exception exception)
+ public void AddModelError(string key, Exception exception, ModelMetadata metadata)
{
if (key == null)
{
@@ -214,7 +215,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
throw new ArgumentNullException(nameof(exception));
}
- TryAddModelError(key, exception);
+ if (metadata == null)
+ {
+ throw new ArgumentNullException(nameof(metadata));
+ }
+
+ TryAddModelError(key, exception, metadata);
}
///
@@ -228,7 +234,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
/// True if the given error was added, false if the error was ignored.
/// See .
///
- public bool TryAddModelError(string key, Exception exception)
+ public bool TryAddModelError(string key, Exception exception, ModelMetadata metadata)
{
if (key == null)
{
@@ -240,6 +246,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
throw new ArgumentNullException(nameof(exception));
}
+ if (metadata == null)
+ {
+ throw new ArgumentNullException(nameof(metadata));
+ }
+
if (ErrorCount >= MaxAllowedErrors - 1)
{
EnsureMaxErrorsReachedRecorded();
@@ -252,16 +263,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
ModelStateEntry entry;
TryGetValue(key, out entry);
+ var name = metadata.GetDisplayName();
string errorMessage;
if (entry == null)
{
- errorMessage = Resources.FormatModelError_InvalidValue_GenericMessage(key);
+ errorMessage = Resources.FormatModelError_InvalidValue_GenericMessage(name);
}
else
{
errorMessage = Resources.FormatModelError_InvalidValue_MessageWithModelValue(
entry.AttemptedValue,
- key);
+ name);
}
return TryAddModelError(key, errorMessage);
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BodyModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BodyModelBinder.cs
index b62726ddd8..739410f6bc 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BodyModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/BodyModelBinder.cs
@@ -59,7 +59,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
httpContext,
modelBindingKey,
bindingContext.ModelState,
- bindingContext.ModelType);
+ bindingContext.ModelMetadata);
var formatters = bindingContext.OperationBindingContext.InputFormatters;
var formatter = formatters.FirstOrDefault(f => f.CanRead(formatterContext));
@@ -95,7 +95,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
}
catch (Exception ex)
{
- bindingContext.ModelState.AddModelError(modelBindingKey, ex);
+ bindingContext.ModelState.AddModelError(modelBindingKey, ex, bindingContext.ModelMetadata);
// This model binder is the only handler for the Body binding source and it cannot run twice. Always
// tell the model binding system to skip other model binders and never to fall back i.e. indicate a
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ByteArrayModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ByteArrayModelBinder.cs
index fd5d86adca..eada01b85c 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ByteArrayModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/ByteArrayModelBinder.cs
@@ -50,9 +50,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var model = Convert.FromBase64String(value);
return ModelBindingResult.SuccessAsync(bindingContext.ModelName, model);
}
- catch (Exception ex)
+ catch (Exception exception)
{
- bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, ex);
+ bindingContext.ModelState.TryAddModelError(
+ bindingContext.ModelName,
+ exception,
+ bindingContext.ModelMetadata);
}
// Matched the type (byte[]) only this binder supports. As in missing data cases, always tell the model
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs
index e94fa618fb..439c682b4c 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/MutableObjectModelBinder.cs
@@ -592,7 +592,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
var validationState = modelState.GetFieldValidationState(modelStateKey);
if (validationState == ModelValidationState.Unvalidated)
{
- modelState.AddModelError(modelStateKey, exception);
+ modelState.AddModelError(modelStateKey, exception, bindingContext.ModelMetadata);
}
}
diff --git a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/SimpleTypeModelBinder.cs b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/SimpleTypeModelBinder.cs
index bc36685396..4963002370 100644
--- a/src/Microsoft.AspNet.Mvc.Core/ModelBinding/SimpleTypeModelBinder.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/ModelBinding/SimpleTypeModelBinder.cs
@@ -60,9 +60,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
return ModelBindingResult.SuccessAsync(bindingContext.ModelName, model);
}
}
- catch (Exception ex)
+ catch (Exception exception)
{
- bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, ex);
+ bindingContext.ModelState.TryAddModelError(
+ bindingContext.ModelName,
+ exception,
+ bindingContext.ModelMetadata);
// Were able to find a converter for the type but conversion failed.
// Tell the model binding system to skip other model binders.
diff --git a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonInputFormatter.cs b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonInputFormatter.cs
index f94ef448ef..badf691390 100644
--- a/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonInputFormatter.cs
+++ b/src/Microsoft.AspNet.Mvc.Formatters.Json/JsonInputFormatter.cs
@@ -6,7 +6,7 @@ using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.Internal;
-using Microsoft.Net.Http.Headers;
+using Microsoft.AspNet.Mvc.ModelBinding;
using Newtonsoft.Json;
namespace Microsoft.AspNet.Mvc.Formatters
@@ -101,7 +101,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
}
}
- context.ModelState.TryAddModelError(key, eventArgs.ErrorContext.Error);
+ var metadata = GetPathMetadata(context.Metadata, eventArgs.ErrorContext.Path);
+ context.ModelState.TryAddModelError(key, eventArgs.ErrorContext.Error, metadata);
// Error must always be marked as handled
// Failure to do so can cause the exception to be rethrown at every recursive level and
@@ -171,5 +172,51 @@ namespace Microsoft.AspNet.Mvc.Formatters
{
return JsonSerializer.Create(SerializerSettings);
}
+
+ private ModelMetadata GetPathMetadata(ModelMetadata metadata, string path)
+ {
+ var index = 0;
+ while (index >= 0 && index < path.Length)
+ {
+ if (path[index] == '[')
+ {
+ // At start of "[0]".
+ if (metadata.ElementMetadata == null)
+ {
+ // Odd case but don't throw just because ErrorContext had an odd-looking path.
+ break;
+ }
+
+ metadata = metadata.ElementMetadata;
+ index = path.IndexOf(']', index);
+ }
+ else if (path[index] == '.' || path[index] == ']')
+ {
+ // Skip '.' in "prefix.property" or "[0].property" or ']' in "[0]".
+ index++;
+ }
+ else
+ {
+ // At start of "property", "property." or "property[0]".
+ var endIndex = path.IndexOfAny(new[] { '.', '[' }, index);
+ if (endIndex == -1)
+ {
+ endIndex = path.Length;
+ }
+
+ var propertyName = path.Substring(index, endIndex - index);
+ if (metadata.Properties[propertyName] == null)
+ {
+ // Odd case but don't throw just because ErrorContext had an odd-looking path.
+ break;
+ }
+
+ metadata = metadata.Properties[propertyName];
+ index = endIndex;
+ }
+ }
+
+ return metadata;
+ }
}
}
diff --git a/src/Microsoft.AspNet.Mvc.ViewFeatures/ModelStateDictionaryExtensions.cs b/src/Microsoft.AspNet.Mvc.ViewFeatures/ModelStateDictionaryExtensions.cs
index 4e65b3ba9c..58c2f71501 100644
--- a/src/Microsoft.AspNet.Mvc.ViewFeatures/ModelStateDictionaryExtensions.cs
+++ b/src/Microsoft.AspNet.Mvc.ViewFeatures/ModelStateDictionaryExtensions.cs
@@ -26,6 +26,21 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Expression> expression,
string errorMessage)
{
+ if (modelState == null)
+ {
+ throw new ArgumentNullException(nameof(modelState));
+ }
+
+ if (expression == null)
+ {
+ throw new ArgumentNullException(nameof(expression));
+ }
+
+ if (errorMessage == null)
+ {
+ throw new ArgumentNullException(nameof(errorMessage));
+ }
+
modelState.AddModelError(GetExpressionText(expression), errorMessage);
}
@@ -40,9 +55,25 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public static void AddModelError(
this ModelStateDictionary modelState,
Expression> expression,
- Exception exception)
+ Exception exception,
+ ModelMetadata metadata)
{
- modelState.AddModelError(GetExpressionText(expression), exception);
+ if (modelState == null)
+ {
+ throw new ArgumentNullException(nameof(modelState));
+ }
+
+ if (expression == null)
+ {
+ throw new ArgumentNullException(nameof(expression));
+ }
+
+ if (metadata == null)
+ {
+ throw new ArgumentNullException(nameof(metadata));
+ }
+
+ modelState.AddModelError(GetExpressionText(expression), exception, metadata);
}
///
@@ -59,6 +90,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
this ModelStateDictionary modelState,
Expression> expression)
{
+ if (modelState == null)
+ {
+ throw new ArgumentNullException(nameof(modelState));
+ }
+
+ if (expression == null)
+ {
+ throw new ArgumentNullException(nameof(expression));
+ }
+
return modelState.Remove(GetExpressionText(expression));
}
@@ -73,6 +114,16 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
this ModelStateDictionary modelState,
Expression> expression)
{
+ if (modelState == null)
+ {
+ throw new ArgumentNullException(nameof(modelState));
+ }
+
+ if (expression == null)
+ {
+ throw new ArgumentNullException(nameof(expression));
+ }
+
string modelKey = GetExpressionText(expression);
if (string.IsNullOrEmpty(modelKey))
{
diff --git a/test/Microsoft.AspNet.Mvc.Abstractions.Test/ModelBinding/ModelStateDictionaryTest.cs b/test/Microsoft.AspNet.Mvc.Abstractions.Test/ModelBinding/ModelStateDictionaryTest.cs
index 2bc7e3667e..f99c08ff89 100644
--- a/test/Microsoft.AspNet.Mvc.Abstractions.Test/ModelBinding/ModelStateDictionaryTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Abstractions.Test/ModelBinding/ModelStateDictionaryTest.cs
@@ -179,10 +179,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var dictionary = new ModelStateDictionary();
dictionary.AddModelError("some key", "some error");
- var ex = new Exception();
+ var exception = new Exception();
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
// Act
- dictionary.AddModelError("some key", ex);
+ dictionary.AddModelError("some key", exception, metadata);
// Assert
Assert.Equal(2, dictionary.ErrorCount);
@@ -191,7 +193,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Assert.Equal(2, kvp.Value.Errors.Count);
Assert.Equal("some error", kvp.Value.Errors[0].ErrorMessage);
- Assert.Same(ex, kvp.Value.Errors[1].Exception);
+ Assert.Same(exception, kvp.Value.Errors[1].Exception);
}
[Fact]
@@ -546,9 +548,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
MaxAllowedErrors = 5
};
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
dictionary.AddModelError("key1", "error1");
- dictionary.AddModelError("key2", new Exception());
- dictionary.AddModelError("key3", new Exception());
+ dictionary.AddModelError("key2", new Exception(), metadata);
+ dictionary.AddModelError("key3", new Exception(), metadata);
dictionary.AddModelError("key4", "error4");
dictionary.AddModelError("key5", "error5");
@@ -572,6 +576,8 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
MaxAllowedErrors = 3
};
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
// Act and Assert
Assert.False(dictionary.HasReachedMaxErrors);
@@ -579,7 +585,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
Assert.True(result);
Assert.False(dictionary.HasReachedMaxErrors);
- result = dictionary.TryAddModelError("key2", new Exception());
+ result = dictionary.TryAddModelError("key2", new Exception(), metadata);
Assert.True(result);
Assert.False(dictionary.HasReachedMaxErrors); // Still room for TooManyModelErrorsException.
@@ -614,10 +620,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
MaxAllowedErrors = 4
};
- dictionary.AddModelError("key1", new Exception());
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
+ dictionary.AddModelError("key1", new Exception(), metadata);
dictionary.AddModelError("key2", "error2");
dictionary.AddModelError("key3", "error3");
- dictionary.AddModelError("key3", new Exception());
+ dictionary.AddModelError("key3", new Exception(), metadata);
// Act and Assert
Assert.True(dictionary.HasReachedMaxErrors);
@@ -642,15 +650,17 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
MaxAllowedErrors = 3
};
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
// Act and Assert
var result = dictionary.TryAddModelError("key1", "error1");
Assert.True(result);
- result = dictionary.TryAddModelError("key2", new Exception());
+ result = dictionary.TryAddModelError("key2", new Exception(), metadata);
Assert.True(result);
- result = dictionary.TryAddModelError("key3", new Exception());
+ result = dictionary.TryAddModelError("key3", new Exception(), metadata);
Assert.False(result);
Assert.Equal(3, dictionary.Count);
@@ -668,10 +678,12 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
{
MaxAllowedErrors = 3
};
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
// Act
dictionary.AddModelError("key1", "error1");
- dictionary.TryAddModelError("key3", new Exception());
+ dictionary.TryAddModelError("key3", new Exception(), metadata);
var copy = new ModelStateDictionary(dictionary);
copy.AddModelError("key2", "error2");
@@ -711,11 +723,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public void ModelStateDictionary_ReturnGenericErrorMessage_WhenModelStateNotSet()
{
// Arrange
- var expected = "The supplied value is invalid for key.";
+ var expected = "The supplied value is invalid for Length.";
var dictionary = new ModelStateDictionary();
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
// Act
- dictionary.TryAddModelError("key", new FormatException());
+ dictionary.TryAddModelError("key", new FormatException(), metadata);
// Assert
var error = Assert.Single(dictionary["key"].Errors);
@@ -726,12 +740,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public void ModelStateDictionary_ReturnSpecificErrorMessage_WhenModelStateSet()
{
// Arrange
- var expected = "The value 'some value' is not valid for key.";
+ var expected = "The value 'some value' is not valid for Length.";
var dictionary = new ModelStateDictionary();
dictionary.SetModelValue("key", new string[] { "some value" }, "some value");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
// Act
- dictionary.TryAddModelError("key", new FormatException());
+ dictionary.TryAddModelError("key", new FormatException(), metadata);
// Assert
var error = Assert.Single(dictionary["key"].Errors);
@@ -744,9 +760,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// Arrange
var dictionary = new ModelStateDictionary();
dictionary.SetModelValue("key", new string[] { "some value" }, "some value");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
// Act
- dictionary.TryAddModelError("key", new InvalidOperationException());
+ dictionary.TryAddModelError("key", new InvalidOperationException(), metadata);
// Assert
var error = Assert.Single(dictionary["key"].Errors);
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/InputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/InputFormatterTest.cs
index dd7fca8b8e..edce8d3bfd 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/InputFormatterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/Formatters/InputFormatterTest.cs
@@ -36,11 +36,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
var formatter = new CatchAllFormatter();
var httpContext = new DefaultHttpContext();
httpContext.Request.ContentType = requestContentType;
+
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(void));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(void));
+ metadata: metadata);
// Act
var result = formatter.CanRead(context);
@@ -66,11 +69,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
var formatter = new MultipartFormatter();
var httpContext = new DefaultHttpContext();
httpContext.Request.ContentType = requestContentType;
+
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(void));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(void));
+ metadata: metadata);
// Act
var result = formatter.CanRead(context);
@@ -93,11 +99,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
var formatter = new MultipartFormatter();
var httpContext = new DefaultHttpContext();
httpContext.Request.ContentType = requestContentType;
+
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(void));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(void));
+ metadata: metadata);
// Act
var result = formatter.CanRead(context);
@@ -123,11 +132,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
var formatter = new MultipartMixedFormatter();
var httpContext = new DefaultHttpContext();
httpContext.Request.ContentType = requestContentType;
+
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(void));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(void));
+ metadata: metadata);
// Act
var result = formatter.CanRead(context);
@@ -150,11 +162,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
var formatter = new MultipartMixedFormatter();
var httpContext = new DefaultHttpContext();
httpContext.Request.ContentType = requestContentType;
+
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(void));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(void));
+ metadata: metadata);
// Act
var result = formatter.CanRead(context);
@@ -183,11 +198,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
var formatter = new MathMLFormatter();
var httpContext = new DefaultHttpContext();
httpContext.Request.ContentType = requestContentType;
+
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(void));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(void));
+ metadata: metadata);
// Act
var result = formatter.CanRead(context);
@@ -209,11 +227,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
var formatter = new MathMLFormatter();
var httpContext = new DefaultHttpContext();
httpContext.Request.ContentType = requestContentType;
+
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(void));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(void));
+ metadata: metadata);
// Act
var result = formatter.CanRead(context);
@@ -240,11 +261,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
var formatter = new XmlFormatter();
var httpContext = new DefaultHttpContext();
httpContext.Request.ContentType = requestContentType;
+
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(void));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(void));
+ metadata: metadata);
// Act
var result = formatter.CanRead(context);
@@ -268,11 +292,14 @@ namespace Microsoft.AspNet.Mvc.Formatters
var formatter = new XmlFormatter();
var httpContext = new DefaultHttpContext();
httpContext.Request.ContentType = requestContentType;
+
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(void));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(void));
+ metadata: metadata);
// Act
var result = formatter.CanRead(context);
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/ByteArrayModelBinderTests.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/ByteArrayModelBinderTests.cs
index 767a7e473c..b5f8d2bb28 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/ByteArrayModelBinderTests.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/ByteArrayModelBinderTests.cs
@@ -62,7 +62,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModelAddsModelErrorsOnInvalidCharacters()
{
// Arrange
- var expected = "The value '\"Fys1\"' is not valid for foo.";
+ var expected = "The value '\"Fys1\"' is not valid for Byte[].";
var valueProvider = new SimpleValueProvider()
{
diff --git a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/SimpleTypeModelBinderTest.cs b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/SimpleTypeModelBinderTest.cs
index 36b9c04efd..fcd825d704 100644
--- a/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/SimpleTypeModelBinderTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Core.Test/ModelBinding/SimpleTypeModelBinderTest.cs
@@ -113,7 +113,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Test
public async Task BindModel_Error_FormatExceptionsTurnedIntoStringsInModelState()
{
// Arrange
- var message = "The value 'not an integer' is not valid for theModelName.";
+ var message = "The value 'not an integer' is not valid for Int32.";
var bindingContext = GetBindingContext(typeof(int));
bindingContext.ValueProvider = new SimpleValueProvider
{
diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs
index 5b502b2202..e11be51c8c 100644
--- a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonInputFormatterTest.cs
@@ -38,11 +38,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var contentBytes = Encoding.UTF8.GetBytes("content");
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(string));
var formatterContext = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(string));
+ metadata: metadata);
// Act
var result = formatter.CanRead(formatterContext);
@@ -84,11 +86,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var contentBytes = Encoding.UTF8.GetBytes(content);
var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(type);
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: type);
+ metadata: metadata);
// Act
var result = await formatter.ReadAsync(context);
@@ -107,11 +111,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var contentBytes = Encoding.UTF8.GetBytes(content);
var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(User));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: typeof(User));
+ metadata: metadata);
// Act
var result = await formatter.ReadAsync(context);
@@ -133,11 +139,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(User));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(User));
+ metadata: metadata);
// Act
var result = await formatter.ReadAsync(context);
@@ -149,6 +157,61 @@ namespace Microsoft.AspNet.Mvc.Formatters
modelState["Age"].Errors[0].Exception.Message);
}
+ [Fact]
+ public async Task ReadAsync_InvalidArray_AddsOverflowErrorsToModelState()
+ {
+ // Arrange
+ var content = "[0, 23, 300]";
+ var formatter = new JsonInputFormatter();
+ var contentBytes = Encoding.UTF8.GetBytes(content);
+
+ var modelState = new ModelStateDictionary();
+ var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(byte[]));
+ var context = new InputFormatterContext(
+ httpContext,
+ modelName: string.Empty,
+ modelState: modelState,
+ metadata: metadata);
+
+ // Act
+ var result = await formatter.ReadAsync(context);
+
+ // Assert
+ Assert.True(result.HasError);
+ Assert.Equal("The supplied value is invalid for Byte.", modelState["[2]"].Errors[0].ErrorMessage);
+ Assert.Null(modelState["[2]"].Errors[0].Exception);
+ }
+
+ [Fact]
+ public async Task ReadAsync_InvalidComplexArray_AddsOverflowErrorsToModelState()
+ {
+ // Arrange
+ var content = "[{name: 'Name One', Age: 30}, {name: 'Name Two', Small: 300}]";
+ var formatter = new JsonInputFormatter();
+ var contentBytes = Encoding.UTF8.GetBytes(content);
+
+ var modelState = new ModelStateDictionary();
+ var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(User[]));
+ var context = new InputFormatterContext(
+ httpContext,
+ modelName: "names",
+ modelState: modelState,
+ metadata: metadata);
+
+ // Act
+ var result = await formatter.ReadAsync(context);
+
+ // Assert
+ Assert.True(result.HasError);
+ Assert.Equal(
+ "Error converting value 300 to type 'System.Byte'. Path '[1].Small', line 1, position 59.",
+ modelState["names[1].Small"].Errors[0].Exception.Message);
+ }
+
[Fact]
public async Task ReadAsync_UsesTryAddModelValidationErrorsToModelState()
{
@@ -159,11 +222,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(User));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(User));
+ metadata: metadata);
modelState.MaxAllowedErrors = 3;
modelState.AddModelError("key1", "error1");
@@ -215,11 +280,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, "application/json;charset=utf-8");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(UserLogin));
var inputFormatterContext = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(UserLogin));
+ metadata: metadata);
// Act
var result = await jsonFormatter.ReadAsync(inputFormatterContext);
@@ -248,11 +315,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, "application/json;charset=utf-8");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(UserLogin));
var inputFormatterContext = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(UserLogin));
+ metadata: metadata);
// Act
var result = await jsonFormatter.ReadAsync(inputFormatterContext);
@@ -315,6 +384,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
public string Name { get; set; }
public decimal Age { get; set; }
+
+ public byte Small { get; set; }
}
private sealed class UserLogin
diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonPatchInputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonPatchInputFormatterTest.cs
index 8b40c2059e..86bb77883b 100644
--- a/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonPatchInputFormatterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Formatters.Json.Test/JsonPatchInputFormatterTest.cs
@@ -25,11 +25,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(JsonPatchDocument));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(JsonPatchDocument));
+ metadata: metadata);
// Act
var result = await formatter.ReadAsync(context);
@@ -53,11 +55,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(JsonPatchDocument));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(JsonPatchDocument));
+ metadata: metadata);
// Act
var result = await formatter.ReadAsync(context);
@@ -86,11 +90,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(JsonPatchDocument));
var formatterContext = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(JsonPatchDocument));
+ metadata: metadata);
// Act
var result = formatter.CanRead(formatterContext);
@@ -111,11 +117,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: "application/json-patch+json");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(modelType);
var formatterContext = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: modelType);
+ metadata: metadata);
// Act
var result = formatter.CanRead(formatterContext);
@@ -137,11 +145,13 @@ namespace Microsoft.AspNet.Mvc.Formatters
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: "application/json-patch+json");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(Customer));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(Customer));
+ metadata: metadata);
// Act
var result = await formatter.ReadAsync(context);
diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlDataContractSerializerInputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlDataContractSerializerInputFormatterTest.cs
index b16c0994eb..f4b3e17db3 100644
--- a/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlDataContractSerializerInputFormatterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlDataContractSerializerInputFormatterTest.cs
@@ -73,11 +73,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(string));
var formatterContext = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(string));
+ metadata: metadata);
// Act
var result = formatter.CanRead(formatterContext);
@@ -337,11 +339,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(inputBytes, contentType: "application/xml; charset=utf-16");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(TestLevelOne));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(TestLevelOne));
+ metadata: metadata);
// Act
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
@@ -401,11 +405,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: "application/xml; charset=utf-16");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(TestLevelOne));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(TestLevelOne));
+ metadata: metadata);
// Act
var result = await formatter.ReadAsync(context);
@@ -544,11 +550,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
private InputFormatterContext GetInputFormatterContext(byte[] contentBytes, Type modelType)
{
var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(modelType);
return new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: modelType);
+ metadata: metadata);
}
private static HttpContext GetHttpContext(
diff --git a/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlSerializerInputFormatterTest.cs b/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlSerializerInputFormatterTest.cs
index 5205fc9c73..4a11d84d85 100644
--- a/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlSerializerInputFormatterTest.cs
+++ b/test/Microsoft.AspNet.Mvc.Formatters.Xml.Test/XmlSerializerInputFormatterTest.cs
@@ -59,11 +59,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: requestContentType);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(string));
var formatterContext = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(string));
+ metadata: metadata);
// Act
var result = formatter.CanRead(formatterContext);
@@ -342,11 +344,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(inputBytes, contentType: "application/xml; charset=utf-16");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(TestLevelOne));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(TestLevelOne));
+ metadata: metadata);
// Act and Assert
var ex = await Assert.ThrowsAsync(expectedException, () => formatter.ReadAsync(context));
@@ -403,11 +407,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
var modelState = new ModelStateDictionary();
var httpContext = GetHttpContext(contentBytes, contentType: "application/xml; charset=utf-16");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(typeof(TestLevelOne));
var context = new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: modelState,
- modelType: typeof(TestLevelOne));
+ metadata: metadata);
// Act
var result = await formatter.ReadAsync(context);
@@ -425,11 +431,13 @@ namespace Microsoft.AspNet.Mvc.Formatters.Xml
private InputFormatterContext GetInputFormatterContext(byte[] contentBytes, Type modelType)
{
var httpContext = GetHttpContext(contentBytes);
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForType(modelType);
return new InputFormatterContext(
httpContext,
modelName: string.Empty,
modelState: new ModelStateDictionary(),
- modelType: modelType);
+ metadata: metadata);
}
private static HttpContext GetHttpContext(
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/ModelBindingTest.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/ModelBindingTest.cs
index c2013d3f7d..726275d7b9 100644
--- a/test/Microsoft.AspNet.Mvc.FunctionalTests/ModelBindingTest.cs
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/ModelBindingTest.cs
@@ -1443,7 +1443,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await response.Content.ReadAsStringAsync();
- Assert.Equal("The value 'random string' is not valid for birthdate.", result);
+ Assert.Equal("The value 'random string' is not valid for DateTime.", result);
}
[Fact]
diff --git a/test/Microsoft.AspNet.Mvc.IntegrationTests/SimpleTypeModelBinderIntegrationTest.cs b/test/Microsoft.AspNet.Mvc.IntegrationTests/SimpleTypeModelBinderIntegrationTest.cs
index f647c18fbb..a61b67d16f 100644
--- a/test/Microsoft.AspNet.Mvc.IntegrationTests/SimpleTypeModelBinderIntegrationTest.cs
+++ b/test/Microsoft.AspNet.Mvc.IntegrationTests/SimpleTypeModelBinderIntegrationTest.cs
@@ -244,7 +244,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
var error = Assert.Single(entry.Errors);
Assert.Null(error.Exception);
- Assert.Equal("The value 'abcd' is not valid for Parameter1.", error.ErrorMessage);
+ Assert.Equal("The value 'abcd' is not valid for Int32.", error.ErrorMessage);
}
[Theory]
diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ModelStateDictionaryExtensionsTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ModelStateDictionaryExtensionsTest.cs
index 923286330b..66fcab72c6 100644
--- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ModelStateDictionaryExtensionsTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/ModelStateDictionaryExtensionsTest.cs
@@ -81,11 +81,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public void AddModelError_ForSingleExpression_AddsExpectedException()
{
// Arrange
- var exception = new Exception();
var dictionary = new ModelStateDictionary();
+ var exception = new Exception();
+ var provider = new TestModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(TestModel), nameof(TestModel.Text));
// Act
- dictionary.AddModelError(model => model.Text, exception);
+ dictionary.AddModelError(model => model.Text, exception, metadata);
// Assert
var modelState = Assert.Single(dictionary);
@@ -99,11 +101,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public void AddModelError_ForRelationExpression_AddsExpectedException()
{
// Arrange
- var exception = new Exception();
var dictionary = new ModelStateDictionary();
+ var exception = new Exception();
+ var provider = new TestModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(ChildModel), nameof(ChildModel.Text));
// Act
- dictionary.AddModelError(model => model.Child.Text, exception);
+ dictionary.AddModelError(model => model.Child.Text, exception, metadata);
// Assert
var modelState = Assert.Single(dictionary);
@@ -117,11 +121,13 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public void AddModelError_ForImplicitlyCastedToObjectExpression_AddsExpectedException()
{
// Arrange
- var exception = new Exception();
var dictionary = new ModelStateDictionary();
+ var exception = new Exception();
+ var provider = new TestModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(ChildModel), nameof(ChildModel.Value));
// Act
- dictionary.AddModelError(model => model.Child.Value, exception);
+ dictionary.AddModelError(model => model.Child.Value, exception, metadata);
// Assert
var modelState = Assert.Single(dictionary);
@@ -135,12 +141,14 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
public void AddModelError_ForNotModelsExpression_AddsExpectedException()
{
// Arrange
+ var dictionary = new ModelStateDictionary();
var variable = "Test";
var exception = new Exception();
- var dictionary = new ModelStateDictionary();
+ var provider = new TestModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
// Act
- dictionary.AddModelError(model => variable, exception);
+ dictionary.AddModelError(model => variable, exception, metadata);
// Assert
var modelState = Assert.Single(dictionary);
diff --git a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperValidationSummaryTest.cs b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperValidationSummaryTest.cs
index 5e79d59e70..325bf1914a 100644
--- a/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperValidationSummaryTest.cs
+++ b/test/Microsoft.AspNet.Mvc.ViewFeatures.Test/Rendering/HtmlHelperValidationSummaryTest.cs
@@ -343,23 +343,29 @@ namespace Microsoft.AspNet.Mvc.Rendering
modelState.AddModelError("Property3.OrderedProperty3", "This is an error for Property3.OrderedProperty3.");
modelState.AddModelError("Property3.OrderedProperty2", "This is an error for Property3.OrderedProperty2.");
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(ValidationModel), nameof(ValidationModel.Property3));
modelState.AddModelError("Property3", "This is an error for Property3.");
- modelState.AddModelError("Property3", new InvalidCastException("Exception will be ignored."));
+ modelState.AddModelError("Property3", new InvalidCastException("Exception will be ignored."), metadata);
+ metadata = provider.GetMetadataForProperty(typeof(ValidationModel), nameof(ValidationModel.Property2));
modelState.AddModelError("Property2", "This is an error for Property2.");
modelState.AddModelError("Property2", "This is another error for Property2.");
- modelState.AddModelError("Property2", new OverflowException("Produces invalid value message"));
+ modelState.AddModelError("Property2", new OverflowException("Produces invalid value message"), metadata);
+ metadata = provider.GetMetadataForType(typeof(ValidationModel));
modelState.AddModelError(string.Empty, "This is an error for the model root.");
modelState.AddModelError(string.Empty, "This is another error for the model root.");
- modelState.AddModelError(string.Empty, new InvalidOperationException("Another ignored Exception."));
+ modelState.AddModelError(string.Empty, new InvalidOperationException("Another ignored Exception."), metadata);
}
// Adds one or more errors for all properties in OrderedModel. But adds errors out of order.
private void AddOrderedErrors(ModelStateDictionary modelState)
{
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(OrderedModel), nameof(OrderedModel.Property3));
modelState.AddModelError("Property3", "This is an error for Property3.");
- modelState.AddModelError("Property3", new InvalidCastException("An ignored Exception."));
+ modelState.AddModelError("Property3", new InvalidCastException("An ignored Exception."), metadata);
modelState.AddModelError("Property2", "This is an error for Property2.");
modelState.AddModelError("Property2", "This is another error for Property2.");
diff --git a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/HttpErrorTest.cs b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/HttpErrorTest.cs
index 5d698eddcb..de1acc77a4 100644
--- a/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/HttpErrorTest.cs
+++ b/test/Microsoft.AspNet.Mvc.WebApiCompatShimTest/HttpErrorTest.cs
@@ -66,13 +66,19 @@ namespace System.Web.Http.Dispatcher
[Fact]
public void ModelStateConstructorWithDetail_AddsCorrectDictionaryItems()
{
+ // Arrange
ModelStateDictionary modelState = new ModelStateDictionary();
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
modelState.AddModelError("[0].Name", "error1");
modelState.AddModelError("[0].Name", "error2");
modelState.AddModelError("[0].Address", "error");
- modelState.AddModelError("[2].Name", new Exception("OH NO"));
+ modelState.AddModelError("[2].Name", new Exception("OH NO"), metadata);
+ // Act
HttpError error = new HttpError(modelState, true);
+
+ // Assert
HttpError modelStateError = error["ModelState"] as HttpError;
Assert.Contains(new KeyValuePair("Message", "The request is invalid."), error);
@@ -98,13 +104,19 @@ namespace System.Web.Http.Dispatcher
[Fact]
public void ModelStateConstructorWithoutDetail_AddsCorrectDictionaryItems()
{
+ // Arrange
ModelStateDictionary modelState = new ModelStateDictionary();
+ var provider = new EmptyModelMetadataProvider();
+ var metadata = provider.GetMetadataForProperty(typeof(string), nameof(string.Length));
modelState.AddModelError("[0].Name", "error1");
modelState.AddModelError("[0].Name", "error2");
modelState.AddModelError("[0].Address", "error");
- modelState.AddModelError("[2].Name", new Exception("OH NO"));
+ modelState.AddModelError("[2].Name", new Exception("OH NO"), metadata);
+ // Act
HttpError error = new HttpError(modelState, false);
+
+ // Assert
HttpError modelStateError = error["ModelState"] as HttpError;
Assert.Contains(new KeyValuePair("Message", "The request is invalid."), error);
diff --git a/test/WebSites/XmlFormattersWebSite/Controllers/SerializableErrorController.cs b/test/WebSites/XmlFormattersWebSite/Controllers/SerializableErrorController.cs
index d569271517..5a90992907 100644
--- a/test/WebSites/XmlFormattersWebSite/Controllers/SerializableErrorController.cs
+++ b/test/WebSites/XmlFormattersWebSite/Controllers/SerializableErrorController.cs
@@ -24,7 +24,7 @@ namespace XmlFormattersWebSite.Controllers
}
ModelState.AddModelError("key1", "key1-error");
- ModelState.AddModelError("key2", exception);
+ ModelState.AddModelError("key2", exception, ViewData.ModelMetadata);
return new ObjectResult(new SerializableError(ModelState));
}