mirror of https://github.com/abpframework/abp.git
46 changed files with 546 additions and 390 deletions
@ -1,55 +0,0 @@ |
|||||
using System; |
|
||||
using System.ComponentModel.DataAnnotations; |
|
||||
using System.Linq; |
|
||||
using FluentValidation; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
using Volo.Abp.Validation; |
|
||||
|
|
||||
namespace Volo.Abp.FluentValidation |
|
||||
{ |
|
||||
public class FluentMethodInvocationValidator : IMethodInvocationValidator, ITransientDependency |
|
||||
{ |
|
||||
private readonly IServiceProvider _serviceProvider; |
|
||||
|
|
||||
public FluentMethodInvocationValidator( |
|
||||
IServiceProvider serviceProvider) |
|
||||
{ |
|
||||
_serviceProvider = serviceProvider; |
|
||||
} |
|
||||
|
|
||||
public void Validate(MethodInvocationValidationContext context) |
|
||||
{ |
|
||||
var validationResult = new AbpValidationResult(); |
|
||||
|
|
||||
foreach (var parameterValue in context.ParameterValues) |
|
||||
{ |
|
||||
var serviceType = typeof(IValidator<>).MakeGenericType(parameterValue.GetType()); |
|
||||
var validator = _serviceProvider.GetService(serviceType) as IValidator; |
|
||||
if (validator == null) |
|
||||
{ |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
var result = validator.Validate(parameterValue); |
|
||||
if (!result.IsValid) |
|
||||
{ |
|
||||
validationResult.Errors.AddRange( |
|
||||
result.Errors.Select( |
|
||||
error => |
|
||||
new ValidationResult(error.ErrorMessage) |
|
||||
) |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (validationResult.Errors.Any()) |
|
||||
{ |
|
||||
//TODO: How to localize messages?
|
|
||||
throw new AbpValidationException( |
|
||||
"Method arguments are not valid! See ValidationErrors for details.", |
|
||||
context.Errors |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,41 @@ |
|||||
|
using FluentValidation; |
||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Validation; |
||||
|
|
||||
|
namespace Volo.Abp.FluentValidation |
||||
|
{ |
||||
|
public class FluentObjectValidationContributor : IObjectValidationContributor, ITransientDependency |
||||
|
{ |
||||
|
private readonly IServiceProvider _serviceProvider; |
||||
|
|
||||
|
public FluentObjectValidationContributor( |
||||
|
IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
_serviceProvider = serviceProvider; |
||||
|
} |
||||
|
|
||||
|
public void AddErrors(ObjectValidationContext context) |
||||
|
{ |
||||
|
var serviceType = typeof(IValidator<>).MakeGenericType(context.ValidatingObject.GetType()); |
||||
|
var validator = _serviceProvider.GetService(serviceType) as IValidator; |
||||
|
if (validator == null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var result = validator.Validate(context.ValidatingObject); |
||||
|
if (!result.IsValid) |
||||
|
{ |
||||
|
context.Errors.AddRange( |
||||
|
result.Errors.Select( |
||||
|
error => |
||||
|
new ValidationResult(error.ErrorMessage) |
||||
|
) |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Menu:Administration": "管理" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,122 @@ |
|||||
|
using System.Collections; |
||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using System.Linq; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Reflection; |
||||
|
|
||||
|
namespace Volo.Abp.Validation |
||||
|
{ |
||||
|
public class DataAnnotationObjectValidationContributor : IObjectValidationContributor, ITransientDependency |
||||
|
{ |
||||
|
public const int MaxRecursiveParameterValidationDepth = 8; |
||||
|
|
||||
|
protected AbpValidationOptions Options { get; } |
||||
|
|
||||
|
public DataAnnotationObjectValidationContributor(IOptions<AbpValidationOptions> options) |
||||
|
{ |
||||
|
Options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public void AddErrors(ObjectValidationContext context) |
||||
|
{ |
||||
|
ValidateObjectRecursively(context.Errors, context.ValidatingObject, currentDepth: 1); |
||||
|
} |
||||
|
|
||||
|
protected virtual void ValidateObjectRecursively(List<ValidationResult> errors, object validatingObject, int currentDepth) |
||||
|
{ |
||||
|
if (currentDepth > MaxRecursiveParameterValidationDepth) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (validatingObject == null) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
AddErrors(errors, validatingObject); |
||||
|
|
||||
|
//Validate items of enumerable
|
||||
|
if (validatingObject is IEnumerable) |
||||
|
{ |
||||
|
if (!(validatingObject is IQueryable)) |
||||
|
{ |
||||
|
foreach (var item in (validatingObject as IEnumerable)) |
||||
|
{ |
||||
|
ValidateObjectRecursively(errors, item, currentDepth + 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var validatingObjectType = validatingObject.GetType(); |
||||
|
|
||||
|
//Do not recursively validate for primitive objects
|
||||
|
if (TypeHelper.IsPrimitiveExtended(validatingObjectType)) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (Options.IgnoredTypes.Any(t => t.IsInstanceOfType(validatingObject))) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var properties = TypeDescriptor.GetProperties(validatingObject).Cast<PropertyDescriptor>(); |
||||
|
foreach (var property in properties) |
||||
|
{ |
||||
|
if (property.Attributes.OfType<DisableValidationAttribute>().Any()) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
ValidateObjectRecursively(errors, property.GetValue(validatingObject), currentDepth + 1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public void AddErrors(List<ValidationResult> errors, object validatingObject) |
||||
|
{ |
||||
|
var properties = TypeDescriptor.GetProperties(validatingObject).Cast<PropertyDescriptor>(); |
||||
|
|
||||
|
foreach (var property in properties) |
||||
|
{ |
||||
|
AddPropertyErrors(validatingObject, property, errors); |
||||
|
} |
||||
|
|
||||
|
if (validatingObject is IValidatableObject validatableObject) |
||||
|
{ |
||||
|
errors.AddRange( |
||||
|
validatableObject.Validate(new ValidationContext(validatableObject)) |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual void AddPropertyErrors(object validatingObject, PropertyDescriptor property, List<ValidationResult> errors) |
||||
|
{ |
||||
|
var validationAttributes = property.Attributes.OfType<ValidationAttribute>().ToArray(); |
||||
|
if (validationAttributes.IsNullOrEmpty()) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var validationContext = new ValidationContext(validatingObject) |
||||
|
{ |
||||
|
DisplayName = property.DisplayName, |
||||
|
MemberName = property.Name |
||||
|
}; |
||||
|
|
||||
|
foreach (var attribute in validationAttributes) |
||||
|
{ |
||||
|
var result = attribute.GetValidationResult(property.GetValue(validatingObject), validationContext); |
||||
|
if (result != null) |
||||
|
{ |
||||
|
errors.Add(result); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,71 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using System.ComponentModel; |
|
||||
using System.ComponentModel.DataAnnotations; |
|
||||
using System.Linq; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace Volo.Abp.Validation |
|
||||
{ |
|
||||
public class DataAnnotationValidator : IDataAnnotationValidator, ITransientDependency |
|
||||
{ |
|
||||
public void Validate(object validatingObject) |
|
||||
{ |
|
||||
var errors = GetErrors(validatingObject); |
|
||||
|
|
||||
if (errors.Any()) |
|
||||
{ |
|
||||
throw new AbpValidationException( |
|
||||
"Object state is not valid! See ValidationErrors for details.", |
|
||||
errors |
|
||||
); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets all errors from properties for DataAnnotations attributes and IValidatableObject interface.
|
|
||||
/// </summary>
|
|
||||
public virtual List<ValidationResult> GetErrors(object validatingObject) |
|
||||
{ |
|
||||
var errors = new List<ValidationResult>(); |
|
||||
var properties = TypeDescriptor.GetProperties(validatingObject).Cast<PropertyDescriptor>(); |
|
||||
|
|
||||
foreach (var property in properties) |
|
||||
{ |
|
||||
AddPropertyErrors(validatingObject, property, errors); |
|
||||
} |
|
||||
|
|
||||
if (validatingObject is IValidatableObject validatableObject) |
|
||||
{ |
|
||||
errors.AddRange( |
|
||||
validatableObject.Validate(new ValidationContext(validatableObject)) |
|
||||
); |
|
||||
} |
|
||||
|
|
||||
return errors; |
|
||||
} |
|
||||
|
|
||||
protected virtual void AddPropertyErrors(object validatingObject, PropertyDescriptor property, List<ValidationResult> errors) |
|
||||
{ |
|
||||
var validationAttributes = property.Attributes.OfType<ValidationAttribute>().ToArray(); |
|
||||
if (validationAttributes.IsNullOrEmpty()) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
var validationContext = new ValidationContext(validatingObject) |
|
||||
{ |
|
||||
DisplayName = property.DisplayName, |
|
||||
MemberName = property.Name |
|
||||
}; |
|
||||
|
|
||||
foreach (var attribute in validationAttributes) |
|
||||
{ |
|
||||
var result = attribute.GetValidationResult(property.GetValue(validatingObject), validationContext); |
|
||||
if (result != null) |
|
||||
{ |
|
||||
errors.Add(result); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,12 +0,0 @@ |
|||||
using System.Collections.Generic; |
|
||||
using System.ComponentModel.DataAnnotations; |
|
||||
|
|
||||
namespace Volo.Abp.Validation |
|
||||
{ |
|
||||
public interface IDataAnnotationValidator |
|
||||
{ |
|
||||
void Validate(object validatingObject); |
|
||||
|
|
||||
List<ValidationResult> GetErrors(object validatingObject); |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace Volo.Abp.Validation |
||||
|
{ |
||||
|
public interface IObjectValidationContributor |
||||
|
{ |
||||
|
void AddErrors(ObjectValidationContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.Abp.Validation |
||||
|
{ |
||||
|
public class ObjectValidationContext |
||||
|
{ |
||||
|
[NotNull] |
||||
|
public object ValidatingObject { get; } |
||||
|
|
||||
|
public List<ValidationResult> Errors { get; } |
||||
|
|
||||
|
public ObjectValidationContext([NotNull] object validatingObject) |
||||
|
{ |
||||
|
ValidatingObject = Check.NotNull(validatingObject, nameof(validatingObject)); |
||||
|
Errors = new List<ValidationResult>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,6 +1,6 @@ |
|||||
{ |
{ |
||||
"culture": "en", |
"culture": "en", |
||||
"texts": { |
"texts": { |
||||
|
"Features": "Features" |
||||
} |
} |
||||
} |
} |
||||
@ -1,6 +1,6 @@ |
|||||
{ |
{ |
||||
"culture": "tr", |
"culture": "tr", |
||||
"texts": { |
"texts": { |
||||
|
"Features": "Özellikler" |
||||
} |
} |
||||
} |
} |
||||
Loading…
Reference in new issue