Persilsoft.ValidationService.FluentValidation
1.0.5
dotnet add package Persilsoft.ValidationService.FluentValidation --version 1.0.5
NuGet\Install-Package Persilsoft.ValidationService.FluentValidation -Version 1.0.5
<PackageReference Include="Persilsoft.ValidationService.FluentValidation" Version="1.0.5" />
paket add Persilsoft.ValidationService.FluentValidation --version 1.0.5
#r "nuget: Persilsoft.ValidationService.FluentValidation, 1.0.5"
// Install Persilsoft.ValidationService.FluentValidation as a Cake Addin #addin nuget:?package=Persilsoft.ValidationService.FluentValidation&version=1.0.5 // Install Persilsoft.ValidationService.FluentValidation as a Cake Tool #tool nuget:?package=Persilsoft.ValidationService.FluentValidation&version=1.0.5
Persilsoft.ValidationService.FluentValidation
An implementation of Persilsoft.Validation using FluentValidation.
Example
Let's start by creating a class to register an order with its details.
public class CreateOrderDto(string customerId, string shipAddress, string shipPostalCode, IEnumerable<CreateOrderDetailDto> orderDetails)
{
public string CustomerId => customerId;
public string ShipAddress => shipAddress;
public string ShipPostalCode => shipPostalCode;
public IEnumerable<CreateOrderDetailDto> OrderDetails => orderDetails;
}
public class CreateOrderDetailDto(int productId, decimal unitPrice, short quantity)
{
public int ProductId => productId;
public decimal UnitPrice => unitPrice;
public short Quantity => quantity;
}
Now, let's implement validators for each model.
using Persilsoft.Validation.Abstracts;
using Persilsoft.Validation.Interfaces;
public class CreateOrderDtoValidator : AbstractModelValidator<CreateOrderDto>
{
public CreateOrderDtoValidator(IValidationService<CreateOrderDto> validationService,
IModelValidator<CreateOrderDetailDto> detailValidator)
: base(validationService)
{
AddRuleFor(dto => dto.CustomerId)
.NotEmpty("Customer Id is required.")
.Length(7, "Customer Id must have 7 characters.");
AddRuleFor(dto => dto.ShipAddress)
.NotEmpty("Ship address is required.")
.MinimumLength(20, "Ship address must have a minimum lenght of 20 characters.")
.MaximumLength(50, "Ship address must have a maximum lenght of 50 characters.");
AddRuleFor(dto => dto.ShipPostalCode)
.NotEmpty("Ship postal code is required")
.Length(5, "Ship postal code must have 5 characters.");
AddRuleFor(dto => dto.OrderDetails)
.NotNull("Order details is required.")
.NotNull("Order details must not be empty");
AddRuleForEach(dto => dto.OrderDetails)
.SetValidator(detailValidator);
}
}
using Persilsoft.Validation.Abstracts;
using Persilsoft.Validation.Interfaces;
internal class CreateOrderDetailDtoValidator :
AbstractModelValidator<CreateOrderDetailDto>
{
public CreateOrderDetailDtoValidator(IValidationService<CreateOrderDetailDto> validationService)
: base(validationService)
{
AddRuleFor(d => d.ProductId)
.GreaterThan(0, "Product Id must be greater than 0.");
AddRuleFor<int>(d => d.Quantity)
.GreaterThan(0, "Quantity must be greater than 0.");
AddRuleFor(d => d.UnitPrice)
.GreaterThan<decimal>(0, "Unit price must be greater than 0.");
}
}
Next, let's register the validators and the validation service.
using ServiceCollectionExtensions;
builder.Services.AddModelValidator<CreateOrderDto, CreateOrderDtoValidator>();
builder.Services.AddModelValidator<CreateOrderDetailDto, CreateOrderDetailDtoValidator>();
builder.Services.AddValidationService();
Now, let's implement an Endpoint that receives the model, and we'll inject the validation hub for the model.
using Persilsoft.Exceptions.CustomExceptions;
using Persilsoft.Validation.Interfaces;
app.MapPost("/order/register", async (CreateOrderDto order, IModelValidatorHub<CreateOrderDto> modelValidatorHub) =>
{
if (!await modelValidatorHub.Validate(order))
throw new ValidationException(modelValidatorHub.Errors);
Console.WriteLine("Sending the new order to the Database");
await Task.Delay(750);
return Results.Ok("Order registered!");
})
.WithName("Order");
Note:
You can use constructor injection.
You can implement a custom exception handler to handle the ValidationException and format the output appropriately, or you can include the Persilsoft.Exceptions package, which already includes a ready-to-use handler.
using ServiceCollectionExtensions;
builder.Services.AddValidationExceptionHandler();
If you will use the Persilsoft.Exceptions handler, it will be necessary to configure the Localization middleware in your AspNet Core application.
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
var SupportedCultures = new[] { "en-US", "es-PE" };
var NeutralCulture = SupportedCultures[1];
options.SetDefaultCulture(NeutralCulture)
.AddSupportedCultures(SupportedCultures)6
.AddSupportedUICultures(SupportedCultures);
});
Finally, we add the localization and exception handling middlewares to the AspNet Core pipeline
app.UseRequestLocalization();
app.UseExceptionHandler(e => { });
Note:
It's important that the localization middleware is added before the exception handling middleware; otherwise, you won't see the messages in the appropriate language.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- FluentValidation (= 11.9.2)
- Persilsoft.Validation (= 1.0.3)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Persilsoft.ValidationService.FluentValidation:
Package | Downloads |
---|---|
Persilsoft.Membership.Backend.IoC
Package Description |
|
Persilsoft.Membership.Blazor
Contains razor clases for use in frontend membership projects |
GitHub repositories
This package is not used by any popular GitHub repositories.