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. More info.
| 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 =>
{
// Experimental - 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)]
// Experimental - 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)
{
// Get the formatted error message
var formattedMessage = ex.GetFormattedValidationErrors();
Console.WriteLine(formattedMessage);
// Optionally, get the structured validation errors
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 for details.