parent
0d603a38cf
commit
d912f6cd39
|
|
@ -1,60 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public class CompositeModelValidator : IModelValidator
|
||||
{
|
||||
private readonly IEnumerable<IModelValidator> _validators;
|
||||
|
||||
public CompositeModelValidator(IEnumerable<IModelValidator> validators)
|
||||
{
|
||||
_validators = validators;
|
||||
}
|
||||
|
||||
public bool IsRequired
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
|
||||
{
|
||||
var propertiesValid = true;
|
||||
var metadata = context.ModelMetadata;
|
||||
|
||||
foreach (var propertyMetadata in metadata.Properties)
|
||||
{
|
||||
var propertyContext = new ModelValidationContext(context, propertyMetadata);
|
||||
|
||||
foreach (var propertyValidator in _validators)
|
||||
{
|
||||
foreach (var validationResult in propertyValidator.Validate(propertyContext))
|
||||
{
|
||||
propertiesValid = false;
|
||||
yield return CreateSubPropertyResult(propertyMetadata, validationResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (propertiesValid)
|
||||
{
|
||||
foreach (var typeValidator in _validators)
|
||||
{
|
||||
foreach (var typeResult in typeValidator.Validate(context))
|
||||
{
|
||||
yield return typeResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ModelValidationResult CreateSubPropertyResult(ModelMetadata propertyMetadata,
|
||||
ModelValidationResult propertyResult)
|
||||
{
|
||||
return new ModelValidationResult(propertyMetadata.PropertyName + '.' + propertyResult.MemberName,
|
||||
propertyResult.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="IModelValidator"/> to represent an error. This validator will always throw an exception regardless
|
||||
/// of the actual model value.
|
||||
/// This is used to perform meta-validation - that is to verify the validation attributes make sense.
|
||||
/// </summary>
|
||||
public class ErrorModelValidator : IModelValidator
|
||||
{
|
||||
private readonly string _errorMessage;
|
||||
|
||||
public ErrorModelValidator([NotNull] string errorMessage)
|
||||
{
|
||||
_errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public bool IsRequired
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public IEnumerable<ModelValidationResult> Validate(ModelValidationContext context)
|
||||
{
|
||||
throw new InvalidOperationException(_errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
// 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.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public class InvalidModelValidatorProvider : AssociatedValidatorProvider
|
||||
{
|
||||
protected override IEnumerable<IModelValidator> GetValidators(ModelMetadata metadata,
|
||||
IEnumerable<Attribute> attributes)
|
||||
{
|
||||
if (metadata.ContainerType == null || string.IsNullOrEmpty(metadata.PropertyName))
|
||||
{
|
||||
// Validate that the type's fields and nonpublic properties don't have any validation attributes on
|
||||
// them. Validation only runs against public properties
|
||||
var type = metadata.ModelType;
|
||||
var nonPublicProperties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
foreach (var nonPublicProperty in nonPublicProperties)
|
||||
{
|
||||
if (nonPublicProperty.GetCustomAttributes(typeof(ValidationAttribute), inherit: true).Any())
|
||||
{
|
||||
var message = Resources.FormatValidationAttributeOnNonPublicProperty(nonPublicProperty.Name,
|
||||
type);
|
||||
yield return new ErrorModelValidator(message);
|
||||
}
|
||||
}
|
||||
|
||||
var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
var allFields = metadata.ModelType.GetFields(bindingFlags);
|
||||
foreach (var field in allFields)
|
||||
{
|
||||
if (field.GetCustomAttributes(typeof(ValidationAttribute), inherit: true).Any())
|
||||
{
|
||||
var message = Resources.FormatValidationAttributeOnField(field.Name, type);
|
||||
yield return new ErrorModelValidator(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Validate that value-typed properties marked as [Required] are also marked as
|
||||
// [DataMember(IsRequired=true)]. Certain formatters may not recognize a member as required if it's
|
||||
// marked as [Required] but not [DataMember(IsRequired=true)]. This is not a problem for reference
|
||||
// types because [Required] will still cause a model error to be raised after a null value is
|
||||
// deserialized.
|
||||
if (metadata.ModelType.GetTypeInfo().IsValueType &&
|
||||
attributes.Any(attribute => attribute is RequiredAttribute))
|
||||
{
|
||||
if (!DataMemberModelValidatorProvider.IsRequiredDataMember(metadata.ContainerType, attributes))
|
||||
{
|
||||
var message = Resources.FormatMissingDataMemberIsRequired(metadata.PropertyName,
|
||||
metadata.ContainerType);
|
||||
yield return new ErrorModelValidator(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
// 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 Microsoft.AspNet.Mvc.Razor.Host;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Razor
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents information about an injected property.
|
||||
/// </summary>
|
||||
public class InjectDescriptor
|
||||
{
|
||||
public InjectDescriptor(string typeName, string memberName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(typeName))
|
||||
{
|
||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpy, "typeName");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(memberName))
|
||||
{
|
||||
throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpy, "memberName");
|
||||
}
|
||||
|
||||
TypeName = typeName;
|
||||
MemberName = memberName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type name of the injected property
|
||||
/// </summary>
|
||||
public string TypeName { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the injected property.
|
||||
/// </summary>
|
||||
public string MemberName { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// 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 Microsoft.AspNet.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public class ErrorModelValidatorTest
|
||||
{
|
||||
private readonly DataAnnotationsModelMetadataProvider _metadataProvider = new DataAnnotationsModelMetadataProvider();
|
||||
|
||||
[Fact]
|
||||
public void ValidateThrowsException()
|
||||
{
|
||||
// Arrange
|
||||
var validator = new ErrorModelValidator("error");
|
||||
|
||||
// Act and Assert
|
||||
ExceptionAssert.Throws<InvalidOperationException>(() => validator.Validate(null), "error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
// 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.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ModelBinding
|
||||
{
|
||||
public class InvalidModelValidatorProviderTest
|
||||
{
|
||||
private static DataAnnotationsModelMetadataProvider _metadataProvider = new DataAnnotationsModelMetadataProvider();
|
||||
|
||||
[Fact]
|
||||
public void GetValidatorsReturnsNothingForValidModel()
|
||||
{
|
||||
// Arrange
|
||||
var validatorProvider = new InvalidModelValidatorProvider();
|
||||
|
||||
// Act
|
||||
var validators = validatorProvider.GetValidators(_metadataProvider.GetMetadataForType(null, typeof(ValidModel)));
|
||||
|
||||
// Assert
|
||||
Assert.Empty(validators);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetValidatorsReturnsInvalidModelValidatorsForInvalidModelType()
|
||||
{
|
||||
// Arrange
|
||||
var name = typeof(InvalidModel).FullName;
|
||||
var validatorProvider = new InvalidModelValidatorProvider();
|
||||
|
||||
// Act
|
||||
var validators = validatorProvider.GetValidators(_metadataProvider.GetMetadataForType(null, typeof(InvalidModel)));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, validators.Count());
|
||||
ExceptionAssert.Throws<InvalidOperationException>(() => validators.ElementAt(0).Validate(null),
|
||||
"Non-public property 'Internal' on type '" + name + "' is attributed with one or more validation attributes. Validation attributes on non-public properties are not supported. Consider using a public property for validation instead.");
|
||||
ExceptionAssert.Throws<InvalidOperationException>(() => validators.ElementAt(1).Validate(null),
|
||||
"Field 'Field' on type '" + name + "' is attributed with one or more validation attributes. Validation attributes on fields are not supported. Consider using a public property for validation instead.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetValidatorsReturnsInvalidModelValidatorsForInvalidModelProperty()
|
||||
{
|
||||
// Arrange
|
||||
var name = typeof(InvalidModel).FullName;
|
||||
var validatorProvider = new InvalidModelValidatorProvider();
|
||||
|
||||
// Act
|
||||
var validators = validatorProvider.GetValidators(_metadataProvider.GetMetadataForProperty(null, typeof(InvalidModel), "Value"));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, validators.Count());
|
||||
ExceptionAssert.Throws<InvalidOperationException>(() => validators.First().Validate(null),
|
||||
"Property 'Value' on type '" + name + "' is invalid. Value-typed properties marked as [Required] must also be marked with [DataMember(IsRequired=true)] to be recognized as required. Consider attributing the declaring type with [DataContract] and the property with [DataMember(IsRequired=true)].");
|
||||
}
|
||||
|
||||
[DataContract]
|
||||
public class ValidModel
|
||||
{
|
||||
[Required]
|
||||
[DataMember]
|
||||
[StringLength(10)]
|
||||
public string Ref { get; set; }
|
||||
|
||||
[DataMember]
|
||||
internal string Internal { get; set; }
|
||||
|
||||
[Required]
|
||||
[DataMember(IsRequired = true)]
|
||||
public int Value { get; set; }
|
||||
|
||||
public string Field;
|
||||
}
|
||||
|
||||
public class InvalidModel
|
||||
{
|
||||
[Required]
|
||||
public string Ref { get; set; }
|
||||
|
||||
[StringLength(10)]
|
||||
[RegularExpression("pattern")]
|
||||
internal string Internal { get; set; }
|
||||
|
||||
[Required]
|
||||
public int Value { get; set; }
|
||||
|
||||
[StringLength(10)]
|
||||
public string Field;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue