/// <summary> /// Validates the parameter. /// </summary> /// <param name="invocation">The invocation.</param> /// <param name="parameterPosition">The parameter position.</param> /// <param name="runWhen">The run when.</param> /// <param name="errors">The errors.</param> protected virtual void ValidateParameter(IInvocation invocation, int parameterPosition, RunWhen runWhen, ErrorSummary errors) { MethodInfo method = invocation.Method; ParameterInfoMeta parameterInfoMeta; IValidator[] validators = methodValidatorMetaStore.GetValidatorsFor(method, parameterPosition, null, runWhen, out parameterInfoMeta); foreach (IValidator validator in validators) { IPropertyAccessAware propertyAccessAware = (IPropertyAccessAware)validator; object value = invocation.Arguments[parameterPosition]; if (parameterInfoMeta == ParameterInfoMeta.ParamsArray) { ValidateParamsArray(validator, propertyAccessAware, value, errors); continue; } propertyAccessAware.PropertyAccessor = delegate { return invocation.Arguments[parameterPosition]; }; if (validator.IsValid(value)) continue; AppendError(validator, errors); } }
/// <summary> /// Builds the error message to throw when there are validator errors. /// </summary> /// <param name="method">The method.</param> /// <param name="errors">The errors.</param> /// <returns></returns> protected virtual string BuildErrorMessage(MethodInfo method, ErrorSummary errors) { StringBuilder builder = new StringBuilder(); builder.Append(string.Format("Validation failure will invoking method: {0}", method)).Append(Environment.NewLine); builder.Append(ErrorSummaryHelper.CreateSummary(errors)); return builder.ToString(); }
/// <errorSummary> /// Determines whether the specified instance is valid. /// </errorSummary> /// <param name="instance">The instance.</param> /// <param name="fieldValue">The field value.</param> /// <returns> /// <c>true</c> if the specified instance is valid; otherwise, <c>false</c>. /// </returns> public override bool IsValid(object instance, object fieldValue) { ValidatorRunner runner = new ValidatorRunner(validationRegistry.BaseRegistry); bool valid = runner.IsValid(instance); if (!valid) errorSummary = runner.GetErrorSummary(instance); return valid; }
public void Validate(ErrorSummary errors) { if (Product == null) { errors.RegisterErrorMessage("Product", "The order must have a product."); return; } if (Quantity < Product.MinQuantity || Quantity > Product.MaxQuantity) errors.RegisterErrorMessage("Quantity", string.Format("The quantity {0} is invalid, it must be between {1} and {2}", Quantity, Product.MinQuantity, Product.MaxQuantity)); }
/// <summary> /// Creates a string representation of the error summary. /// </summary> /// <param name="errors">The errors.</param> /// <returns></returns> public static string CreateSummary(ErrorSummary errors) { StringBuilder builder = new StringBuilder(); foreach (string property in errors.InvalidProperties) { builder.Append(" - ").Append(property).Append(": "); builder.Append(string.Join(",", errors.GetErrorsForProperty(property))); builder.Append(Environment.NewLine); } return builder.ToString(); }
bool IValidationPerformer.PerformValidation(object objectInstance, IEnumerable<IValidator> validators, IEnumerable<IValidationContributor> contributors, RunWhen runWhen, ErrorSummary summaryToPopulate) { foreach (IValidator validator in validators) { if (!validator.IsValid(objectInstance)) { string name = validator.FriendlyName ?? validator.Name; summaryToPopulate.RegisterErrorMessage(name, validator.ErrorMessage); } } if(contributors != null) (this as IValidationPerformer).ExecuteContributors(objectInstance, contributors, summaryToPopulate, runWhen); bool isValid = !summaryToPopulate.HasError; return isValid; }
private static string GenerateMessage(ErrorSummary summary) { StringBuilder sb = new StringBuilder(); sb.AppendLine("Validation errors"); foreach (string invalidProperty in summary.InvalidProperties) { sb.Append(invalidProperty).AppendLine(":"); foreach (string error in summary.GetErrorsForProperty(invalidProperty)) { sb.Append("\t").AppendLine(error); } sb.AppendLine(); } return sb.ToString(); }
/// <summary> /// Determines whether the specified instance is valid. /// </summary> /// <param name="instance">The instance.</param> /// <param name="runWhen">The run when.</param> /// <returns></returns> public ErrorSummary IsValid(object instance, RunWhen runWhen) { ErrorSummary errors = new ErrorSummary(); IInvocation invocation = instance as IInvocation; if (invocation == null) return errors; for (int i = 0; i < invocation.Arguments.Length; i++) { ValidateParameter(invocation, i, runWhen, errors); } return errors; }
public void Update([DataBind("details", Validate = true)] UserDetailsRequestDTO details) { if (Validator.IsValid(details)) { var success = userService.UpdateDetails(details); if (!success) { var errorSummary = new ErrorSummary(); errorSummary.RegisterErrorMessage(string.Empty, "There was a problem updating your details"); Flash["errors"] = errorSummary; } } else Flash["errors"] = Validator.GetErrorSummary(details); RedirectToAction("Show"); }
private static void AddModelErrors(ModelStateDictionary modelState, ErrorSummary errorSummary) { if (errorSummary == null) { throw new ArgumentNullException("errorSummary"); } var errorInfos = from property in errorSummary.InvalidProperties from message in errorSummary.GetErrorsForProperty(property) select new { PropertyName = property, ErrorMessage = message }; foreach (var errorInfo in errorInfos) { modelState.AddModelError(errorInfo.PropertyName, errorInfo.ErrorMessage); } }
public void Should_Fail_To_Send_Email_Because_Email_Is_Invalid() { // arrange const string errorMessage = "message"; var email = new Email(); var validatorRunner = new Mock<IValidatorRunner>(); var errorSummary = new ErrorSummary(); validatorRunner.Setup(v => v.IsValid(It.IsAny<Email>())).Returns(false); validatorRunner.Setup(v => v.GetErrorSummary(It.IsAny<Email>())).Returns(errorSummary); errorSummary.RegisterErrorMessage(errorMessage, errorMessage); // act var service = new EmailSenderService(validatorRunner.Object); TestDelegate act = () => service.Send(email); // assert Assert.That(act, Throws.InstanceOf<ValidationException>().With.Property("ValidationErrorMessages").EqualTo(new[] { errorMessage })); }
/// <summary> /// Registers the error message returned from an object validator /// as an error message for each individual indexed property. /// </summary> /// <param name="validator">The validator.</param> /// <param name="errors">The errors.</param> private void RegisterObjectValidatorErrorMessages(ObjectValidator validator, ErrorSummary errors) { ErrorSummary objectErrors = validator.ErrorSummary; foreach (string property in objectErrors.InvalidProperties) { foreach (string message in objectErrors.GetErrorsForProperty(property)) { errors.RegisterErrorMessage(validator.FriendlyName + "." + property, message); } } }
void IValidationPerformer.ExecuteContributors(object objectInstance, IEnumerable<IValidationContributor> contributors, ErrorSummary summaryToPopulate, RunWhen runWhen) { foreach (IValidationContributor contributor in contributors) { ErrorSummary errors = contributor.IsValid(objectInstance, runWhen); summaryToPopulate.RegisterErrorsFrom(errors); } }
/// <summary> /// associate error summary to the object instance /// </summary> /// <param name="objectInstance">object instance to associate validation error summary with</param> /// <param name="summary">error summary to be associated with object instance</param> protected void SetErrorSummaryForInstance(object objectInstance, ErrorSummary summary) { errorPerInstance[objectInstance] = summary; }
/// <summary> /// Determines whether the specified instance is valid. Returns an /// <see cref="ErrorSummary"/> that will be appended to the existing /// error summary for an object. /// </summary> /// <param name="instance">The instance.</param> /// <param name="runWhen">The run when.</param> /// <returns></returns> protected override ErrorSummary IsValidInternal(object instance, RunWhen runWhen) { ErrorSummary errorSummary = new ErrorSummary(); ArrayList methods = (ArrayList)methodsPerType[instance.GetType()]; if (methods == null) return errorSummary; foreach (SelfValidationMeta meta in methods) { if (!IsMetaOnPhase(meta, runWhen)) continue; MethodInfo methodInfo = meta.MethodInfo; methodInfo.Invoke(instance, new object[] {errorSummary}); } return errorSummary; }
/// <summary> /// Registers the errors from another error summary instance. /// </summary> /// <param name="errorSummary">The error summary.</param> public void RegisterErrorsFrom(ErrorSummary errorSummary) { foreach (string property in errorSummary.InvalidProperties) { foreach (string errorMessage in errorSummary.GetErrorsForProperty(property)) { RegisterErrorMessage(property, errorMessage); } } }
/// <summary> /// Initializes a new instance of the <see cref="MethodValidationException"/> class. /// </summary> /// <param name="message">The message.</param> /// <param name="errors">The errors.</param> public MethodValidationException(string message, ErrorSummary errors) : base(message, errors.ErrorMessages) { this.errors = errors; }
/// <summary> /// Determines whether the specified instance is valid. /// <para> /// All validators are run for the specified <see cref="RunWhen"/> phase. /// </para> /// </summary> /// <param name="objectInstance">The object instance to be validated (cannot be null).</param> /// <param name="runWhen">Restrict the set returned to the phase specified</param> /// <returns> /// <see langword="true"/> if the specified instance is valid; otherwise, <see langword="false"/>. /// </returns> public bool IsValid(object objectInstance, RunWhen runWhen) { if (objectInstance == null) throw new ArgumentNullException("objectInstance"); bool isValid; ErrorSummary summary = new ErrorSummary(); IValidator[] validators = GetValidators(objectInstance, runWhen); SortValidators(validators); isValid = validationPerformer.PerformValidation( objectInstance, validators, contributors, runWhen, summary); SetErrorSummaryForInstance(objectInstance, summary); return isValid; }
protected bool CheckForValidationFailures(object instance, Type instanceType, PropertyInfo prop, object value, string name, string prefix, ErrorSummary summary) { bool hasFailure = false; if (validator == null) { return false; } IValidator[] validators = validator.GetValidators(instanceType, prop); foreach(IValidator validatorItem in validators) { if (!validatorItem.IsValid(instance, value)) { string propName = validatorItem.FriendlyName ?? validatorItem.Name; errors.Add(new DataBindError(prefix, prop.Name, validatorItem.ErrorMessage)); summary.RegisterErrorMessage(propName, validatorItem.ErrorMessage); hasFailure = true; } } return hasFailure; }
/// <summary> /// Initializes a new instance of the <see cref="ValidationException"/> class. /// </summary> /// <param name="errorSummary">The error summary.</param> public ValidationException(ErrorSummary errorSummary) : base(GenerateMessage(errorSummary)) { this.errorSummary = errorSummary; }
protected void InternalRecursiveBindObjectInstance(object instance, String prefix, CompositeNode node) { if (node == null || instance == null) { return; } BeforeBinding(instance, prefix, node); if (PerformCustomBinding(instance, prefix, node)) { return; } PushInstance(instance, prefix); ErrorSummary summary = new ErrorSummary(); validationErrorSummaryPerInstance[instance] = summary; Type instanceType = instance.GetType(); PropertyInfo[] props = instanceType.GetProperties(PropertiesBindingFlags); string nodeFullName = node.FullName; foreach(PropertyInfo prop in props) { if (ShouldIgnoreProperty(prop, nodeFullName)) { continue; } Type propType = prop.PropertyType; String paramName = prop.Name; String translatedParamName = Translate(instanceType, paramName); if (translatedParamName == null) { continue; } bool isSimpleProperty = IsSimpleProperty(propType); // There are some caveats by running the validators here. // We should follow the validator's execution order... if (isSimpleProperty) { if (CheckForValidationFailures(instance, instanceType, prop, node, translatedParamName, prefix, summary)) { continue; } } BeforeBindingProperty(instance, prop, prefix, node); try { bool conversionSucceeded; if (isSimpleProperty) { object value = ConvertToSimpleValue(propType, translatedParamName, node, out conversionSucceeded); if (conversionSucceeded) { SetPropertyValue(instance, prop, value); } } else { // if the property is an object, we look if it is already instanciated object value = prop.GetValue(instance, null); Node nestedNode = node.GetChildNode(paramName); if (nestedNode != null) { if (ShouldRecreateInstance(value, propType, paramName, nestedNode)) { value = InternalBindObject(propType, paramName, nestedNode, out conversionSucceeded); if (conversionSucceeded) { SetPropertyValue(instance, prop, value); } } else { InternalRecursiveBindObjectInstance(value, paramName, nestedNode); } } CheckForValidationFailures(instance, instanceType, prop, value, translatedParamName, prefix, summary); } } catch(Exception ex) { errors.Add(new DataBindError(prefix, prop.Name, ex)); } } PopInstance(instance, prefix); AfterBinding(instance, prefix, node); }
/// <summary> /// Called when the validator finds an invalid method. /// </summary> /// <param name="method">The method.</param> /// <param name="errors">The errors.</param> protected virtual void OnInvalidMethod(MethodInfo method, ErrorSummary errors) { string errorMessage = BuildErrorMessage(method, errors); throw new ValidationException(errorMessage, errors.ErrorMessages); }
private void CreateErrorMessage(string message) { var errorSummary = new ErrorSummary(); errorSummary.RegisterErrorMessage(string.Empty, message); Flash["error"] = errorSummary; }
/// <summary> /// Determines whether the specified instance is valid. /// <para> /// All validators are run for the specified <see cref="RunWhen"/> phase. /// </para> /// </summary> /// <param name="objectInstance">The object instance to be validated (cannot be null).</param> /// <param name="runWhen">Restrict the set returned to the phase specified</param> /// <returns> /// <see langword="true"/> if the specified instance is valid; otherwise, <see langword="false"/>. /// </returns> public bool IsValid(object objectInstance, RunWhen runWhen) { if (objectInstance == null) throw new ArgumentNullException("objectInstance"); bool isValid; ErrorSummary summary = new ErrorSummary(); IEnumerable<IValidator> validators = GetValidators(objectInstance, runWhen); isValid = PerformValidation(objectInstance, validators, summary); return isValid; }
/// <summary> /// main validation logic happens here /// </summary> /// <param name="objectInstance">object instance to be validated</param> /// <param name="validators">the validators to run</param> /// <param name="summaryToPopulate"></param> protected virtual bool PerformValidation(object objectInstance, IEnumerable<IValidator> validators, ErrorSummary summaryToPopulate) { bool isValid = true; foreach (IValidator validator in validators) { if (!validator.IsValid(objectInstance)) { string name = validator.FriendlyName ?? validator.Name; summaryToPopulate.RegisterErrorMessage(name, validator.ErrorMessage); isValid = false; } } SetErrorSummaryForInstance(objectInstance, summaryToPopulate); return isValid; }
protected bool CheckForValidationFailures(object instance, Type instanceType, PropertyInfo prop, CompositeNode node, string name, string prefix, ErrorSummary summary) { object value = null; if (validator == null) { return false; } IValidator[] validators = validator.GetValidators(instanceType, prop); if (validators.Length != 0) { Node valNode = node.GetChildNode(name); if (valNode != null && valNode.NodeType == NodeType.Leaf) { value = ((LeafNode)valNode).Value; } if (value == null && IsDateTimeType(prop.PropertyType)) { bool conversionSucceeded; value = TryGetDateWithUTCFormat(node, name, out conversionSucceeded); } if (value == null && valNode == null) { // Value was not present on the data source. Skip validation return false; } } return CheckForValidationFailures(instance, instanceType, prop, value, name, prefix, summary); }
/// <summary> /// Appends the error to the <see cref="ErrorSummary">ErrorSummary</see>. /// </summary> /// <param name="validator">The validator.</param> /// <param name="errors">The errors.</param> protected virtual void AppendError(IValidator validator, ErrorSummary errors) { string name = validator.FriendlyName ?? validator.Name; ObjectValidator objectValidator = validator as ObjectValidator; if (objectValidator != null) RegisterObjectValidatorErrorMessages(objectValidator, errors); else errors.RegisterErrorMessage(name, validator.ErrorMessage); }
bool IValidationPerformer.PerformValidation(object objectInstance, IEnumerable <IValidator> validators, IEnumerable <IValidationContributor> contributors, RunWhen runWhen, ErrorSummary summaryToPopulate) { foreach (IValidator validator in validators) { if (!validator.IsValid(objectInstance)) { string name = validator.FriendlyName ?? validator.Name; summaryToPopulate.RegisterErrorMessage(name, validator.ErrorMessage); } } if (contributors != null) { (this as IValidationPerformer).ExecuteContributors(objectInstance, contributors, summaryToPopulate, runWhen); } bool isValid = !summaryToPopulate.HasError; return(isValid); }
void IValidationPerformer.ExecuteContributors(object objectInstance, IEnumerable <IValidationContributor> contributors, ErrorSummary summaryToPopulate, RunWhen runWhen) { foreach (IValidationContributor contributor in contributors) { ErrorSummary errors = contributor.IsValid(objectInstance, runWhen); summaryToPopulate.RegisterErrorsFrom(errors); } }
/// <summary> /// Populates the validator error summary with errors relative to the /// validation rules associated with the target type. /// </summary> /// <param name="instance">The instance.</param> /// <param name="binderUsedForBinding">The binder used for binding.</param> public void PopulateValidatorErrorSummary(object instance, ErrorSummary binderUsedForBinding) { if (validationSummaryPerInstance == null) { validationSummaryPerInstance = new Dictionary<object, ErrorSummary>(); } validationSummaryPerInstance[instance] = binderUsedForBinding; }
/// <summary> /// Validate method parameters that are decorated with the params keyword. /// </summary> /// <param name="validator">The validator.</param> /// <param name="propertyAccessAware">The property access aware.</param> /// <param name="value">The value.</param> /// <param name="errors">The errors.</param> private void ValidateParamsArray(IValidator validator, IPropertyAccessAware propertyAccessAware, object value, ErrorSummary errors) { object[] paramsValue = (object[]) value; foreach (object paramValue in paramsValue) { propertyAccessAware.PropertyAccessor = delegate { return paramValue; }; if (validator.IsValid(paramValue)) continue; AppendError(validator, errors); } }