Data annotation validation for gRPC Code-First models in ASP.NET Core. Automatically validates request messages using System.ComponentModel.DataAnnotations attributes and returns structured validation errors via gRPC trailers. Optionally validate required reference type properties on request models.
| Package | Description |
|---|---|
| Codify.GrpcCodeFirstDataAnnotations | Server-side interceptor that validates incoming gRPC requests |
| Codify.GrpcCodeFirstDataAnnotations.Exceptions | Client-side helper to read validation errors from gRPC RpcException trailers |
- Install the NuGet package:
dotnet add package Codify.GrpcCodeFirstDataAnnotations- Register services and enable the validation interceptor:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpcDataAnnotationValidation();
builder.Services.AddCodeFirstGrpc(options =>
{
options.EnableDataAnnotationValidation();
});Optionally configure the validation behavior:
builder.Services.Configure<GrpcDataAnnotationValidationOptions>(options =>
{
// In addition to DataAnnotations attributes, also validate `required` nullable reference type properties
options.ValidateRequiredNullableProperties = true;
// Log validation failures at Warning level
options.ValidationFailureLogLevel = LogLevel.Warning;
});- Add
DataAnnotationsattributes to your request models:
[DataContract]
public class CreatePersonRequest
{
[DataMember(Order = 1)]
[Required]
[StringLength(50)]
public string FirstName { get; set; }
[DataMember(Order = 2)]
[Required]
[EmailAddress]
public string Email { get; set; }
[DataMember(Order = 3)]
[Range(1, 120)]
public int Age { get; set; }
[DataMember(Order = 4)]
[Range(typeof(TimeSpan), "00:30:00", "08:00:00")]
public TimeSpan SessionDuration { get; set; }
[DataMember(Order = 5)]
// This property will be validated as well if `ValidateRequiredNullableProperties` is enabled, even without DataAnnotations attributes
public required string Job { get; set; }
}When a request fails validation, the interceptor throws an RpcException with StatusCode.InvalidArgument and includes the validation errors as Base64-encoded JSON in the gRPC trailers.
- Install the client package:
dotnet add package Codify.GrpcCodeFirstDataAnnotations.Exceptions- Catch and read validation errors:
try
{
var response = await client.CreatePersonAsync(request);
}
catch (RpcException ex)
{
var errors = ex.GetValidationErrors();
foreach (var error in errors)
{
Console.WriteLine($"{string.Join(", ", error.PropertyNames)}: {error.ErrorMessage}");
}
}Implement IDataAnnotationsResultHandler to customize how validation failures are processed:
public class MyCustomHandler : IDataAnnotationsResultHandler
{
public Task<DataAnnotationValidationResult> HandleAsync(IList<ValidationResult> failures)
{
// Custom logic here
}
}Register it before calling AddGrpcDataAnnotationValidation:
builder.Services.AddSingleton<IDataAnnotationsResultHandler, MyCustomHandler>();- Unary
- Server streaming
- Client streaming
- Duplex streaming
For streaming methods, each incoming message is validated as it is read.
See license.txt for details.