diff --git a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/ValidationExcludeFiltersExtensions.cs b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/ValidationExcludeFiltersExtensions.cs
index ff644186ea..09d346918c 100644
--- a/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/ValidationExcludeFiltersExtensions.cs
+++ b/src/Microsoft.AspNet.Mvc.Core/OptionDescriptors/ValidationExcludeFiltersExtensions.cs
@@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
+using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.OptionDescriptors;
namespace Microsoft.AspNet.Mvc
@@ -13,33 +14,46 @@ namespace Microsoft.AspNet.Mvc
public static class ValidationExcludeFiltersExtensions
{
///
- /// Adds a descriptor to the specified
- /// that excludes the properties of the specified and it's derived types from validaton.
+ /// Adds a descriptor to the specified that excludes the properties of
+ /// the specified and its derived types from validaton.
///
- /// A list of
- /// which are used to get a collection of exclude filters to be applied for filtering model properties during validation.
+ /// A list of which are used to
+ /// get a collection of exclude filters to be applied for filtering model properties during validation.
///
/// which should be excluded from validation.
- public static void Add(this IList excludeBodyValidationDescriptorCollection,
- Type type)
+ public static void Add(this IList descriptorCollection, Type type)
{
var typeBasedExcludeFilter = new DefaultTypeBasedExcludeFilter(type);
- excludeBodyValidationDescriptorCollection.Add(new ExcludeValidationDescriptor(typeBasedExcludeFilter));
+ descriptorCollection.Add(new ExcludeValidationDescriptor(typeBasedExcludeFilter));
}
///
- /// Adds a descriptor to the specified
- /// that excludes the properties of the type specified and it's derived types from validaton.
+ /// Adds a descriptor to the specified that excludes the properties of
+ /// the type specified and its derived types from validaton.
///
- /// A list of
- /// which are used to get a collection of exclude filters to be applied for filtering model properties during validation.
+ /// A list of which are used to
+ /// get a collection of exclude filters to be applied for filtering model properties during validation.
///
/// Full name of the type which should be excluded from validation.
- public static void Add(this IList excludeBodyValidationDescriptorCollection,
- string typeFullName)
+ public static void Add(this IList descriptorCollection, string typeFullName)
{
var filter = new DefaultTypeNameBasedExcludeFilter(typeFullName);
- excludeBodyValidationDescriptorCollection.Add(new ExcludeValidationDescriptor(filter));
+ descriptorCollection.Add(new ExcludeValidationDescriptor(filter));
+ }
+
+ ///
+ /// Adds a descriptor to the specified that excludes the properties of
+ /// the type specified and its derived types from validaton.
+ ///
+ /// A list of which are used to
+ /// get a collection of exclude filters to be applied for filtering model properties during validation.
+ ///
+ /// which should be excluded from validation.
+ ///
+ public static void Add(this IList descriptorCollection,
+ IExcludeTypeValidationFilter filter)
+ {
+ descriptorCollection.Add(new ExcludeValidationDescriptor(filter));
}
}
}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/SimpleTypesExcludeFilter.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/SimpleTypesExcludeFilter.cs
new file mode 100644
index 0000000000..85316acd77
--- /dev/null
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/SimpleTypesExcludeFilter.cs
@@ -0,0 +1,70 @@
+// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+
+namespace Microsoft.AspNet.Mvc.ModelBinding
+{
+ ///
+ /// Identifies the simple types that the default model binding validation will exclude.
+ ///
+ public class SimpleTypesExcludeFilter : IExcludeTypeValidationFilter
+ {
+ ///
+ /// Returns true if the given type will be excluded from the default model validation.
+ ///
+ public bool IsTypeExcluded(Type type)
+ {
+ Type[] actualTypes;
+
+ var enumerable = type.ExtractGenericInterface(typeof(IEnumerable<>));
+ if (enumerable == null)
+ {
+ actualTypes = new Type[] { type };
+ }
+ else
+ {
+ actualTypes = enumerable.GenericTypeArguments;
+ // The following special case is for IEnumerable>,
+ // supertype of IDictionary, and IReadOnlyDictionary.
+ if (actualTypes.Length == 1
+ && actualTypes[0].IsGenericType()
+ && actualTypes[0].GetGenericTypeDefinition() == typeof(KeyValuePair<,>))
+ {
+ actualTypes = actualTypes[0].GenericTypeArguments;
+ }
+ }
+
+ foreach (var actualType in actualTypes)
+ {
+ var underlyingType = Nullable.GetUnderlyingType(actualType) ?? actualType;
+
+ if (!IsSimpleType(underlyingType))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ ///
+ /// Returns true if the given type is the underlying types that will exclude.
+ ///
+ protected virtual bool IsSimpleType(Type type)
+ {
+ var result = type.GetTypeInfo().IsPrimitive ||
+ type.Equals(typeof(decimal)) ||
+ type.Equals(typeof(string)) ||
+ type.Equals(typeof(DateTime)) ||
+ type.Equals(typeof(Guid)) ||
+ type.Equals(typeof(DateTimeOffset)) ||
+ type.Equals(typeof(TimeSpan)) ||
+ type.Equals(typeof(Uri));
+
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Microsoft.AspNet.Mvc.ModelBinding/Validation/DefaultBodyModelValidator.cs b/src/Microsoft.AspNet.Mvc.ModelBinding/Validation/DefaultBodyModelValidator.cs
index d9ae190cab..ca3a9a7f0c 100644
--- a/src/Microsoft.AspNet.Mvc.ModelBinding/Validation/DefaultBodyModelValidator.cs
+++ b/src/Microsoft.AspNet.Mvc.ModelBinding/Validation/DefaultBodyModelValidator.cs
@@ -56,9 +56,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding
// We don't need to recursively traverse the graph for types that shouldn't be validated
var modelType = metadata.Model.GetType();
- if (TypeHelper.IsSimpleType(modelType) ||
- IsTypeExcludedFromValidation(
- validationContext.ModelValidationContext.ExcludeFromValidationFilters, modelType))
+ if (IsTypeExcludedFromValidation(validationContext.ModelValidationContext.ExcludeFromValidationFilters, modelType))
{
return ShallowValidate(metadata, validationContext, validators);
}
diff --git a/src/Microsoft.AspNet.Mvc/MvcOptionsSetup.cs b/src/Microsoft.AspNet.Mvc/MvcOptionsSetup.cs
index 9f9e0da1ee..2be43e3715 100644
--- a/src/Microsoft.AspNet.Mvc/MvcOptionsSetup.cs
+++ b/src/Microsoft.AspNet.Mvc/MvcOptionsSetup.cs
@@ -58,9 +58,9 @@ namespace Microsoft.AspNet.Mvc
options.ModelValidatorProviders.Add(new DataMemberModelValidatorProvider());
// Add types to be excluded from Validation
+ options.ValidationExcludeFilters.Add(new SimpleTypesExcludeFilter());
options.ValidationExcludeFilters.Add(typeof(XObject));
options.ValidationExcludeFilters.Add(typeof(Type));
- options.ValidationExcludeFilters.Add(typeof(byte[]));
options.ValidationExcludeFilters.Add(typeof(JToken));
options.ValidationExcludeFilters.Add(typeFullName: "System.Xml.XmlNode");
}
diff --git a/test/Microsoft.AspNet.Mvc.FunctionalTests/InputObjectValidationTests.cs b/test/Microsoft.AspNet.Mvc.FunctionalTests/InputObjectValidationTests.cs
index 2291ba9081..600f899cd8 100644
--- a/test/Microsoft.AspNet.Mvc.FunctionalTests/InputObjectValidationTests.cs
+++ b/test/Microsoft.AspNet.Mvc.FunctionalTests/InputObjectValidationTests.cs
@@ -2,12 +2,15 @@
// 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.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.TestHost;
+using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests
@@ -17,6 +20,28 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
private readonly IServiceProvider _services = TestHelper.CreateServices("FormatterWebSite");
private readonly Action _app = new FormatterWebSite.Startup().Configure;
+ // Parameters: Request Content, Expected status code, Expected model state error message
+ public static IEnumerable