diff --git a/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationValidator.cs b/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationValidator.cs
index 900230afcf..3333354937 100644
--- a/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationValidator.cs
+++ b/src/Volo.Abp.Validation/Volo/Abp/Validation/DataAnnotationValidator.cs
@@ -10,53 +10,61 @@ namespace Volo.Abp.Validation
{
public void Validate(object validatingObject)
{
- var validationResult = new AbpValidationResult();
+ var errors = GetErrors(validatingObject);
- AddErrors(validationResult, validatingObject);
-
- if (validationResult.Errors.Any())
+ if (errors.Any())
{
throw new AbpValidationException(
"Object state is not valid! See ValidationErrors for details.",
- validationResult.Errors
+ errors
);
}
}
///
- /// Checks all properties for DataAnnotations attributes.
+ /// Gets all errors from properties for DataAnnotations attributes and IValidatableObject interface.
///
- public virtual void AddErrors(IAbpValidationResult validationResult, object validatingObject)
+ public virtual List GetErrors(object validatingObject)
{
+ var errors = new List();
var properties = TypeDescriptor.GetProperties(validatingObject).Cast();
+
foreach (var property in properties)
{
- var validationAttributes = property.Attributes.OfType().ToArray();
- if (validationAttributes.IsNullOrEmpty())
- {
- continue;
- }
+ AddPropertyErrors(validatingObject, property, errors);
+ }
- var validationContext = new ValidationContext(validatingObject)
- {
- DisplayName = property.DisplayName,
- MemberName = property.Name
- };
+ if (validatingObject is IValidatableObject validatableObject)
+ {
+ errors.AddRange(
+ validatableObject.Validate(new ValidationContext(validatableObject))
+ );
+ }
- foreach (var attribute in validationAttributes)
- {
- var result = attribute.GetValidationResult(property.GetValue(validatingObject), validationContext);
- if (result != null)
- {
- validationResult.Errors.Add(result);
- }
- }
+ return errors;
+ }
+
+ protected virtual void AddPropertyErrors(object validatingObject, PropertyDescriptor property, List errors)
+ {
+ var validationAttributes = property.Attributes.OfType().ToArray();
+ if (validationAttributes.IsNullOrEmpty())
+ {
+ return;
}
- if (validatingObject is IValidatableObject)
+ var validationContext = new ValidationContext(validatingObject)
{
- var results = (validatingObject as IValidatableObject).Validate(new ValidationContext(validatingObject));
- validationResult.Errors.AddRange(results);
+ 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);
+ }
}
}
}
diff --git a/src/Volo.Abp.Validation/Volo/Abp/Validation/IDataAnnotationValidator.cs b/src/Volo.Abp.Validation/Volo/Abp/Validation/IDataAnnotationValidator.cs
index a31642daae..6b14ff66b6 100644
--- a/src/Volo.Abp.Validation/Volo/Abp/Validation/IDataAnnotationValidator.cs
+++ b/src/Volo.Abp.Validation/Volo/Abp/Validation/IDataAnnotationValidator.cs
@@ -1,9 +1,12 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+
namespace Volo.Abp.Validation
{
public interface IDataAnnotationValidator
{
void Validate(object validatingObject);
- void AddErrors(IAbpValidationResult validationResult, object validatingObject);
+ List GetErrors(object validatingObject);
}
}
\ No newline at end of file
diff --git a/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs b/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs
index ee501a44de..8388605e62 100644
--- a/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs
+++ b/src/Volo.Abp.Validation/Volo/Abp/Validation/IObjectValidator.cs
@@ -1,9 +1,16 @@
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+
namespace Volo.Abp.Validation
{
public interface IObjectValidator
{
- void Validate(object validatingObject, string name = null, bool allowNull = false);
+ void Validate(
+ object validatingObject,
+ string name = null,
+ bool allowNull = false
+ );
- void AddErrors(IAbpValidationResult validationResult, object validatingObject, string name = null, bool allowNull = false);
+ List GetErrors(object validatingObject, string name = null, bool allowNull = false);
}
}
\ No newline at end of file
diff --git a/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs b/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs
index aa4dab2aa1..bf266b3936 100644
--- a/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs
+++ b/src/Volo.Abp.Validation/Volo/Abp/Validation/MethodInvocationValidator.cs
@@ -40,6 +40,7 @@ namespace Volo.Abp.Validation
throw new Exception("Method parameter count does not match with argument count!");
}
+ //todo: consider to remove this condition
if (context.Errors.Any() && HasSingleNullArgument(context))
{
ThrowValidationError(context);
@@ -90,7 +91,7 @@ namespace Volo.Abp.Validation
parameterInfo.IsOut ||
TypeHelper.IsPrimitiveExtendedIncludingNullable(parameterInfo.ParameterType, includeEnums: true);
- _objectValidator.AddErrors(context, parameterValue, parameterInfo.Name, allowNulls);
+ context.Errors.AddRange(_objectValidator.GetErrors(parameterValue, parameterInfo.Name, allowNulls));
}
}
}
\ No newline at end of file
diff --git a/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs b/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs
index 1f1062c993..315652b78c 100644
--- a/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs
+++ b/src/Volo.Abp.Validation/Volo/Abp/Validation/ObjectValidator.cs
@@ -1,4 +1,5 @@
using System.Collections;
+using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
@@ -8,7 +9,7 @@ using Volo.Abp.Reflection;
namespace Volo.Abp.Validation
{
- public class ObjectValidator : ITransientDependency, IObjectValidator
+ public class ObjectValidator : IObjectValidator, ITransientDependency
{
private const int MaxRecursiveParameterValidationDepth = 8;
@@ -23,36 +24,38 @@ namespace Volo.Abp.Validation
public virtual void Validate(object validatingObject, string name = null, bool allowNull = false)
{
- var validationResult = new AbpValidationResult();
+ var errors = GetErrors(validatingObject, name, allowNull);
- AddErrors(validationResult, validatingObject, name, allowNull);
-
- if (validationResult.Errors.Any())
+ if (errors.Any())
{
throw new AbpValidationException(
"Object state is not valid! See ValidationErrors for details.",
- validationResult.Errors
+ errors
);
}
}
- public virtual void AddErrors(IAbpValidationResult validationResult, object validatingObject, string name = null, bool allowNull = false)
+ public virtual List GetErrors(object validatingObject, string name = null, bool allowNull = false)
{
+ var errors = new List();
+
if (validatingObject == null && !allowNull)
{
- validationResult.Errors.Add(
+ errors.Add(
name == null
? new ValidationResult("Given object is null!")
: new ValidationResult(name + " is null!", new[] { name })
);
- return;
+ return errors;
}
- ValidateObjectRecursively(validationResult, validatingObject, 1);
+ ValidateObjectRecursively(errors, validatingObject, currentDepth: 1);
+
+ return errors;
}
- protected virtual void ValidateObjectRecursively(IAbpValidationResult context, object validatingObject, int currentDepth)
+ protected virtual void ValidateObjectRecursively(List errors, object validatingObject, int currentDepth)
{
if (currentDepth > MaxRecursiveParameterValidationDepth)
{
@@ -64,20 +67,19 @@ namespace Volo.Abp.Validation
return;
}
- _dataAnnotationValidator.AddErrors(context, validatingObject);
+ errors.AddRange(_dataAnnotationValidator.GetErrors(validatingObject));
//Validate items of enumerable
- if (validatingObject is IEnumerable && !(validatingObject is IQueryable))
+ if (validatingObject is IEnumerable)
{
- foreach (var item in (validatingObject as IEnumerable))
+ if (!(validatingObject is IQueryable))
{
- ValidateObjectRecursively(context, item, currentDepth + 1);
+ foreach (var item in (validatingObject as IEnumerable))
+ {
+ ValidateObjectRecursively(errors, item, currentDepth + 1);
+ }
}
- }
- //Do not recursively validate for enumerable objects
- if (validatingObject is IEnumerable)
- {
return;
}
@@ -102,7 +104,7 @@ namespace Volo.Abp.Validation
continue;
}
- ValidateObjectRecursively(context, property.GetValue(validatingObject), currentDepth + 1);
+ ValidateObjectRecursively(errors, property.GetValue(validatingObject), currentDepth + 1);
}
}
}