mirror of https://github.com/abpframework/abp.git
24 changed files with 191 additions and 323 deletions
@ -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); |
|||
} |
|||
} |
|||
@ -1,9 +0,0 @@ |
|||
using Volo.Abp.Validation; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.Validation |
|||
{ |
|||
public interface IMvcModelObjectValidator : IObjectValidator |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -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 })); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
} |
|||
} |
|||
@ -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 })); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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<AbpValidationOptions> options) |
|||
: base(options, NullDataAnnotationValidator.Instance) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -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) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace Volo.Abp.Validation |
|||
{ |
|||
public interface IMethodInvocationValidator |
|||
{ |
|||
void Validate(MethodInvocationValidationContext context); |
|||
} |
|||
} |
|||
@ -1,13 +0,0 @@ |
|||
namespace Volo.Abp.Validation |
|||
{ |
|||
/// <summary>
|
|||
/// This interface is used to normalize inputs before method execution.
|
|||
/// </summary>
|
|||
public interface IShouldNormalize |
|||
{ |
|||
/// <summary>
|
|||
/// This method is called lastly before method execution (after validation if exists).
|
|||
/// </summary>
|
|||
void Normalize(); |
|||
} |
|||
} |
|||
@ -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 |
|||
{ |
|||
/// <summary>
|
|||
/// This class is used to validate a method call (invocation) for method arguments.
|
|||
/// </summary>
|
|||
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<DisableValidationAttribute>(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); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Validates the method invocation.
|
|||
/// </summary>
|
|||
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<DisableValidationAttribute>(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); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue