[Partial fix for #1372]Added SimpleTypesExcludeFilter to exlcude validation on simple types and also added tests to cover scenarios.
This commit is contained in:
parent
d788e87a94
commit
00b61ec1e6
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a descriptor to the specified <paramref name="excludeBodyValidationDescriptorCollection" />
|
||||
/// that excludes the properties of the <see cref="Type"/> specified and it's derived types from validaton.
|
||||
/// Adds a descriptor to the specified <paramref name="descriptorCollection" /> that excludes the properties of
|
||||
/// the <see cref="Type"/> specified and its derived types from validaton.
|
||||
/// </summary>
|
||||
/// <param name="excludeBodyValidationDescriptorCollection">A list of <see cref="ExcludeValidationDescriptor"/>
|
||||
/// which are used to get a collection of exclude filters to be applied for filtering model properties during validation.
|
||||
/// <param name="descriptorCollection">A list of <see cref="ExcludeValidationDescriptor"/> which are used to
|
||||
/// get a collection of exclude filters to be applied for filtering model properties during validation.
|
||||
/// </param>
|
||||
/// <param name="type"><see cref="Type"/> which should be excluded from validation.</param>
|
||||
public static void Add(this IList<ExcludeValidationDescriptor> excludeBodyValidationDescriptorCollection,
|
||||
Type type)
|
||||
public static void Add(this IList<ExcludeValidationDescriptor> descriptorCollection, Type type)
|
||||
{
|
||||
var typeBasedExcludeFilter = new DefaultTypeBasedExcludeFilter(type);
|
||||
excludeBodyValidationDescriptorCollection.Add(new ExcludeValidationDescriptor(typeBasedExcludeFilter));
|
||||
descriptorCollection.Add(new ExcludeValidationDescriptor(typeBasedExcludeFilter));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a descriptor to the specified <paramref name="excludeBodyValidationDescriptorCollection" />
|
||||
/// that excludes the properties of the type specified and it's derived types from validaton.
|
||||
/// Adds a descriptor to the specified <paramref name="descriptorCollection" /> that excludes the properties of
|
||||
/// the type specified and its derived types from validaton.
|
||||
/// </summary>
|
||||
/// <param name="excludeBodyValidationDescriptorCollection">A list of <see cref="ExcludeValidationDescriptor"/>
|
||||
/// which are used to get a collection of exclude filters to be applied for filtering model properties during validation.
|
||||
/// <param name="descriptorCollection">A list of <see cref="ExcludeValidationDescriptor"/> which are used to
|
||||
/// get a collection of exclude filters to be applied for filtering model properties during validation.
|
||||
/// </param>
|
||||
/// <param name="typeFullName">Full name of the type which should be excluded from validation.</param>
|
||||
public static void Add(this IList<ExcludeValidationDescriptor> excludeBodyValidationDescriptorCollection,
|
||||
string typeFullName)
|
||||
public static void Add(this IList<ExcludeValidationDescriptor> descriptorCollection, string typeFullName)
|
||||
{
|
||||
var filter = new DefaultTypeNameBasedExcludeFilter(typeFullName);
|
||||
excludeBodyValidationDescriptorCollection.Add(new ExcludeValidationDescriptor(filter));
|
||||
descriptorCollection.Add(new ExcludeValidationDescriptor(filter));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a descriptor to the specified <paramref name="descriptorCollection" /> that excludes the properties of
|
||||
/// the type specified and its derived types from validaton.
|
||||
/// </summary>
|
||||
/// <param name="descriptorCollection">A list of <see cref="ExcludeValidationDescriptor"/> which are used to
|
||||
/// get a collection of exclude filters to be applied for filtering model properties during validation.
|
||||
/// </param>
|
||||
/// <param name="filter"><see cref="IExcludeTypeValidationFilter"/> which should be excluded from validation.
|
||||
/// </param>
|
||||
public static void Add(this IList<ExcludeValidationDescriptor> descriptorCollection,
|
||||
IExcludeTypeValidationFilter filter)
|
||||
{
|
||||
descriptorCollection.Add(new ExcludeValidationDescriptor(filter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
/// <summary>
|
||||
/// Identifies the simple types that the default model binding validation will exclude.
|
||||
/// </summary>
|
||||
public class SimpleTypesExcludeFilter : IExcludeTypeValidationFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns true if the given type will be excluded from the default model validation.
|
||||
/// </summary>
|
||||
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<KeyValuePair<K,V>>,
|
||||
// supertype of IDictionary<K,V>, and IReadOnlyDictionary<K,V>.
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the given type is the underlying types that <see cref="IsTypeExcluded"/> will exclude.
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<IApplicationBuilder> _app = new FormatterWebSite.Startup().Configure;
|
||||
|
||||
// Parameters: Request Content, Expected status code, Expected model state error message
|
||||
public static IEnumerable<object[]> SimpleTypePropertiesModelRequestData
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new object[] {
|
||||
"{\"ByteProperty\":1, \"NullableByteProperty\":5, \"ByteArrayProperty\":[1,2,3]}",
|
||||
400,
|
||||
"The field ByteProperty must be between 2 and 8."};
|
||||
|
||||
yield return new object[] {
|
||||
"{\"ByteProperty\":8, \"NullableByteProperty\":1, \"ByteArrayProperty\":[1,2,3]}",
|
||||
400,
|
||||
"The field NullableByteProperty must be between 2 and 8."};
|
||||
|
||||
yield return new object[] {
|
||||
"{\"ByteProperty\":8, \"NullableByteProperty\":2, \"ByteArrayProperty\":[1]}",
|
||||
400,
|
||||
"The field ByteArrayProperty must be a string or array type with a minimum length of '2'."};
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckIfObjectIsDeserializedWithoutErrors()
|
||||
{
|
||||
|
|
@ -84,9 +109,64 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
|
||||
//Assert
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("No model validation for developer, even though developer.Name is empty.", await response.Content.ReadAsStringAsync());
|
||||
Assert.Equal("No model validation for developer, even though developer.Name is empty.",
|
||||
await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ShallowValidation_HappensOnExcluded_ComplexTypeProperties()
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
var requestData = "{\"Name\":\"Library Manager\", \"Suppliers\": [{\"Name\":\"Contoso Corp\"}]}";
|
||||
var content = new StringContent(requestData, Encoding.UTF8, "application/json");
|
||||
var expectedModelStateErrorMessage
|
||||
= "The field Suppliers must be a string or array type with a minimum length of '2'.";
|
||||
var shouldNotContainMessage
|
||||
= "The field Name must be a string or array type with a maximum length of '5'.";
|
||||
|
||||
// Act
|
||||
var response = await client.PostAsync("http://localhost/Validation/CreateProject", content);
|
||||
|
||||
//Assert
|
||||
Assert.Equal(400, (int)response.StatusCode);
|
||||
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var responseObject = JsonConvert.DeserializeObject<Dictionary<string, ErrorCollection>>(responseContent);
|
||||
var errorCollection = Assert.Single(responseObject);
|
||||
var error = Assert.Single(errorCollection.Value.Errors);
|
||||
Assert.Equal(expectedModelStateErrorMessage, error.ErrorMessage);
|
||||
|
||||
// verifies that the excluded type is not validated
|
||||
Assert.NotEqual(shouldNotContainMessage, error.ErrorMessage);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(SimpleTypePropertiesModelRequestData))]
|
||||
public async Task ShallowValidation_HappensOnExlcuded_SimpleTypeProperties(
|
||||
string requestContent,
|
||||
int expectedStatusCode,
|
||||
string expectedModelStateErrorMessage)
|
||||
{
|
||||
// Arrange
|
||||
var server = TestServer.Create(_services, _app);
|
||||
var client = server.CreateClient();
|
||||
var content = new StringContent(requestContent, Encoding.UTF8, "application/json");
|
||||
|
||||
// Act
|
||||
var response = await client.PostAsync("http://localhost/Validation/CreateSimpleTypePropertiesModel",
|
||||
content);
|
||||
|
||||
//Assert
|
||||
Assert.Equal(expectedStatusCode, (int)response.StatusCode);
|
||||
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var responseObject = JsonConvert.DeserializeObject<Dictionary<string, ErrorCollection>>(responseContent);
|
||||
var errorCollection = Assert.Single(responseObject);
|
||||
var error = Assert.Single(errorCollection.Value.Errors);
|
||||
Assert.Equal(expectedModelStateErrorMessage, error.ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CheckIfExcludedField_IsValidatedForNonBodyBoundModels()
|
||||
|
|
@ -103,5 +183,23 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
|||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
Assert.Equal("The Name field is required.", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
|
||||
private class ErrorCollection
|
||||
{
|
||||
public IEnumerable<Error> Errors
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
private class Error
|
||||
{
|
||||
public string ErrorMessage
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// 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 Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding.Test
|
||||
{
|
||||
public class SimpleTypeExcluceFilterTest
|
||||
{
|
||||
[Theory]
|
||||
[MemberData(nameof(ExcludedTypes))]
|
||||
public void SimpleTypeExcluceFilter_ExcludedTypes(Type type)
|
||||
{
|
||||
// Arrange
|
||||
var filter = new SimpleTypesExcludeFilter();
|
||||
|
||||
// Act & Assert
|
||||
Assert.True(filter.IsTypeExcluded(type));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(IncludedTypes))]
|
||||
public void SimpleTypeExcluceFilter_IncludedTypes(Type type)
|
||||
{
|
||||
// Arrange
|
||||
var filter = new SimpleTypesExcludeFilter();
|
||||
|
||||
// Act & Assert
|
||||
Assert.False(filter.IsTypeExcluded(type));
|
||||
}
|
||||
|
||||
private class TestType
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static TheoryData<Type> ExcludedTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<Type>()
|
||||
{
|
||||
// Simple types
|
||||
typeof(int[]),
|
||||
typeof(int),
|
||||
typeof(List<decimal>),
|
||||
typeof(SortedSet<int>),
|
||||
|
||||
// Nullable types
|
||||
typeof(ICollection<string>),
|
||||
typeof(int?[]),
|
||||
typeof(SortedSet<int?>),
|
||||
typeof(HashSet<Uri>),
|
||||
typeof(HashSet<string>),
|
||||
|
||||
// Value types
|
||||
typeof(IList<DateTime>),
|
||||
|
||||
// KeyValue types
|
||||
typeof(Dictionary<int, string>),
|
||||
typeof(IReadOnlyDictionary<int?, char>)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static TheoryData<Type> IncludedTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
return new TheoryData<Type>()
|
||||
{
|
||||
typeof(TestType),
|
||||
typeof(TestType[]),
|
||||
typeof(SortedSet<TestType>),
|
||||
typeof(Dictionary<int, TestType>),
|
||||
typeof(Dictionary<TestType, int>),
|
||||
typeof(Dictionary<TestType, TestType>)
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -133,21 +133,26 @@ namespace Microsoft.AspNet.Mvc
|
|||
Assert.Equal(5, mvcOptions.ValidationExcludeFilters.Count);
|
||||
|
||||
// Verify if the delegates registered by default exclude the given types.
|
||||
Assert.Equal(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[0].OptionType);
|
||||
var instance = Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[0].Instance);
|
||||
Assert.Equal(instance.ExcludedType, typeof(XObject));
|
||||
Assert.Equal(typeof(SimpleTypesExcludeFilter), mvcOptions.ValidationExcludeFilters[0].OptionType);
|
||||
Assert.Equal(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[1].OptionType);
|
||||
var instance2 = Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[1].Instance);
|
||||
Assert.Equal(instance2.ExcludedType, typeof(Type));
|
||||
var xObjectFilter
|
||||
= Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[1].Instance);
|
||||
Assert.Equal(xObjectFilter.ExcludedType, typeof(XObject));
|
||||
|
||||
Assert.Equal(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[2].OptionType);
|
||||
var instance3 = Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[2].Instance);
|
||||
Assert.Equal(instance3.ExcludedType, typeof(byte[]));
|
||||
var typeFilter =
|
||||
Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[2].Instance);
|
||||
Assert.Equal(typeFilter.ExcludedType, typeof(Type));
|
||||
|
||||
Assert.Equal(typeof(DefaultTypeBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[3].OptionType);
|
||||
var instance4 = Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[3].Instance);
|
||||
Assert.Equal(instance4.ExcludedType, typeof(JToken));
|
||||
var jTokenFilter
|
||||
= Assert.IsType<DefaultTypeBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[3].Instance);
|
||||
Assert.Equal(jTokenFilter.ExcludedType, typeof(JToken));
|
||||
|
||||
Assert.Equal(typeof(DefaultTypeNameBasedExcludeFilter), mvcOptions.ValidationExcludeFilters[4].OptionType);
|
||||
var instance5 = Assert.IsType<DefaultTypeNameBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[4].Instance);
|
||||
Assert.Equal(instance5.ExcludedTypeName, "System.Xml.XmlNode");
|
||||
var xmlNodeFilter =
|
||||
Assert.IsType<DefaultTypeNameBasedExcludeFilter>(mvcOptions.ValidationExcludeFilters[4].Instance);
|
||||
Assert.Equal(xmlNodeFilter.ExcludedTypeName, "System.Xml.XmlNode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
// 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.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace FormatterWebSite
|
||||
{
|
||||
public class CustomObjectResult : ObjectResult
|
||||
{
|
||||
public CustomObjectResult(object value, int statusCode) : base(value)
|
||||
{
|
||||
StatusCode = statusCode;
|
||||
}
|
||||
|
||||
public int StatusCode { get; private set; }
|
||||
|
||||
public override Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
context.HttpContext.Response.StatusCode = StatusCode;
|
||||
|
||||
return base.ExecuteResultAsync(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,8 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace FormatterWebSite
|
||||
|
|
@ -54,5 +56,19 @@ namespace FormatterWebSite
|
|||
return ModelState["Name"].Errors[0].ErrorMessage;
|
||||
}
|
||||
}
|
||||
|
||||
// 'Developer' type is excluded but the shallow validation on the
|
||||
// property Developers should happen
|
||||
[ModelStateValidationFilter]
|
||||
public IActionResult CreateProject([FromBody]Project project)
|
||||
{
|
||||
return Json(project);
|
||||
}
|
||||
|
||||
[ModelStateValidationFilter]
|
||||
public IActionResult CreateSimpleTypePropertiesModel([FromBody] SimpleTypePropertiesModel simpleTypePropertiesModel)
|
||||
{
|
||||
return Json(simpleTypePropertiesModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// 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 Microsoft.AspNet.Mvc;
|
||||
|
||||
namespace FormatterWebSite
|
||||
{
|
||||
public class ModelStateValidationFilterAttribute : ActionFilterAttribute
|
||||
{
|
||||
public override void OnActionExecuting(ActionExecutingContext context)
|
||||
{
|
||||
if (!context.ModelState.IsValid)
|
||||
{
|
||||
context.Result = new CustomObjectResult(context.ModelState, 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace FormatterWebSite
|
||||
{
|
||||
public class Project
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
[MinLength(2)]
|
||||
[MaxLength(5)]
|
||||
public Supplier[] Suppliers { get; set; }
|
||||
}
|
||||
|
||||
public class Supplier
|
||||
{
|
||||
public int Id { get; set; }
|
||||
|
||||
[MaxLength(5)]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace FormatterWebSite
|
||||
{
|
||||
public class SimpleTypePropertiesModel
|
||||
{
|
||||
[Range(2, 8)]
|
||||
public byte ByteProperty { get; set; }
|
||||
|
||||
[Range(2, 8)]
|
||||
public byte? NullableByteProperty { get; set; }
|
||||
|
||||
[MinLength(2)]
|
||||
public byte[] ByteArrayProperty { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,6 +23,7 @@ namespace FormatterWebSite
|
|||
services.Configure<MvcOptions>(options =>
|
||||
{
|
||||
options.ValidationExcludeFilters.Add(typeof(Developer));
|
||||
options.ValidationExcludeFilters.Add(typeof(Supplier));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue