/// <summary> /// Validates instance using DataAnnotations. /// </summary> /// <param name="instance">Validated instance.</param> /// <returns><see cref="FailedResult"/> if invalid, otherwise <see cref="SuccessfulResult"/>.</returns> public static IExecutionResult Validate(object instance) { if (instance == null) { return(new SuccessfulResult()); } var validationContext = new ValidationContext(instance); var executionErrors = new List <ExecutionError>(); // Validate current level of the instance. CoreValidator.TryValidateObject(instance, validationContext, executionErrors, true); var instanceType = instance.GetType(); var result = new FailedResult(CoreErrorCodes.ValidationFailed, instanceType.Name); foreach (var executionError in executionErrors) { var field = executionError.Source ?? string.Empty; var source = $"{instanceType.Name}.{field}"; var error = new ExecutionError(executionError.CodeInfo, source); result.AddError(error); } // Recursively validate nested types. var properties = instanceType .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty) .Where(PropertyCanBeValidated); foreach (var property in properties) { var propertyValue = property.GetValue(instance); if (typeof(System.Collections.IEnumerable).IsAssignableFrom(property.PropertyType)) { UpdateFailedResultWithArrayElementsDetails(result, property, instanceType, propertyValue); continue; } var propertyResult = Validate(propertyValue); if (!(propertyResult is FailedResult fr)) { continue; } UpdateFailedResultWithDetails(result, fr, property, instanceType); } return(result.Details.Any() ? (IExecutionResult)result : new SuccessfulResult()); }
public void NotEmpty_ValidationFailed_ReturnsCorrectResult() { var expectedInvalidProperty = nameof(FakeInstance.Property); var expectedErrorMessage = string.Format(CultureInfo.InvariantCulture, NotEmptyAttribute.ErrorMessageTemplate, expectedInvalidProperty); var expectedErrorCodeInfo = new ErrorCodeInfo(AnnotationErrorCodes.NotEmpty.Code, expectedErrorMessage); var expectedExecutionError = new ExecutionError(expectedErrorCodeInfo, expectedInvalidProperty, expectedErrorMessage); var instance = new FakeInstance(); var context = new ValidationContext(instance); var errors = new List <ExecutionError>(); var isValid = CoreValidator.TryValidateObject(instance, context, errors, true); isValid.Should().BeFalse(); errors.Single().Should().BeEquivalentTo(expectedExecutionError); }