public void HandleComponentModelValidationException(ComponentModelValidationException exception, ExceptionContext context) { foreach (var key in exception.ValidationResult.MemberNames) { context.ModelState.TryAddModelException(key, exception); } var details = new ValidationProblemDetails(context.ModelState); context.Result = new BadRequestObjectResult(details); context.ExceptionHandled = true; }
public void GivenValidationExceptions_WhenMapped_ThenReturnsBadRequestHttpStatusWithProperMessage() { //Given const string message = "Message"; var fluentValidationException = new ValidationException(message); var dataAnnotationsException = new System.ComponentModel.DataAnnotations.ValidationException(message); var exceptions = new Exception[] { fluentValidationException, dataAnnotationsException }; foreach (var validationException in exceptions) { //When var codeInfo = ExceptionToHttpStatusMapper.Map(fluentValidationException); //Then codeInfo.Code.Should().Be(HttpStatusCode.BadRequest); codeInfo.Message.Should().Be(message); } }
public async Task AsHttpResponseData_ContentTypeIsJson_ReturnsResponseSerializedAsJson() { // arrange const string expectedXml = "{\"error\":{\"code\":\"VALIDATION_EXCEPTION\",\"message\":\"BundleIdAlreadyInUse\"}}"; var request = new MockedHttpRequestData(new MockedFunctionContext()); request.HttpRequestDataMock.Setup(x => x.Headers).Returns(new Microsoft.Azure.Functions.Worker.Http.HttpHeadersCollection( new[] { new KeyValuePair <string, IEnumerable <string> >(HeaderNames.ContentType, new[] { MediaTypeNames.Application.Json }) })); const string validationErrorMessage = nameof(BundleCreatedResponse.BundleIdAlreadyInUse); var exception = new System.ComponentModel.DataAnnotations.ValidationException(validationErrorMessage); // act var actual = await exception.AsHttpResponseDataAsync(request.HttpRequestData).ConfigureAwait(false); var content = Encoding.UTF8.GetString(((MemoryStream)actual.Body).ToArray()); // assert Assert.Equal(expectedXml, content); }
public static ExceptionModel ToHttpException(this Exception e) { return(e switch { FluentValidation.ValidationException exception => new ValidationExceptionModel { Message = e.Message, InnerException = e?.InnerException?.ToHttpException(), StackTrace = e.StackTrace, ValidationErrors = exception.Errors.Select(x => new ValidationErrorModel { Message = x.ErrorMessage, PropertyName = x.PropertyName, AttemptedValue = x.AttemptedValue, ErrorCode = x.ErrorCode }) .ToList() }, System.ComponentModel.DataAnnotations.ValidationException exception => new ValidationExceptionModel() { Message = e.Message, InnerException = e?.InnerException?.ToHttpException(), StackTrace = e.StackTrace, ValidationErrors = exception?.ValidationResult?.MemberNames?.Select(x => new ValidationErrorModel { Message = (e as System.ComponentModel.DataAnnotations.ValidationException) ?.ValidationResult?.ErrorMessage ?? String.Empty, PropertyName = x }) ?.ToList() }, _ => new ExceptionModel { Message = e.Message, InnerException = e?.InnerException?.ToHttpException(), StackTrace = e.StackTrace } });
public static HttpStatusCodeInfo Map(Exception exception) { if (CustomMaps.ContainsKey(exception.GetType())) { return(CustomMaps[exception.GetType()](exception)); } var code = exception switch { ValidationException _ => HttpStatusCode.BadRequest, System.ComponentModel.DataAnnotations.ValidationException _ => HttpStatusCode.BadRequest, ArgumentException _ => HttpStatusCode.BadRequest, UnauthorizedAccessException _ => HttpStatusCode.Unauthorized, InvalidOperationException _ => HttpStatusCode.Forbidden, NotFoundException _ => HttpStatusCode.NotFound, OptimisticConcurrencyException _ => HttpStatusCode.Conflict, NotImplementedException _ => HttpStatusCode.NotImplemented, _ => HttpStatusCode.InternalServerError }; return(new HttpStatusCodeInfo(code, exception.Message)); }
public async Task AsHttpResponseData_ExceptionIsDataAnnotationException_ReturnsResponseWithGenericErrorAndStatusValidationError() { // arrange var request = new MockedHttpRequestData(new MockedFunctionContext()); const string validationErrorMessage = nameof(BundleCreatedResponse.BundleIdAlreadyInUse); var exception = new System.ComponentModel.DataAnnotations.ValidationException(validationErrorMessage); // act var actual = await exception.AsHttpResponseDataAsync(request.HttpRequestData).ConfigureAwait(false); var actualFunctionError = JsonSerializer.Deserialize <ErrorResponse>( ((MemoryStream)actual.Body).ToArray(), new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }) !; var error = actualFunctionError.Error; // assert Assert.Equal(HttpStatusCode.BadRequest, actual.StatusCode); Assert.Equal("VALIDATION_EXCEPTION", error.Code); Assert.Equal(nameof(BundleCreatedResponse.BundleIdAlreadyInUse), error.Message); Assert.Null(error.Target); Assert.Null(error.Details); }
/// <summary> /// Given a <see cref="System.ComponentModel.DataAnnotations.ValidationException"/> will convert it to an /// equivalent <see cref="ValidationFailedOperationResult" /> to be output to the user. /// </summary> /// <param name="validationException">The exception to be converted.</param> /// <returns>The response to send back to the client.</returns> // ReSharper disable once MemberCanBePrivate.Global This is used in generated code public static ValidationFailedOperationResult ToValidationFailedOperationResult(System.ComponentModel.DataAnnotations.ValidationException validationException) { var validationResult = validationException.ValidationResult; if (!validationResult.MemberNames.Any()) { return(new ValidationFailedOperationResult(validationResult.ErrorMessage)); } var errorMessages = (IEnumerable <string>) new[] { validationResult.ErrorMessage }; return(new ValidationFailedOperationResult(validationResult.MemberNames.ToDictionary(m => m, m => errorMessages))); }