Skip to main content

BadRequestException

Namespace: RA.Utilities.Core.Exceptions

BadRequestException represents a failure caused by invalid client-side input. The API layer maps it to HTTP 400 Bad Request.

🎯 Purpose​

This is the primary tool for validation errors discovered inside business logic (for example, in a CQRS handler or application service). Instead of a generic exception with a single string, BadRequestException carries a structured array of ValidationError items so the client can see exactly which fields failed and why.

Use it when the request itself is invalid. When the request is well formed but the resource state prevents the operation, use UnprocessableException instead.

Properties​

PropertyTypeDescription
ErrorsValidationError[]The validation failures that caused the exception.
ErrorCodeintInherited. 400 unless supplied explicitly.
ResponseTypeResponseTypeInherited. ResponseType.BadRequest.
MessagestringInherited. BaseResponseMessages.BadRequest ("The request is invalid.") unless supplied explicitly.

Each ValidationError exposes PropertyName, ErrorMessage, AttemptedValue, ExpectedValue, and a custom ErrorCode.

Constructors​

ConstructorErrorCodeMessage
BadRequestException(ValidationError error)400BaseResponseMessages.BadRequest
BadRequestException(ValidationError error, int errorCode, string? message = null)suppliedsupplied, or BaseResponseMessages.BadRequest when null/omitted
BadRequestException(ValidationError[] errors)400BaseResponseMessages.BadRequest
BadRequestException(ValidationError[] errors, int errorCode, string? message = null)suppliedsupplied, or BaseResponseMessages.BadRequest when null/omitted

There is no message-only constructor: a ValidationError is always required.

🚀 How to Use​

Example: Using with FluentValidation​

Catch a FluentValidation ValidationException and convert its failures into ValidationError items:

using FluentValidation;
using RA.Utilities.Core.Results;
using RA.Utilities.Core.Exceptions;

public async Task<Result<UserDto>> CreateUserAsync(CreateUserCommand command)
{
try
{
await _validator.ValidateAndThrowAsync(command);
}
catch (ValidationException ex)
{
ValidationError[] validationErrors = [.. ex.Errors.Select(e => new ValidationError(e.ErrorMessage)
{
PropertyName = e.PropertyName,
AttemptedValue = e.AttemptedValue,
ErrorCode = e.ErrorCode
})];

return new BadRequestException(validationErrors);
}

// ... continue with user creation logic if validation passes
}

Example: A single validation error​

using RA.Utilities.Core.Constants;
using RA.Utilities.Core.Exceptions;

if (string.IsNullOrWhiteSpace(request.Email))
{
throw new BadRequestException(new ValidationError(BaseErrorMessage.EmailRequired)
{
PropertyName = "Email",
ErrorCode = BaseErrorCode.EmailRequired
});
}

Example: Attach a request-level code and message​

return new BadRequestException(
errors: validationErrors,
errorCode: 4001,
message: "The registration form is invalid."
);

🔗 HTTP mapping​

ErrorResultResponse maps BadRequestException to HTTP 400 with a BadRequestResponse whose result is an array of the exception's Errors. The ErrorCode is echoed into responseCode; it does not change the HTTP status.

See BadRequestResponse for the exact JSON shape and the ValidationError reference for each item's fields.