diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/RazorPages/AbpPageModel.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/RazorPages/AbpPageModel.cs index 0a5af5d7ee..5c337d15b3 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/RazorPages/AbpPageModel.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/RazorPages/AbpPageModel.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using Volo.Abp.AspNetCore.Mvc.Validation; using Volo.Abp.Guids; using Volo.Abp.ObjectMapping; using Volo.Abp.Uow; @@ -20,7 +21,7 @@ namespace Volo.Abp.AspNetCore.Mvc.RazorPages public ILoggerFactory LoggerFactory { get; set; } - public IObjectValidator ObjectValidator { get; set; } + public IModelStateValidator ModelValidator { get; set; } protected IUnitOfWork CurrentUnitOfWork => UnitOfWorkManager?.Current; @@ -31,5 +32,10 @@ namespace Volo.Abp.AspNetCore.Mvc.RazorPages { return new NoContentResult(); } + + protected virtual void ValidateModel() + { + ModelValidator?.Validate(ModelState); + } } } diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/AbpValidationActionFilter.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/AbpValidationActionFilter.cs index 41b1d2471b..ead395a783 100644 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/AbpValidationActionFilter.cs +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/AbpValidationActionFilter.cs @@ -8,9 +8,9 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation { public class AbpValidationActionFilter : IAsyncActionFilter, ITransientDependency { - private readonly MvcActionInvocationValidator _validator; + private readonly ModelStateValidator _validator; - public AbpValidationActionFilter(MvcActionInvocationValidator validator) + public AbpValidationActionFilter(ModelStateValidator validator) { _validator = validator; } @@ -28,7 +28,7 @@ namespace Volo.Abp.AspNetCore.Mvc.Validation using (AbpCrossCuttingConcerns.Applying(context.Controller, AbpCrossCuttingConcerns.Validation)) { - _validator.Validate(new MvcActionInvocationValidationContext(context)); + _validator.Validate(context.ModelState); await next(); } } diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/IModelStateValidator.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/IModelStateValidator.cs new file mode 100644 index 0000000000..6d984f2069 --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/IModelStateValidator.cs @@ -0,0 +1,12 @@ +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Volo.Abp.Validation; + +namespace Volo.Abp.AspNetCore.Mvc.Validation +{ + public interface IModelStateValidator + { + void Validate(ModelStateDictionary modelState); + + void AddErrors(IAbpValidationResult validationResult, ModelStateDictionary modelState); + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/IMvcModelObjectValidator.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/IMvcModelObjectValidator.cs deleted file mode 100644 index ec1c777b8d..0000000000 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/IMvcModelObjectValidator.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Volo.Abp.Validation; - -namespace Volo.Abp.AspNetCore.Mvc.Validation -{ - public interface IMvcModelObjectValidator : IObjectValidator - { - - } -} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ModelStateValidator.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ModelStateValidator.cs new file mode 100644 index 0000000000..d943a439fb --- /dev/null +++ b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/ModelStateValidator.cs @@ -0,0 +1,42 @@ +using System.ComponentModel.DataAnnotations; +using System.Linq; +using Microsoft.AspNetCore.Mvc.ModelBinding; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Validation; + +namespace Volo.Abp.AspNetCore.Mvc.Validation +{ + public class ModelStateValidator : IModelStateValidator, ITransientDependency + { + public virtual void Validate(ModelStateDictionary modelState) + { + var validationResult = new AbpValidationResult(); + + AddErrors(validationResult, modelState); + + if (validationResult.Errors.Any()) + { + throw new AbpValidationException( + "ModelState is not valid! See ValidationErrors for details.", + validationResult.Errors + ); + } + } + + public virtual void AddErrors(IAbpValidationResult validationResult, ModelStateDictionary modelState) + { + if (modelState.IsValid) + { + return; + } + + foreach (var state in modelState) + { + foreach (var error in state.Value.Errors) + { + validationResult.Errors.Add(new ValidationResult(error.ErrorMessage, new[] { state.Key })); + } + } + } + } +} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/MvcActionInvocationValidationContext.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/MvcActionInvocationValidationContext.cs deleted file mode 100644 index b5b7740e17..0000000000 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/MvcActionInvocationValidationContext.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Collections.Generic; -using Microsoft.AspNetCore.Mvc.Abstractions; -using Microsoft.AspNetCore.Mvc.Filters; -using Volo.Abp.Validation; - -namespace Volo.Abp.AspNetCore.Mvc.Validation -{ - public class MvcActionInvocationValidationContext : MethodInvocationValidationContext - { - public ActionExecutingContext ActionContext { get; } - - public MvcActionInvocationValidationContext(ActionExecutingContext actionContext) - : base(actionContext.ActionDescriptor.GetMethodInfo(), GetParameterValues(actionContext)) - { - ActionContext = actionContext; - } - - private static object[] GetParameterValues(ActionExecutingContext actionContext) - { - var methodInfo = actionContext.ActionDescriptor.GetMethodInfo(); - - var parameters = methodInfo.GetParameters(); - var parameterValues = new object[parameters.Length]; - - for (var i = 0; i < parameters.Length; i++) - { - parameterValues[i] = actionContext.ActionArguments.GetOrDefault(parameters[i].Name); - } - - return parameterValues; - } - } -} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/MvcActionInvocationValidator.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/MvcActionInvocationValidator.cs deleted file mode 100644 index 9d904b1c21..0000000000 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/MvcActionInvocationValidator.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Volo.Abp.Validation; - -namespace Volo.Abp.AspNetCore.Mvc.Validation -{ - public class MvcActionInvocationValidator : MethodInvocationValidatorBase - { - // ReSharper disable once SuggestBaseTypeForParameter - public MvcActionInvocationValidator(IMvcModelObjectValidator objectValidator) - : base(objectValidator) - { - - } - - public virtual void Validate(MvcActionInvocationValidationContext context) - { - AddModelStateErrors(context); - ValidateInternal(context); - } - - public virtual void AddModelStateErrors(MvcActionInvocationValidationContext context) - { - if (context.ActionContext.ModelState.IsValid) - { - return; - } - - foreach (var state in context.ActionContext.ModelState) - { - foreach (var error in state.Value.Errors) - { - context.Errors.Add(new ValidationResult(error.ErrorMessage, new[] { state.Key })); - } - } - } - } -} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/MvcModelValidator.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/MvcModelValidator.cs deleted file mode 100644 index 182c023784..0000000000 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/MvcModelValidator.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Validation; - -namespace Volo.Abp.AspNetCore.Mvc.Validation -{ - [ExposeServices(typeof(IMvcModelObjectValidator))] - public class MvcModelValidator : ObjectValidator, IMvcModelObjectValidator - { - public MvcModelValidator(IOptions options) - : base(options, NullDataAnnotationValidator.Instance) - { - } - } -} \ No newline at end of file diff --git a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/NullDataAnnotationValidator.cs b/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/NullDataAnnotationValidator.cs deleted file mode 100644 index cb1e659a86..0000000000 --- a/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Validation/NullDataAnnotationValidator.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Volo.Abp.Validation; - -namespace Volo.Abp.AspNetCore.Mvc.Validation -{ - public sealed class NullDataAnnotationValidator : IDataAnnotationValidator - { - public static IDataAnnotationValidator Instance { get; } = new DataAnnotationValidator(); - - private NullDataAnnotationValidator() - { - - } - - public void AddDataAnnotationAttributeErrors(IAbpValidationResult validationResult, object validatingObject) - { - - } - } -} \ No newline at end of file diff --git a/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs b/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs index 0147de8f02..2fb0a4a25a 100644 --- a/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs +++ b/src/Volo.Abp.Identity.Web/Pages/Identity/Users/CreateModal.cshtml.cs @@ -35,8 +35,7 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users public async Task OnPostAsync() { - ObjectValidator.Validate(UserInfo, nameof(UserInfo)); - ObjectValidator.Validate(Roles, nameof(Roles)); + ValidateModel(); var input = ObjectMapper.Map(UserInfo); input.RoleNames = Roles.Where(r => r.IsAssigned).Select(r => r.Name).ToArray(); diff --git a/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs b/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs index 8c21f50fad..ee689ad32e 100644 --- a/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs +++ b/src/Volo.Abp.Identity.Web/Pages/Identity/Users/EditModal.cshtml.cs @@ -45,8 +45,7 @@ namespace Volo.Abp.Identity.Web.Pages.Identity.Users public async Task OnPostAsync() { - ObjectValidator.Validate(UserInfo, nameof(UserInfo)); - ObjectValidator.Validate(Roles, nameof(Roles)); + ValidateModel(); var input = ObjectMapper.Map(UserInfo); input.RoleNames = Roles.Where(r => r.IsAssigned).Select(r => r.Name).ToArray(); diff --git a/src/Volo.Abp/Volo/Abp/Validation/AbpValidationResult.cs b/src/Volo.Abp/Volo/Abp/Validation/AbpValidationResult.cs index a9bf2c9fde..05121c2f7c 100644 --- a/src/Volo.Abp/Volo/Abp/Validation/AbpValidationResult.cs +++ b/src/Volo.Abp/Volo/Abp/Validation/AbpValidationResult.cs @@ -7,12 +7,9 @@ namespace Volo.Abp.Validation { public List Errors { get; } - public List ObjectsToBeNormalized { get; } - public AbpValidationResult() { Errors = new List(); - ObjectsToBeNormalized = new List(); } } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Validation/DataAnnotationValidator.cs b/src/Volo.Abp/Volo/Abp/Validation/DataAnnotationValidator.cs index 0ecd1ae7a2..900230afcf 100644 --- a/src/Volo.Abp/Volo/Abp/Validation/DataAnnotationValidator.cs +++ b/src/Volo.Abp/Volo/Abp/Validation/DataAnnotationValidator.cs @@ -8,10 +8,25 @@ namespace Volo.Abp.Validation { public class DataAnnotationValidator : IDataAnnotationValidator, ITransientDependency { + public void Validate(object validatingObject) + { + var validationResult = new AbpValidationResult(); + + AddErrors(validationResult, validatingObject); + + if (validationResult.Errors.Any()) + { + throw new AbpValidationException( + "Object state is not valid! See ValidationErrors for details.", + validationResult.Errors + ); + } + } + /// /// Checks all properties for DataAnnotations attributes. /// - public virtual void AddDataAnnotationAttributeErrors(IAbpValidationResult validationResult, object validatingObject) + public virtual void AddErrors(IAbpValidationResult validationResult, object validatingObject) { var properties = TypeDescriptor.GetProperties(validatingObject).Cast(); foreach (var property in properties) diff --git a/src/Volo.Abp/Volo/Abp/Validation/IAbpValidationResult.cs b/src/Volo.Abp/Volo/Abp/Validation/IAbpValidationResult.cs index 56e597e6f1..d96ec70bec 100644 --- a/src/Volo.Abp/Volo/Abp/Validation/IAbpValidationResult.cs +++ b/src/Volo.Abp/Volo/Abp/Validation/IAbpValidationResult.cs @@ -6,7 +6,5 @@ namespace Volo.Abp.Validation public interface IAbpValidationResult { List Errors { get; } - - List ObjectsToBeNormalized { get; } } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Validation/IDataAnnotationValidator.cs b/src/Volo.Abp/Volo/Abp/Validation/IDataAnnotationValidator.cs index fcf523dd16..a31642daae 100644 --- a/src/Volo.Abp/Volo/Abp/Validation/IDataAnnotationValidator.cs +++ b/src/Volo.Abp/Volo/Abp/Validation/IDataAnnotationValidator.cs @@ -2,6 +2,8 @@ namespace Volo.Abp.Validation { public interface IDataAnnotationValidator { - void AddDataAnnotationAttributeErrors(IAbpValidationResult validationResult, object validatingObject); + void Validate(object validatingObject); + + void AddErrors(IAbpValidationResult validationResult, object validatingObject); } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Validation/IMethodInvocationValidator.cs b/src/Volo.Abp/Volo/Abp/Validation/IMethodInvocationValidator.cs new file mode 100644 index 0000000000..218ad9313d --- /dev/null +++ b/src/Volo.Abp/Volo/Abp/Validation/IMethodInvocationValidator.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.Validation +{ + public interface IMethodInvocationValidator + { + void Validate(MethodInvocationValidationContext context); + } +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Validation/IObjectValidator.cs b/src/Volo.Abp/Volo/Abp/Validation/IObjectValidator.cs index f0cb893d97..ee501a44de 100644 --- a/src/Volo.Abp/Volo/Abp/Validation/IObjectValidator.cs +++ b/src/Volo.Abp/Volo/Abp/Validation/IObjectValidator.cs @@ -4,6 +4,6 @@ namespace Volo.Abp.Validation { void Validate(object validatingObject, string name = null, bool allowNull = false); - void AddValidatationErrors(IAbpValidationResult validationResult, object validatingObject, string name = null, bool allowNull = false); + void AddErrors(IAbpValidationResult validationResult, object validatingObject, string name = null, bool allowNull = false); } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Validation/IShouldNormalize.cs b/src/Volo.Abp/Volo/Abp/Validation/IShouldNormalize.cs deleted file mode 100644 index bf543bba6e..0000000000 --- a/src/Volo.Abp/Volo/Abp/Validation/IShouldNormalize.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Volo.Abp.Validation -{ - /// - /// This interface is used to normalize inputs before method execution. - /// - public interface IShouldNormalize - { - /// - /// This method is called lastly before method execution (after validation if exists). - /// - void Normalize(); - } -} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidationContext.cs b/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidationContext.cs index 9f7a63bf7d..96548e96f7 100644 --- a/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidationContext.cs +++ b/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidationContext.cs @@ -15,7 +15,6 @@ namespace Volo.Abp.Validation Method = method; ParameterValues = parameterValues; Parameters = method.GetParameters(); - } } } \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidator.cs b/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidator.cs index cadae946dd..aa4dab2aa1 100644 --- a/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidator.cs +++ b/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidator.cs @@ -1,19 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Reflection; + namespace Volo.Abp.Validation { - /// - /// This class is used to validate a method call (invocation) for method arguments. - /// - public class MethodInvocationValidator : MethodInvocationValidatorBase + public class MethodInvocationValidator : IMethodInvocationValidator, ITransientDependency { - public MethodInvocationValidator(IObjectValidator objectValidator) - : base(objectValidator) - { + private readonly IObjectValidator _objectValidator; + public MethodInvocationValidator(IObjectValidator objectValidator) + { + _objectValidator = objectValidator; } public virtual void Validate(MethodInvocationValidationContext context) { - ValidateInternal(context); + Check.NotNull(context, nameof(context)); + + if (context.Parameters.IsNullOrEmpty()) + { + return; + } + + if (!context.Method.IsPublic) + { + return; + } + + if (IsValidationDisabled(context)) + { + return; + } + + if (context.Parameters.Length != context.ParameterValues.Length) + { + throw new Exception("Method parameter count does not match with argument count!"); + } + + if (context.Errors.Any() && HasSingleNullArgument(context)) + { + ThrowValidationError(context); + } + + AddMethodParameterValidationErrors(context); + + if (context.Errors.Any()) + { + ThrowValidationError(context); + } + } + + protected virtual bool IsValidationDisabled(MethodInvocationValidationContext context) + { + if (context.Method.IsDefined(typeof(EnableValidationAttribute), true)) + { + return false; + } + + return ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(context.Method) != null; + } + + protected virtual bool HasSingleNullArgument(MethodInvocationValidationContext context) + { + return context.Parameters.Length == 1 && context.ParameterValues[0] == null; + } + + protected virtual void ThrowValidationError(MethodInvocationValidationContext context) + { + throw new AbpValidationException( + "Method arguments are not valid! See ValidationErrors for details.", + context.Errors + ); + } + + protected virtual void AddMethodParameterValidationErrors(MethodInvocationValidationContext context) + { + for (var i = 0; i < context.Parameters.Length; i++) + { + AddMethodParameterValidationErrors(context, context.Parameters[i], context.ParameterValues[i]); + } + } + + protected virtual void AddMethodParameterValidationErrors(IAbpValidationResult context, ParameterInfo parameterInfo, object parameterValue) + { + var allowNulls = parameterInfo.IsOptional || + parameterInfo.IsOut || + TypeHelper.IsPrimitiveExtendedIncludingNullable(parameterInfo.ParameterType, includeEnums: true); + + _objectValidator.AddErrors(context, parameterValue, parameterInfo.Name, allowNulls); } } -} +} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidatorBase.cs b/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidatorBase.cs deleted file mode 100644 index a6dc70d3e5..0000000000 --- a/src/Volo.Abp/Volo/Abp/Validation/MethodInvocationValidatorBase.cs +++ /dev/null @@ -1,105 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Reflection; -using Volo.Abp.DependencyInjection; -using Volo.Abp.Reflection; - -namespace Volo.Abp.Validation -{ - public abstract class MethodInvocationValidatorBase : ITransientDependency - { - private readonly IObjectValidator _objectValidator; - - protected MethodInvocationValidatorBase(IObjectValidator objectValidator) - { - _objectValidator = objectValidator; - } - - /// - /// Validates the method invocation. - /// - protected virtual void ValidateInternal(MethodInvocationValidationContext context) - { - Check.NotNull(context, nameof(context)); - - if (context.Parameters.IsNullOrEmpty()) - { - return; - } - - if (!context.Method.IsPublic) - { - return; - } - - if (IsValidationDisabled(context)) - { - return; - } - - if (context.Parameters.Length != context.ParameterValues.Length) - { - throw new Exception("Method parameter count does not match with argument count!"); - } - - if (context.Errors.Any() && HasSingleNullArgument(context)) - { - ThrowValidationError(context); - } - - AddMethodParameterValidationErrors(context); - - if (context.Errors.Any()) - { - ThrowValidationError(context); - } - - foreach (var objectToBeNormalized in context.ObjectsToBeNormalized) - { - objectToBeNormalized.Normalize(); - } - } - - protected virtual bool IsValidationDisabled(MethodInvocationValidationContext context) - { - if (context.Method.IsDefined(typeof(EnableValidationAttribute), true)) - { - return false; - } - - return ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(context.Method) != null; - } - - protected virtual bool HasSingleNullArgument(MethodInvocationValidationContext context) - { - return context.Parameters.Length == 1 && context.ParameterValues[0] == null; - } - - protected virtual void ThrowValidationError(MethodInvocationValidationContext context) - { - throw new AbpValidationException( - "Method arguments are not valid! See ValidationErrors for details.", - context.Errors - ); - } - - protected virtual void AddMethodParameterValidationErrors(MethodInvocationValidationContext context) - { - for (var i = 0; i < context.Parameters.Length; i++) - { - AddMethodParameterValidationErrors(context, context.Parameters[i], context.ParameterValues[i]); - } - } - - protected virtual void AddMethodParameterValidationErrors(IAbpValidationResult context, ParameterInfo parameterInfo, object parameterValue) - { - var allowNulls = parameterInfo.IsOptional || - parameterInfo.IsOut || - TypeHelper.IsPrimitiveExtendedIncludingNullable(parameterInfo.ParameterType, includeEnums: true); - - _objectValidator.AddValidatationErrors(context, parameterValue, parameterInfo.Name, allowNulls); - } - } -} \ No newline at end of file diff --git a/src/Volo.Abp/Volo/Abp/Validation/ObjectValidator.cs b/src/Volo.Abp/Volo/Abp/Validation/ObjectValidator.cs index 92375542c6..1f1062c993 100644 --- a/src/Volo.Abp/Volo/Abp/Validation/ObjectValidator.cs +++ b/src/Volo.Abp/Volo/Abp/Validation/ObjectValidator.cs @@ -25,23 +25,18 @@ namespace Volo.Abp.Validation { var validationResult = new AbpValidationResult(); - AddValidatationErrors(validationResult, validatingObject, name, allowNull); + AddErrors(validationResult, validatingObject, name, allowNull); if (validationResult.Errors.Any()) { throw new AbpValidationException( - "Method arguments are not valid! See ValidationErrors for details.", + "Object state is not valid! See ValidationErrors for details.", validationResult.Errors ); } - - foreach (var objectToBeNormalized in validationResult.ObjectsToBeNormalized) - { - objectToBeNormalized.Normalize(); - } } - public virtual void AddValidatationErrors(IAbpValidationResult validationResult, object validatingObject, string name = null, bool allowNull = false) + public virtual void AddErrors(IAbpValidationResult validationResult, object validatingObject, string name = null, bool allowNull = false) { if (validatingObject == null && !allowNull) { @@ -69,7 +64,7 @@ namespace Volo.Abp.Validation return; } - _dataAnnotationValidator.AddDataAnnotationAttributeErrors(context, validatingObject); + _dataAnnotationValidator.AddErrors(context, validatingObject); //Validate items of enumerable if (validatingObject is IEnumerable && !(validatingObject is IQueryable)) @@ -80,12 +75,6 @@ namespace Volo.Abp.Validation } } - //Add list to be normalized later - if (validatingObject is IShouldNormalize) - { - context.ObjectsToBeNormalized.Add(validatingObject as IShouldNormalize); - } - //Do not recursively validate for enumerable objects if (validatingObject is IEnumerable) { diff --git a/src/Volo.Abp/Volo/Abp/Validation/ValidationInterceptor.cs b/src/Volo.Abp/Volo/Abp/Validation/ValidationInterceptor.cs index d09e5bccd8..afa822e60d 100644 --- a/src/Volo.Abp/Volo/Abp/Validation/ValidationInterceptor.cs +++ b/src/Volo.Abp/Volo/Abp/Validation/ValidationInterceptor.cs @@ -6,9 +6,9 @@ namespace Volo.Abp.Validation { public class ValidationInterceptor : AbpInterceptor, ITransientDependency { - private readonly MethodInvocationValidator _validator; + private readonly IMethodInvocationValidator _validator; - public ValidationInterceptor(MethodInvocationValidator validator) + public ValidationInterceptor(IMethodInvocationValidator validator) { _validator = validator; } @@ -28,13 +28,12 @@ namespace Volo.Abp.Validation protected virtual void Validate(IAbpMethodInvocation invocation) { - _validator - .Validate( - new MethodInvocationValidationContext( - invocation.Method, - invocation.Arguments - ) - ); + _validator.Validate( + new MethodInvocationValidationContext( + invocation.Method, + invocation.Arguments + ) + ); } } } diff --git a/test/Volo.Abp.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs b/test/Volo.Abp.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs index a72c84d54b..281e207298 100644 --- a/test/Volo.Abp.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs +++ b/test/Volo.Abp.Tests/Volo/Abp/Validation/ApplicationService_Validation_Tests.cs @@ -134,22 +134,6 @@ namespace Volo.Abp.Validation }); } - [Fact] - public void Should_Normalize_Nested_Dtos() - { - var input = new MyMethod7Input - { - Inner = new MyMethod7Input.MyMethod7InputInner - { - Value = 10 - } - }; - - _myAppService.MyMethod7(input); - - input.Inner.Value.ShouldBe(12); - } - [Fact] public void Should_Stop_Recursive_Validation_In_A_Constant_Depth() { @@ -180,7 +164,6 @@ namespace Volo.Abp.Validation MyMethodOutput MyMethod4_2(MyMethod4Input input); MyMethodOutput MyMethod5(MyMethod5Input input); MyMethodOutput MyMethod6(MyMethod6Input input); - MyMethodOutput MyMethod7(MyMethod7Input input); MyMethodOutput MyMethod8(MyClassWithRecursiveReference input); void MyMethodWithNullableEnum(MyEnum? value); } @@ -223,11 +206,6 @@ namespace Volo.Abp.Validation return new MyMethodOutput { Result = 42 }; } - public MyMethodOutput MyMethod7(MyMethod7Input input) - { - return new MyMethodOutput { Result = 42 }; - } - public MyMethodOutput MyMethod8(MyClassWithRecursiveReference input) { return new MyMethodOutput { Result = 42 }; @@ -298,26 +276,6 @@ namespace Volo.Abp.Validation } } - public class MyMethod7Input : IShouldNormalize - { - public MyMethod7InputInner Inner { get; set; } - - public void Normalize() - { - Inner.Value++; - } - - public class MyMethod7InputInner : IShouldNormalize - { - public int Value { get; set; } - - public void Normalize() - { - Value++; - } - } - } - public class MyClassInList { [Required]