Overview
Silky has a built-in parameter validation mechanism that automatically validates service entry input parameters during RPC communication. Two validation approaches are supported:
| Approach | NuGet Package | Notes |
|---|---|---|
| DataAnnotations | Silky.Core (built-in) | Standard .NET System.ComponentModel.DataAnnotations attributes |
| FluentValidation | Silky.Validation.Fluent | Complex validation rules with a fluent DSL |
Validation failures throw a ValidationException — HTTP status code 400 Bad Request.
DataAnnotations Validation
Annotate DTO properties directly:
public class CreateOrderInput
{
[Required(ErrorMessage = "Product ID is required")]
public long ProductId { get; set; }
[Range(1, 9999, ErrorMessage = "Quantity must be between 1 and 9999")]
public int Quantity { get; set; }
[Required(ErrorMessage = "Shipping address is required")]
[MaxLength(200, ErrorMessage = "Address cannot exceed 200 characters")]
public string Address { get; set; }
[Phone(ErrorMessage = "Invalid phone number format")]
public string Phone { get; set; }
}
Use the DTO in the service interface — validation runs automatically before the method executes:
[ServiceRoute]
public interface IOrderAppService
{
Task<OrderOutput> CreateOrderAsync(CreateOrderInput input);
}
FluentValidation
For complex validation rules, FluentValidation provides a powerful DSL.
Installation
PM> Install-Package Silky.Validation.Fluent -Version 3.9.2
Define a Validator
Inherit from AbstractValidator<T> and implement IScopedDependency (auto-registered by the framework):
using FluentValidation;
using Silky.Core.DependencyInjection;
public class CreateOrderInputValidator : AbstractValidator<CreateOrderInput>, IScopedDependency
{
public CreateOrderInputValidator()
{
RuleFor(x => x.ProductId)
.GreaterThan(0).WithMessage("Product ID must be greater than 0");
RuleFor(x => x.Quantity)
.InclusiveBetween(1, 9999).WithMessage("Quantity must be between 1 and 9999");
RuleFor(x => x.Address)
.NotEmpty().WithMessage("Shipping address is required")
.MaximumLength(200).WithMessage("Address cannot exceed 200 characters");
RuleFor(x => x.Phone)
.Matches(@"^\+?[1-9]\d{7,14}$").WithMessage("Invalid phone number format");
}
}
No manual registration needed — Silky detects IScopedDependency and registers the validator automatically.
Enable FluentValidation Module
[DependsOn(
typeof(FluentValidationModule),
typeof(DotNettyTcpModule)
)]
public class CustomHostModule : GeneralHostModule { }
Validation Error Response
When validation fails, the framework returns a structured error response:
{
"code": 400,
"message": "Validation failed",
"errors": [
{ "field": "ProductId", "message": "Product ID must be greater than 0" },
{ "field": "Quantity", "message": "Quantity must be between 1 and 9999" }
]
}
Combining Both Approaches
DataAnnotations and FluentValidation can be used together. Both run before the method executes, and all validation errors are collected and returned in a single response.
