Documentation Index Fetch the complete documentation index at: https://mintlify.com/IntentArchitect/Intent.Modules.NET/llms.txt
Use this file to discover all available pages before exploring further.
The Intent.AspNetCore.Grpc module generates high-performance gRPC services based on definitions in the Services Designer. gRPC is a modern, high-performance RPC framework ideal for microservices and mobile-to-backend communication.
Overview
gRPC uses Protocol Buffers (protobuf) as its Interface Definition Language (IDL) and provides features like bidirectional streaming, flow control, and efficient binary serialization. This module automatically generates .proto files and service implementations from your Intent Architect service models.
What Gets Generated
Proto Files
Protocol Buffer definitions for your services:
syntax = "proto3" ;
package myapp.v1 ;
import "google/protobuf/empty.proto" ;
import "google/protobuf/timestamp.proto" ;
service ProductService {
rpc GetProduct ( GetProductRequest ) returns ( ProductResponse );
rpc ListProducts ( ListProductsRequest ) returns ( ListProductsResponse );
rpc CreateProduct ( CreateProductRequest ) returns ( ProductResponse );
rpc UpdateProduct ( UpdateProductRequest ) returns ( google . protobuf . Empty );
rpc DeleteProduct ( DeleteProductRequest ) returns ( google . protobuf . Empty );
}
message ProductResponse {
string id = 1 ;
string name = 2 ;
double price = 3 ;
google.protobuf.Timestamp created_date = 4 ;
}
message GetProductRequest {
string id = 1 ;
}
message ListProductsRequest {
int32 page_size = 1 ;
int32 page_number = 2 ;
}
message ListProductsResponse {
repeated ProductResponse products = 1 ;
int32 total_count = 2 ;
}
message CreateProductRequest {
string name = 1 ;
double price = 2 ;
}
message UpdateProductRequest {
string id = 1 ;
string name = 2 ;
double price = 3 ;
}
message DeleteProductRequest {
string id = 1 ;
}
gRPC Service Implementation
Generated service classes:
public class ProductService : ProductServiceBase
{
private readonly IMediator _mediator ;
private readonly IMapper _mapper ;
public ProductService ( IMediator mediator , IMapper mapper )
{
_mediator = mediator ;
_mapper = mapper ;
}
public override async Task < ProductResponse > GetProduct (
GetProductRequest request ,
ServerCallContext context )
{
var query = new GetProductByIdQuery { Id = Guid . Parse ( request . Id ) };
var result = await _mediator . Send ( query , context . CancellationToken );
return _mapper . Map < ProductResponse >( result );
}
public override async Task < ListProductsResponse > ListProducts (
ListProductsRequest request ,
ServerCallContext context )
{
var query = new GetAllProductsQuery
{
PageSize = request . PageSize ,
PageNumber = request . PageNumber
};
var result = await _mediator . Send ( query , context . CancellationToken );
return new ListProductsResponse
{
Products = { _mapper . Map < List < ProductResponse >>( result . Items ) },
TotalCount = result . TotalCount
};
}
public override async Task < ProductResponse > CreateProduct (
CreateProductRequest request ,
ServerCallContext context )
{
var command = _mapper . Map < CreateProductCommand >( request );
var result = await _mediator . Send ( command , context . CancellationToken );
return _mapper . Map < ProductResponse >( result );
}
public override async Task < Empty > UpdateProduct (
UpdateProductRequest request ,
ServerCallContext context )
{
var command = _mapper . Map < UpdateProductCommand >( request );
await _mediator . Send ( command , context . CancellationToken );
return new Empty ();
}
public override async Task < Empty > DeleteProduct (
DeleteProductRequest request ,
ServerCallContext context )
{
var command = new DeleteProductCommand { Id = Guid . Parse ( request . Id ) };
await _mediator . Send ( command , context . CancellationToken );
return new Empty ();
}
}
GrpcConfiguration
Configures gRPC services:
public static class GrpcConfiguration
{
public static IServiceCollection AddGrpcConfiguration (
this IServiceCollection services )
{
services . AddGrpc ( options =>
{
options . EnableDetailedErrors = true ;
options . MaxReceiveMessageSize = 4 * 1024 * 1024 ; // 4 MB
options . MaxSendMessageSize = 4 * 1024 * 1024 ; // 4 MB
});
services . AddGrpcReflection ();
return services ;
}
public static IApplicationBuilder UseGrpcConfiguration (
this IApplicationBuilder app )
{
app . UseRouting ();
app . UseEndpoints ( endpoints =>
{
endpoints . MapGrpcService < ProductService >();
endpoints . MapGrpcReflectionService ();
});
return app ;
}
}
Exception Interceptor
Handles exceptions gracefully:
public class GrpcExceptionInterceptor : Interceptor
{
private readonly ILogger < GrpcExceptionInterceptor > _logger ;
public GrpcExceptionInterceptor ( ILogger < GrpcExceptionInterceptor > logger )
{
_logger = logger ;
}
public override async Task < TResponse > UnaryServerHandler < TRequest , TResponse >(
TRequest request ,
ServerCallContext context ,
UnaryServerMethod < TRequest , TResponse > continuation )
{
try
{
return await continuation ( request , context );
}
catch ( NotFoundException ex )
{
_logger . LogWarning ( ex , "Not found: {Message}" , ex . Message );
throw new RpcException ( new Status ( StatusCode . NotFound , ex . Message ));
}
catch ( ValidationException ex )
{
_logger . LogWarning ( ex , "Validation failed: {Message}" , ex . Message );
throw new RpcException ( new Status ( StatusCode . InvalidArgument , ex . Message ));
}
catch ( UnauthorizedAccessException ex )
{
_logger . LogWarning ( ex , "Unauthorized: {Message}" , ex . Message );
throw new RpcException ( new Status ( StatusCode . Unauthenticated , ex . Message ));
}
catch ( Exception ex )
{
_logger . LogError ( ex , "Unhandled exception in gRPC call" );
throw new RpcException ( new Status ( StatusCode . Internal , "An error occurred" ));
}
}
}
Key Features
High Performance Binary protocol with efficient serialization
Streaming Support for unary, server, client, and bidirectional streaming
Type Safety Strong typing with auto-generated client code
Multi-Platform Clients for .NET, Java, Python, Go, and more
Service Types
Unary RPC
Simple request-response:
rpc GetProduct (GetProductRequest) returns (ProductResponse);
public override async Task < ProductResponse > GetProduct (
GetProductRequest request ,
ServerCallContext context )
{
// Return single response
}
Server Streaming
Server streams multiple responses:
rpc StreamProducts (StreamProductsRequest) returns (stream ProductResponse);
public override async Task StreamProducts (
StreamProductsRequest request ,
IServerStreamWriter < ProductResponse > responseStream ,
ServerCallContext context )
{
var products = await _repository . GetAllAsync ();
foreach ( var product in products )
{
await responseStream . WriteAsync ( _mapper . Map < ProductResponse >( product ));
await Task . Delay ( 100 ); // Simulate streaming
}
}
Client Streaming
Client streams multiple requests:
rpc UploadProducts (stream CreateProductRequest) returns (UploadSummary);
public override async Task < UploadSummary > UploadProducts (
IAsyncStreamReader < CreateProductRequest > requestStream ,
ServerCallContext context )
{
var count = 0 ;
await foreach ( var request in requestStream . ReadAllAsync ())
{
var command = _mapper . Map < CreateProductCommand >( request );
await _mediator . Send ( command , context . CancellationToken );
count ++ ;
}
return new UploadSummary { ProductsCreated = count };
}
Bidirectional Streaming
Both client and server stream:
rpc Chat (stream ChatMessage) returns (stream ChatMessage);
public override async Task Chat (
IAsyncStreamReader < ChatMessage > requestStream ,
IServerStreamWriter < ChatMessage > responseStream ,
ServerCallContext context )
{
await foreach ( var message in requestStream . ReadAllAsync ())
{
// Process message and respond
var response = new ChatMessage
{
User = "Server" ,
Text = $"Echo: { message . Text } "
};
await responseStream . WriteAsync ( response );
}
}
Client Usage
.NET Client
public class ProductGrpcClient
{
private readonly ProductService . ProductServiceClient _client ;
public ProductGrpcClient ( string address )
{
var channel = GrpcChannel . ForAddress ( address );
_client = new ProductService . ProductServiceClient ( channel );
}
public async Task < ProductResponse > GetProductAsync ( string id )
{
var request = new GetProductRequest { Id = id };
return await _client . GetProductAsync ( request );
}
public async Task < List < ProductResponse >> GetAllProductsAsync ()
{
var request = new ListProductsRequest
{
PageSize = 100 ,
PageNumber = 1
};
var response = await _client . ListProductsAsync ( request );
return response . Products . ToList ();
}
public async Task < ProductResponse > CreateProductAsync (
string name ,
double price )
{
var request = new CreateProductRequest
{
Name = name ,
Price = price
};
return await _client . CreateProductAsync ( request );
}
public async Task StreamProductsAsync ()
{
var request = new StreamProductsRequest ();
using var call = _client . StreamProducts ( request );
await foreach ( var product in call . ResponseStream . ReadAllAsync ())
{
Console . WriteLine ( $"Received: { product . Name } " );
}
}
}
Python Client
import grpc
from generated import product_service_pb2
from generated import product_service_pb2_grpc
class ProductClient :
def __init__ ( self , address ):
self .channel = grpc.insecure_channel(address)
self .stub = product_service_pb2_grpc.ProductServiceStub( self .channel)
def get_product ( self , product_id ):
request = product_service_pb2.GetProductRequest( id = product_id)
return self .stub.GetProduct(request)
def list_products ( self , page_size = 100 ):
request = product_service_pb2.ListProductsRequest(
page_size = page_size,
page_number = 1
)
return self .stub.ListProducts(request)
def stream_products ( self ):
request = product_service_pb2.StreamProductsRequest()
for product in self .stub.StreamProducts(request):
print ( f "Received: { product.name } " )
# Usage
client = ProductClient( 'localhost:5001' )
product = client.get_product( '123' )
print ( f "Product: { product.name } " )
Authentication
JWT Authentication
services . AddGrpc ( options =>
{
options . Interceptors . Add < GrpcAuthenticationInterceptor >();
});
public class GrpcAuthenticationInterceptor : Interceptor
{
private readonly ICurrentUserService _currentUserService ;
public override async Task < TResponse > UnaryServerHandler < TRequest , TResponse >(
TRequest request ,
ServerCallContext context ,
UnaryServerMethod < TRequest , TResponse > continuation )
{
if ( ! _currentUserService . IsAuthenticated )
{
throw new RpcException (
new Status ( StatusCode . Unauthenticated , "Not authenticated" ));
}
return await continuation ( request , context );
}
}
Client includes token:
var credentials = CallCredentials . FromInterceptor (( context , metadata ) =>
{
metadata . Add ( "Authorization" , $"Bearer { token } " );
return Task . CompletedTask ;
});
var channel = GrpcChannel . ForAddress ( address , new GrpcChannelOptions
{
Credentials = ChannelCredentials . Create (
new SslCredentials (),
credentials )
});
Error Handling
Status Codes
gRPC uses standard status codes:
Code Description Use Case OK Success Successful operation CANCELLED Operation cancelled Client cancelled INVALID_ARGUMENT Invalid input Validation failure NOT_FOUND Resource not found Entity doesn’t exist ALREADY_EXISTS Resource exists Duplicate creation PERMISSION_DENIED No permission Authorization failure UNAUTHENTICATED Not authenticated Missing/invalid token RESOURCE_EXHAUSTED Rate limited Too many requests UNIMPLEMENTED Not implemented Method not available INTERNAL Internal error Server error UNAVAILABLE Service unavailable Temporary failure
Exception Handling
try
{
var response = await _client . GetProductAsync ( request );
}
catch ( RpcException ex ) when ( ex . StatusCode == StatusCode . NotFound )
{
Console . WriteLine ( "Product not found" );
}
catch ( RpcException ex ) when ( ex . StatusCode == StatusCode . InvalidArgument )
{
Console . WriteLine ( $"Invalid input: { ex . Status . Detail } " );
}
catch ( RpcException ex )
{
Console . WriteLine ( $"gRPC error: { ex . Status } " );
}
HTTP/2 Settings
{
"Kestrel" : {
"Endpoints" : {
"Grpc" : {
"Url" : "http://localhost:5001" ,
"Protocols" : "Http2"
}
}
}
}
Message Size Limits
services . AddGrpc ( options =>
{
options . MaxReceiveMessageSize = 16 * 1024 * 1024 ; // 16 MB
options . MaxSendMessageSize = 16 * 1024 * 1024 ; // 16 MB
});
Compression
services . AddGrpc ( options =>
{
options . ResponseCompressionLevel = CompressionLevel . Optimal ;
});
Testing
Unit Tests
[ Fact ]
public async Task GetProduct_ValidId_ReturnsProduct ()
{
// Arrange
var mediator = new Mock < IMediator >();
var mapper = new Mock < IMapper >();
var service = new ProductService ( mediator . Object , mapper . Object );
var request = new GetProductRequest { Id = Guid . NewGuid (). ToString () };
var context = TestServerCallContext . Create ();
// Act
var response = await service . GetProduct ( request , context );
// Assert
Assert . NotNull ( response );
}
Integration Tests
public class GrpcTests : IClassFixture < WebApplicationFactory < Program >>
{
private readonly WebApplicationFactory < Program > _factory ;
public GrpcTests ( WebApplicationFactory < Program > factory )
{
_factory = factory ;
}
[ Fact ]
public async Task GetProduct_ReturnsProduct ()
{
// Arrange
var client = _factory . CreateGrpcClient < ProductService . ProductServiceClient >();
var request = new GetProductRequest { Id = Guid . NewGuid (). ToString () };
// Act
var response = await client . GetProductAsync ( request );
// Assert
Assert . NotNull ( response );
}
}
Best Practices
Use clear, consistent naming
Version your proto files
Document with comments
Use well-known types (Timestamp, Duration, etc.)
Use appropriate status codes
Include detailed error messages
Implement proper exception handling
Log all errors
Always use TLS in production
Implement authentication
Validate all inputs
Use interceptors for cross-cutting concerns
gRPC vs REST
Aspect gRPC REST Protocol HTTP/2 HTTP/1.1 Format Protocol Buffers (binary) JSON (text) Performance Faster, less bandwidth Slower, more bandwidth Streaming Built-in Limited Browser Support Limited (gRPC-Web needed) Full Tooling Code generation OpenAPI Human Readable No Yes Best For Microservices, mobile apps Public APIs, web apps
Installation
Dependencies
Intent.Common.CSharp
Intent.Modelers.Services
Intent.OutputManager.RoslynWeaver
Next Steps
Controllers Compare with REST API controllers
MediatR Dispatch gRPC calls to handlers
Security Secure gRPC services