The main use of this packages is to configure the use of FluentValidation within our API services.
Fluent Validation allows you to separate validation rules from your object model and helps you structure the rules so that they are nice and readable. The rules are also super easy to test.
The UseErrorCodeInterceptor
class is used under the covers to make sure that any error code that is specified on a validation rule is actually included in the HTTP response.
By default it just includes the error message and any code specified is left out.
Clients should not need to invoke this class directly.
Simply use the WithErrorCode()
method as normal and the specified code will now appear in the Http response.
RuleFor(x => x.ReasonForTermination).NotXssString()
.WithErrorCode(ErrorCodes.XssCheckFailure);
This class provides extension methods that are used in application startup to ensure that all the required validators
are registered with MVC and will be used when appropriate. It also registers the UseErrorCodeInterceptor
class.
public void ConfigureServices(IServiceCollection services)
{
...
// This example will register any validators just in the application's assembly
services.AddFluentValidation();
// This example will register any validators in the assembly where the CreatePersonRequestObjectValidator is located
// (but not the local assembly - if you need that then add it specifically.)
services.AddFluentValidation(Assembly.GetAssembly(typeof(CreatePersonRequestObjectValidator)));
...
}
Sometimes validation has to be performed manually (as opposed to the MVC pipeline performing it automatically when an endpoint is hit), and in these cases a response object should be returned that has the same format as that generated by the automatic processing.
This class provides extension methods that are used to create a response object in this case.
using FluentValidation;
using Hackney.Core.Validation.AspNet;
public class SomeController : Controller
{
...
[HttpPost]
public async Task<IActionResult> CreateEntity([FromBody] CreateEntityRequestObject request)
{
try
{
var result = await _createEntityUseCase.ExecuteAsync(request).ConfigureAwait(false);
return Created("api/v2/entityDetails", result);
}
catch (ValidationException e)
{
// Construct a BadRequest with a response object generated from the exception
return BadRequest(e.ConstructResponse());
}
}
}
using FluentValidation;
using Hackney.Core.Validation.AspNet;
public class SomeController : Controller
{
...
[HttpPost]
public async Task<IActionResult> CreateEntity([FromBody] CreateEntityRequestObject request)
{
var validationResult = DoSomeCustomValidation(request);
if (!validationResult.IsValid)
// Construct a BadRequest with from the validation response object
return BadRequest(validationResult.ConstructResponse());
var result = await _createEntityUseCase.ExecuteAsync(request).ConfigureAwait(false);
return Created("api/v2/entityDetails", result);
}
public async ValidationResult DoSomeCustomValidation(CreateOtherEntityRequestObject request)
{
SomeTestObject testObject = new SomeTestObject(request);
SomeValidator validator = new SomeValidator();
return validator.Validate(testObject);
}
}