Summary: AdminWeb uses a specialized Protobuffer structure to optimize binary size and build caching. This document defines the naming conventions, project structure, and best practices for defining service communication contracts.
Overview
AdminWeb’s microservices communicate via gRPC using Protocol Buffers (.proto files) for serialization. To reduce binary size and improve build caching, we use a unique naming convention that separates client-side, server-side, and shared message definitions.Core Principle
Each .proto file belongs to one of five specialized project types that control visibility and compilation scope.
Protobuffer Project Types
1. *.client - Client Communication Contracts
Purpose: Used by clients/projects to communicate with a gRPC service
Visibility:
- Includes only messages needed by clients
- Shipped with WASM applications
- Minimal binary footprint
- No backend-specific types
donations.client.proto:
- Blazor Web applications (Frontend)
- Sa.App.Client projects
- Public APIs
- Any WASM client
2. *.server - Server Implementation Contracts
Purpose: Used by the gRPC service that hosts the API
Visibility:
- Includes the complete service definition
- References both client and shared messages
- Only used by ServiceApi projects
- Not distributed to clients
donations.server.proto:
*.ServiceApisprojects (gRPC service hosts)*.Workersprojects (for inter-service calls)
3. *.shared - Backend-Only Shared Messages
Purpose: Shared message definitions between backend services only
Visibility:
- Backend-to-backend communication only
- Never exported to WASM/clients
- Used for internal service-to-service contracts
- Reusable across multiple services
common.shared.proto:
- Multiple
*.ServiceApisprojects *.Workersprojects*.CoreLibsprojects
4. *.shared_external - Client-Accessible Shared Messages
Purpose: Shared message definitions exported to WASM clients
Visibility:
- Backend-to-backend and backend-to-frontend
- Shipped with client applications
- Reusable data structures visible to frontend
- Carefully managed for binary size
common.shared_external.proto:
- Blazor Web frontend
*.ServiceApisprojects*.Workersprojects- WASM clients
5. *.shared_enums - Enumeration Definitions
Purpose: Centralized enum definitions shared across multiple services
Visibility:
- Can be exported to clients or keep backend-only
- Single source of truth for enums
- Prevents duplication
- Easy versioning and maintenance
payment-status.proto:
- Any project that needs these enums
- Can be imported into client or server proto files
Project Structure & Organization
Recommended Directory Layout
Proto File Organization
Naming Conventions:Versioning Strategy
File-Level Versioning
Use package versioning rather than filename versioning:Backward Compatibility
When evolving messages:Best Practices for Message Definitions
1. Use Meaningful Field Numbers
2. Use repeated for Collections
3. Use Well-Known Types
4. Mark Fields as Optional/Required Clearly
5. Use Enums for Constants
6. Nest Messages for Scope
Build Caching Optimization
Why Separate Projects Matter
The separation into.client, .server, .shared, etc. enables optimal build caching:
Benefits
-
Frontend only rebuilds when
.clientor.shared_externalchanges- No rebuild if internal backend messages change
- Faster iteration for web developers
-
Services rebuild independently
- Worker changes don’t force ServiceApi rebuild
- Parallel builds possible
-
Reduced WASM size
- Only necessary messages included
- No internal-only types shipped to browser
Cache Busting
Only change.client or .shared_external when absolutely necessary:
Project File Template
*.client.csproj Example
*.server.csproj Example
Import Patterns
Safe Imports
Code Generation
C# Options
Common Mistakes & Solutions
| Problem | Solution |
|---|---|
| Proto file in wrong project type | Verify file belongs in correct .client/.server/.shared project |
| Circular import dependencies | Review import chain, refactor to single direction |
Including internal messages in .client | Move internal-only messages to .shared instead |
| Field number reuse | Always reserve old field numbers to prevent incompatibility |
| Inconsistent naming conventions | Use lowercase with hyphens for filenames, PascalCase in proto definitions |
| WASM bloat | Audit .shared_external for unnecessary fields |
| Service rebuild on unrelated changes | Ensure proto file is in correct project type for better caching |
Related Documentation
- System Architecture - How services communicate
- gRPC Communication - Service call patterns
- Data Access Patterns - Database integration
- Coding Standards - General code conventions
