Skip to content

The search box in the website knows all the secrets—try it!

For any queries, join our Discord Channel to reach us faster.

JasperFx Logo

JasperFx provides formal support for Wolverine and other JasperFx libraries. Please check our Support Plans for more details.

DataAnnotations Validation Middleware

TIP

There is also an HTTP specific middleware for WolverineFx.Http that uses the ProblemDetails specification. See DataAnnotations Validation Middleware for HTTP for more information.

WARNING

While it is possible to access the IoC Services via ValidationContext, we recommend instead using a more explicit Validate or ValidateAsync() method directly in your message handler class for the data input.

For simple input validation of your messages, the Data Annotation Attributes are a good choice. The WolverineFx.DataAnnotationsValidation nuget package will add support for the built-in and custom attributes via middleware that will stop invalid messages from reaching the message handlers.

To get started, add the nuget package and configure your Wolverine Application:

cs
using var host = await Host.CreateDefaultBuilder()
    .UseWolverine(opts =>
    {
        // Apply the validation middleware
        opts.UseDataAnnotationsValidation();
    }).StartAsync();

snippet source | anchor

Now you can decorate your messages with the built-in or custom ValidationAttributes:

cs
public record CreateCustomer(
    // you can use the attributes on a record, but you need to
    // add the `property` modifier to the attribute
    [property: Required] string FirstName,
    [property: MinLength(5)] string LastName,
    [property: PostalCodeValidator] string PostalCode
) : IValidatableObject
{
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        // you can implement `IValidatableObject` for custom
        // validation logic
        yield break;
    }
};

public class PostalCodeValidatorAttribute : ValidationAttribute
{
    public override bool IsValid(object? value)
    {
        // custom attributes are supported
        return true;
    }
}

public static class CreateCustomerHandler
{
    public static void Handle(CreateCustomer customer)
    {
        // do whatever you'd do here, but this won't be called
        // at all if the DataAnnotations Validation rules fail
    }
}

snippet source | anchor

In the case above, the Validation check will happen at runtime before the call to the handler methods. If the validation fails, the middleware will throw a ValidationException and stop all processing.

Some notes about the middleware:

  • The middleware is applied to all message handler types as there is no easy way of knowing if a message has some sort of validation attribute defined.
  • The registration also adds an error handling policy to discard messages when a ValidationException is thrown

Customizing the Validation Failure Behavior

Out of the box, the Fluent Validation middleware will throw a DataAnnotationsValidation.ValidationException with all the validation failures if the validation fails. To customize that behavior, you can plug in a custom implementation of the IFailureAction<T> interface. This behaves exactly the same as the Fluent Validation Customisation.

Released under the MIT License.