syntax = "proto3";
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
Topics
36
API Documentation with Swagger/OpenAPI
API Versioning
Authentication
Authorization
Background Tasks & Hosted Services
Blazor Integration with ASP.NET Core
Caching
Configuration & Options Pattern
Content Negotiation & Output Formatters
Controllers vs Minimal APIs
CORS (Cross-Origin Resource Sharing)
Dependency Injection
Endpoint Metadata, Route Constraints & Templates
Error Handling
File Uploads & Streaming Large Files
Filters
gRPC Services
Health Checks
Hosting Models: Kestrel, IIS & Reverse Proxies
HTTPS, Certificates & Transport Security
Localization & Globalization
Logging
Model Binding & Validation
MVC Views, Razor Syntax & Tag Helpers
Output Caching & Response Caching
Rate Limiting
Razor Pages
Request Pipeline & Middleware
Response Compression & Caching Headers
Routing
Security Headers, Antiforgery & CSRF Protection
Sessions, Cookies & TempData
SignalR & Real-Time Communication
Static Files, wwwroot & Content Delivery
Testing ASP.NET Core Applications
WebSockets
gRPC Services
15 questions found
gRPC is a high-performance RPC (Remote Procedure Call) framework built on HTTP/2 that uses Protocol Buffers (protobuf) for compact binary serialization and strongly-typed service contracts -- compared to REST/JSON, gRPC offers significantly smaller payload sizes, lower latency (thanks to HTTP/2 multiplexing), strongly-typed client/server code generated from a shared .proto contract, and native support for streaming (client, server, and bidirectional), making it well suited for internal microservice-to-microservice communication.
Real-world example
An internal microservices architecture uses gRPC for service-to-service calls (order service calling inventory service) to benefit from lower latency and strongly-typed contracts, while still exposing a public-facing REST/JSON API for external clients and browsers.
RESTful Web APIs & Controllers;Content Negotiation & Output Formatters
How do you define a gRPC service contract using Protocol Buffers, and how is the C# service implementation generated from it?
IntermediateA .proto file defines the service's RPC methods and message types using protobuf syntax; the Grpc.Tools NuGet package's build-time code generation (via <Protobuf Include="..." /> in the .csproj) automatically generates a strongly-typed C# base class (GreeterBase) that you inherit from and override to implement the actual service logic, plus a strongly-typed client class for consumers.
// greet.proto
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply);
}
// GreeterService.cs -- inherits generated base class
public class GreeterService : Greeter.GreeterBase {
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context) {
return Task.FromResult(new HelloReply { Message = $"Hello {request.Name}" });
}
}
// Program.cs
app.MapGrpcService<GreeterService>();
Real-world example
A payments microservice defines its contract in a shared .proto file checked into a common repository, generating both the C# server implementation stub and client code automatically, ensuring server and client never drift out of sync on the contract shape.
API Versioning;API Documentation with Swagger/OpenAPI
How do the four gRPC method types (unary, server streaming, client streaming, bidirectional streaming) differ, and when would you use each?
AdvancedUnary (single request, single response) is the default and covers most simple RPC calls, analogous to a typical REST call. Server streaming (single request, stream of responses) suits scenarios like a live feed of updates from one initial request. Client streaming (stream of requests, single response) suits scenarios like uploading a large dataset in chunks before getting one final result. Bidirectional streaming (both streams simultaneously, independent of each other) suits real-time, two-way scenarios like a chat application or live collaborative editing.
service DataService {
rpc GetItem (ItemRequest) returns (Item); // unary
rpc StreamUpdates (SubscribeRequest) returns (stream Update); // server streaming
rpc UploadItems (stream Item) returns (UploadSummary); // client streaming
rpc Chat (stream ChatMessage) returns (stream ChatMessage); // bidirectional
}
Real-world example
A stock ticker service uses server streaming to push continuous price updates to a subscribed client from a single subscription request, while a log ingestion service uses client streaming to let an agent send a continuous stream of log entries before receiving one final batch-acknowledgment response.
SignalR & Real-Time Communication;Background Tasks & Hosted Services
Why can't browsers natively call gRPC services directly, and what is gRPC-Web, and how does it solve this?
IntermediateStandard gRPC requires full HTTP/2 features (particularly trailers, sent after the response body, used to carry the final status) that browser JavaScript fetch/XHR APIs don't expose access to -- gRPC-Web is a protocol variant designed to work within browser HTTP/1.1 and HTTP/2 constraints (encoding trailers differently, within the body), requiring a compatible client library on the frontend and either native gRPC-Web support on the server or a proxy (like Envoy) translating between gRPC-Web and standard gRPC for the backend service.
// Program.cs -- enabling gRPC-Web support directly in ASP.NET Core
builder.Services.AddGrpc();
var app = builder.Build();
app.UseGrpcWeb();
app.MapGrpcService<GreeterService>().EnableGrpcWeb();
Real-world example
A single-page application needs to call a gRPC backend service directly from browser JavaScript, so the team enables ASP.NET Core's built-in gRPC-Web support on the server and uses the grpc-web client library on the frontend, avoiding the need for a separate Envoy proxy.
CORS (Cross-Origin Resource Sharing);Hosting Models: Kestrel
IIS & Reverse Proxies
How do you implement authentication and authorization for gRPC services in ASP.NET Core, given gRPC calls don't carry cookies the way browser requests typically do?
AdvancedgRPC authentication commonly uses JWT bearer tokens passed via a custom metadata header (equivalent to an HTTP header) on each call, validated through the same JWT bearer authentication middleware used for REST APIs -- since gRPC runs on top of ASP.NET Core's standard hosting model, the [Authorize] attribute and policy-based authorization work identically on gRPC service methods as they do on MVC controllers, with the token extracted from call metadata instead of a cookie.
[Authorize]
public class SecureGreeterService : Greeter.GreeterBase {
[Authorize(Policy = "AdminOnly")]
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context) {
var user = context.GetHttpContext().User;
return Task.FromResult(new HelloReply { Message = $"Hello {user.Identity.Name}" });
}
}
// Client attaches the token via call metadata
var headers = new Metadata { { "Authorization", $"Bearer {token}" } };
var reply = await client.SayHelloAsync(request, headers);
Real-world example
An internal microservices mesh authenticates gRPC service-to-service calls using JWT bearer tokens issued by a shared identity service, attached as call metadata and validated with the exact same JWT bearer authentication middleware and [Authorize] policies used across the REST APIs in the same solution.
Authentication;Authorization
How do you handle and propagate errors in gRPC, given it doesn't use standard HTTP status codes the way REST does?
IntermediategRPC uses its own status code system (RpcException with a StatusCode like NotFound, InvalidArgument, PermissionDenied) distinct from HTTP status codes, thrown by the server and automatically translated into the equivalent gRPC status on the wire, which the client catches as an RpcException with a matching StatusCode property -- richer error details can be attached via google.rpc.Status metadata for structured error information beyond just a status code and message.
public override Task<Item> GetItem(ItemRequest request, ServerCallContext context) {
var item = _repository.Find(request.Id);
if (item is null)
throw new RpcException(new Status(StatusCode.NotFound, $"Item {request.Id} not found"));
return Task.FromResult(item);
}
// Client-side handling
try {
var item = await client.GetItemAsync(request);
} catch (RpcException ex) when (ex.StatusCode == StatusCode.NotFound) {
// handle not-found case
}
Real-world example
A gRPC inventory service throws an RpcException with StatusCode.NotFound when queried for a nonexistent product, which the calling order service catches specifically by that status code to trigger its own appropriate fallback behavior.
Error Handling;Global Exception Handling & Middleware
What are gRPC interceptors, and how do they compare to ASP.NET Core middleware or MVC filters for implementing cross-cutting concerns?
AdvancedgRPC interceptors (implementing Interceptor, overriding methods like UnaryServerHandler) wrap RPC call execution on either the server or client side, serving a conceptually similar cross-cutting role to middleware/filters but specific to the gRPC pipeline -- used for logging, authentication token extraction, exception translation, or metrics collection uniformly across all gRPC service methods, registered via AddGrpc(options => options.Interceptors.Add<MyInterceptor>()) for server-side or on the channel for client-side.
public class LoggingInterceptor : Interceptor {
public override async Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
TRequest request, ServerCallContext context, UnaryServerMethod<TRequest, TResponse> continuation) {
var start = DateTime.UtcNow;
try {
return await continuation(request, context);
} finally {
Console.WriteLine($"{context.Method} took {(DateTime.UtcNow - start).TotalMilliseconds}ms");
}
}
}
builder.Services.AddGrpc(options => options.Interceptors.Add<LoggingInterceptor>());
Real-world example
A gRPC service applies a single logging interceptor globally to record execution time and status for every RPC method across the entire service, avoiding the need to add manual timing code to each individual method implementation.
ASP.NET Core Middleware & Request Pipeline;Filters
How do you generate and use a strongly-typed gRPC client in a .NET application to call a gRPC service?
IntermediateThe Grpc.Net.Client package combined with the same .proto file (with GrpcServices="Client" in the .csproj) generates a strongly-typed client class; instantiate a GrpcChannel pointing at the service's address, construct the generated client class with that channel, and call its strongly-typed methods directly -- ASP.NET Core's typed HttpClient integration (AddGrpcClient<T>()) further simplifies this by handling channel lifetime and DI registration automatically.
// Program.cs -- DI-based typed client registration
builder.Services.AddGrpcClient<Greeter.GreeterClient>(options => {
options.Address = new Uri("https://localhost:5001");
});
// Injected and used in a service
public class MyService(Greeter.GreeterClient client) {
public async Task<string> Greet(string name) {
var reply = await client.SayHelloAsync(new HelloRequest { Name = name });
return reply.Message;
}
}
Real-world example
An order-processing service registers a typed gRPC client for the inventory service via AddGrpcClient, getting automatic HttpClient lifetime management and DI integration the same way a typed HttpClient for a REST API would be registered.
Dependency Injection;HttpClient & Resilience (Polly)
How would you implement deadline/timeout propagation across a chain of gRPC calls to prevent cascading resource exhaustion when a downstream service is slow?
AdvancedgRPC's built-in deadline mechanism lets a client specify an absolute deadline for a call (via CallOptions.Deadline), and this deadline is automatically propagated by the framework to any downstream gRPC calls made within that call's context -- ensuring a slow downstream dependency doesn't cause an unbounded chain of calls to all hang indefinitely, instead causing the entire chain to fail fast once the original deadline passes, which is a significant advantage over needing to manually implement timeout propagation with plain HTTP calls.
// Client sets an explicit deadline
var callOptions = new CallOptions(deadline: DateTime.UtcNow.AddSeconds(5));
var reply = await client.SayHelloAsync(request, callOptions);
// If SayHello internally calls another gRPC service using the ServerCallContext's
// deadline, that downstream call automatically inherits the remaining time budget
Real-world example
A multi-hop gRPC call chain (gateway to order service to inventory service to pricing service) automatically propagates a single 5-second deadline set at the gateway, causing the entire chain to fail fast together if any downstream service is slow, rather than each hop independently timing out and wasting resources on work whose result will be discarded anyway.
HttpClient & Resilience (Polly);Diagnostics & Performance
How do you enable and use gRPC reflection for service discovery and debugging tools like grpcurl or Postman?
IntermediateThe Grpc.AspNetCore.Server.Reflection package, registered via AddGrpcReflection() and app.MapGrpcReflectionService(), exposes metadata about a gRPC service's available methods and message types at runtime without needing the original .proto file -- essential for generic debugging/testing tools like grpcurl, Postman, or BloomRPC to introspect and call a gRPC service interactively during development, though it's typically disabled in production for security reasons.
// Program.cs
#if DEBUG
builder.Services.AddGrpcReflection();
#endif
var app = builder.Build();
#if DEBUG
app.MapGrpcReflectionService();
#endif
# Using grpcurl with reflection enabled
grpcurl -plaintext localhost:5001 list
grpcurl -plaintext -d '{"name": "World"}' localhost:5001 Greeter/SayHello
Real-world example
A development team enables gRPC reflection only in Debug builds, letting engineers use grpcurl to interactively explore and test a gRPC service's available methods during local development without needing to share or track down the exact .proto file.
API Documentation with Swagger/OpenAPI;Configuration & Options Pattern
Showing 1–10 of 15