public static ValidationErrorDto ShouldHaveFailureNumber(
     this ValidationErrorDto validationError,
     int expectedFailureNumber)
 {
     Assert.That(validationError.Failures, Has.Count.EqualTo(expectedFailureNumber));
     return(validationError);
 }
Beispiel #2
0
        public void Deserialize_NoArguments_DeserializesAsExpected()
        {
            // Arrange
            var validationErrorResponse = ValidationErrorDto.CreateStandard("Foo validation error");

            validationErrorResponse.Failures = new Dictionary <string, ValidationFailureDto>
            {
                { "age", new ValidationFailureDto("bad_age", "Age must be positive") },
            };

            validationErrorResponse.AddFailure("weight", "bad_weight", "Too thin");

            // Act
            var json         = JsonConvert.SerializeObject(validationErrorResponse);
            var deserialized = JsonConvert.DeserializeObject <ValidationErrorDto>(json);

            // Assert
            Assert.That(deserialized.Code, Is.EqualTo("ValidationError"));
            Assert.That(deserialized.Message, Is.EqualTo("Foo validation error"));

            var error = deserialized.Failures["age"];

            Assert.That(error.Code, Is.EqualTo("bad_age"));
            Assert.That(error.Message, Is.EqualTo("Age must be positive"));

            error = deserialized.Failures["weight"];
            Assert.That(error.Code, Is.EqualTo("bad_weight"));
            Assert.That(error.Message, Is.EqualTo("Too thin"));
        }
 internal static ValidationErrorDto ShouldHaveFailureNumber(
     this ValidationErrorDto validationError,
     int failureNumber)
 {
     Assert.That(validationError.Failures, Has.Count.EqualTo(failureNumber));
     return(validationError);
 }
        public static ValidationErrorDto ShouldContainFailure(
            this ValidationErrorDto validationError,
            string expectedKey,
            string expectedCode,
            string expectedMessage)
        {
            Assert.That(validationError.Failures, Does.ContainKey(expectedKey));
            var failure = validationError.Failures[expectedKey];

            Assert.That(failure.Code, Is.EqualTo(expectedCode));
            Assert.That(failure.Message, Is.EqualTo(expectedMessage));

            return(validationError);
        }
        internal static ValidationErrorDto ShouldContainFailure(
            this ValidationErrorDto validationError,
            string key,
            string code,
            string message)
        {
            Assert.That(validationError.Failures, Does.ContainKey(key));
            var failure = validationError.Failures[key];

            Assert.That(failure.Code, Is.EqualTo(code));
            Assert.That(failure.Message, Is.EqualTo(message));

            return(validationError);
        }
        public IActionResult PostReturnsValidationError(
            [FromQuery] string desiredCode,
            [FromQuery] string desiredMessage)
        {
            this.Response.Headers.Add(DtoHelper.PayloadTypeHeaderName, DtoHelper.ValidationErrorPayloadType);

            var validationError = new ValidationErrorDto
            {
                Code     = desiredCode,
                Message  = desiredMessage,
                Failures = new Dictionary <string, ValidationFailureDto>
                {
                    {
                        "name",
                        new ValidationFailureDto
                        {
                            Code    = "NameValidator",
                            Message = "Name is bad."
                        }
                    },
                    {
                        "salary",
                        new ValidationFailureDto
                        {
                            Code    = "SalaryValidator",
                            Message = "Salary is low.",
                        }
                    }
                },
            };

            var json = JsonConvert.SerializeObject(validationError);

            return(new ContentResult
            {
                StatusCode = (int)HttpStatusCode.BadRequest,
                Content = json,
                ContentType = "application/json",
            });
        }
Beispiel #7
0
        public static ErrorDto Map(Exception ex)
        {
            if (ex == null)
            {
                throw new ArgumentNullException(nameof(ex));
            }
            ErrorDto dto = new ErrorDto();

            switch (ex)
            {
            case ValidationException validation:
                dto = new ValidationErrorDto()
                {
                    ValidationSummary = validation.ValidationSummary,
                    Message           = validation.Message,
                    ValidationErrors  = validation.ValidationErrors.Select(x => new FieldErrorDto(FixFieldName(x.Field), x.ErrorsMessages)).ToArray()
                };
                break;

            case NotFoundException notfound:
                dto = new ErrorDto
                {
                    Code    = ReadableErrorCodes.NotFound,
                    Message = notfound.Message
                };
                break;

            default:
            {
                dto = new ErrorDto()
                {
                    Code    = ReadableErrorCodes.ServerFatal,
                    Message = ex.Message
                };
            }
            break;
            }
            return(dto);
        }
        internal static ValidationErrorDto CreateValidationErrorDto(string message, IEnumerable <ValidationFailure> failures)
        {
            if (failures == null)
            {
                throw new ArgumentNullException(nameof(failures));
            }

            var validationError = ValidationErrorDto.CreateStandard(message);

            foreach (var validationFailure in failures)
            {
                // Make sure that all the property names are camel cased
                var propertyName = EnsurePropertyNameIsCamelCase(validationFailure.PropertyName);

                // Only add the first validation message for a property
                if (!validationError.Failures.ContainsKey(propertyName))
                {
                    validationError.AddFailure(propertyName, validationFailure.ErrorCode, validationFailure.ErrorMessage);
                }
            }

            return(validationError);
        }
Beispiel #9
0
 public BadRequestException(ValidationErrorDto errorsDto)
 {
     this.ErrorsDto = errorsDto;
 }
Beispiel #10
0
        public override void OnActionExecuting(ActionExecutingContext actionContext)
        {
            ValidationErrorDto validationError = null;

            // Verify that the model state is valid before running the argument value specific validators.
            if (!actionContext.ModelState.IsValid)
            {
                // Prepare the validation error response
                validationError = ValidationErrorDto.CreateStandard();

                foreach (var fieldState in actionContext.ModelState)
                {
                    // Make sure that all the property names are camel cased and remove all model prefixes
                    var fieldName = WebApiHostHelper.EnsurePropertyNameIsCamelCase(
                        Regex.Replace(fieldState.Key, @"^(.*?\.)(.*)", "$2"));

                    // Get only the first error, the rest will be skipped
                    var error = fieldState.Value.Errors.First();

                    // Create the error message
                    var errorMessage = "Unknown error.";
                    if (!string.IsNullOrEmpty(error.ErrorMessage))
                    {
                        errorMessage = error.ErrorMessage;
                    }
                    else if (!string.IsNullOrEmpty(error.Exception?.Message))
                    {
                        errorMessage = error.Exception.Message;
                    }

                    // Add the error to the response, with an empty error code, since this is an unspecific error
                    validationError.AddFailure(fieldName, null, errorMessage);
                }
            }

            // Validate all the arguments for the current action
            foreach (var argument in actionContext.ActionDescriptor./*GetParameters()*/ Parameters)
            {
                // Skip all arguments without a registered validator
                _validatorTypes.TryGetValue(argument.ParameterType, out var validatorType);
                if (validatorType == null)
                {
                    continue;
                }

                // Get the registered validator
                var validator = (IValidator)actionContext.HttpContext.RequestServices.GetService(validatorType);

                if (validator == null)
                {
                    continue; // could not resolve validator
                }

                // Inject the action arguments into the validator, so that they can be used in the validation
                // This is a "hack" to, amongst other, support unique validation on the update commands where the resource id is needed to exclude itself from the unique check.
                if (validator is IParameterValidator)
                {
                    ((IParameterValidator)validator).Parameters = actionContext.ActionArguments;
                }

                // Validate the argument
                var argumentValue = actionContext.ActionArguments[argument.Name];

                if (argumentValue == null)
                {
                    validationError = ValidationErrorDto.CreateStandard($"Argument '{argument.Name}' is null");
                    break;
                }

                var validationResult = validator.Validate(argumentValue);

                // Return if the argument value was valid
                if (validationResult.IsValid)
                {
                    continue;
                }

                // Create an validation error response, if it does not already exist
                if (validationError == null)
                {
                    validationError = ValidationErrorDto.CreateStandard();
                }

                // Add every field specific error to validation error response
                foreach (var validationFailure in validationResult.Errors)
                {
                    // Make sure that all the property names are camel cased
                    var propertyName = WebApiHostHelper.EnsurePropertyNameIsCamelCase(validationFailure.PropertyName);

                    // Only add the first validation message for a property
                    if (!validationError.Failures.ContainsKey(propertyName))
                    {
                        validationError.AddFailure(propertyName, validationFailure.ErrorCode, validationFailure.ErrorMessage);
                    }
                }
            }

            if (validationError != null)
            {
                actionContext.Result = new ContentResult
                {
                    StatusCode  = StatusCodes.Status400BadRequest,
                    ContentType = "application/json",
                    Content     = JsonConvert.SerializeObject(validationError),
                };

                // Set the action response to a 400 Bad Request, with the validation error response as content
                actionContext.HttpContext.Response.Headers.Add(DtoHelper.PayloadTypeHeaderName, DtoHelper.ValidationErrorPayloadType);
            }
        }