This is a chat service with a tiny front-end orchestrated with .NET Aspire and supported by Dapr for demo purposes.
Architecture | Technology | Prerequisites | Monitoring | Endpoints | Contributing | License | Support
A distributed chat application backend built with .NET 10, ASP.NET Core, .NET Aspire, and Dapr. This demonstration showcases event-driven microservices architecture with real-time messaging capabilities. All orchestrated locally with .NET Aspire and in the cloud with Azure Container Apps (expected soon).
The application consists of four main components:
- Members API (
localhost:5129): Manages user registration and member lifecycle - Messages API (
localhost:5227): Handles message processing and storage - Realtime API (
localhost:5206): Provides real-time message broadcasting via SignalR - Chat Client (
localhost:3000): Node.js-based web client serving the chat interface
All services are orchestrated using .NET Aspire and communicate through Dapr pub/sub messaging patterns.
- .NET 10: Latest .NET version for all projects
- ASP.NET Core Web APIs: RESTful service endpoints
- Node.js & Express: Chat client web server
- Azure Table Storage: Data persistence (using Azurite emulator for local development)
- Dapr: Event-driven pub/sub messaging
- Redis: Dapr state store and pub/sub backend
- SignalR: Real-time client communication
- .NET Aspire: Service orchestration and observability
Before running the application, ensure you have the following installed:
- .NET 10 SDK: Download from https://dotnet.microsoft.com/download/dotnet/10.0
- Node.js (v20 or later): Download from https://nodejs.org/
- Docker Desktop: Required for Redis and Azurite containers
- Dapr CLI: Install from https://docs.dapr.io/getting-started/install-dapr-cli/
- Visual Studio 2022 or Visual Studio Code (recommended)
git clone <repository-url>
cd aspire-dapr-chat-service-demo- Open
src/Aspire Chat.slnin Visual Studio 2022 - Set
HexMaster.Chat.Aspire.AppHostas the startup project - Press F5 or click "Run"
cd src
dotnet run --project Aspire/HexMaster.Chat.Aspire/HexMaster.Chat.Aspire.AppHostOnce running, you'll have access to:
- Aspire Dashboard:
https://localhost:17180(orchestration and monitoring) - Chat Client:
http://localhost:3000(main user interface) - Members API:
http://localhost:5129 - Messages API:
http://localhost:5227 - Realtime API:
http://localhost:5206
POST /members
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com"
}
GET /members/{id}
PUT /members/{id}/activityPOST /messages
Content-Type: application/json
{
"content": "Hello, world!",
"senderId": "member-id-here"
}
GET /messages/recent?count=50
GET /messages/history?from=2024-01-01&to=2024-01-02- SignalR Hub:
/chathub - Event Endpoints: Handled automatically by Dapr subscriptions
- Start the Aspire application using one of the methods above
- Navigate to
http://localhost:3000in your web browser - Enter your name and email, then click "Register & Connect"
- Start typing messages in the message box
- Open multiple browser tabs to simulate multiple users
- Watch real-time message delivery across all connected clients
The chat client automatically detects the backend service URLs through Aspire's service discovery mechanism.
The application uses Dapr pub/sub for loose coupling between services:
-
Member Registration:
- Members API stores member data
- Publishes
member-joinedevent - Realtime API broadcasts to connected clients
-
Message Sending:
- Messages API validates and stores message
- Publishes
message-sentevent - Realtime API broadcasts to all chat participants
-
Member Cleanup:
- Background service removes inactive members (>1 hour)
- Publishes
member-leftevent - Realtime API notifies remaining participants
-
Message Cleanup:
- Background service removes old messages (>24 hours)
- Runs automatically every hour
src/
├── Aspire/
│ ├── HexMaster.Chat.Aspire.AppHost/ # Aspire orchestration
│ └── HexMaster.Chat.Aspire.ServiceDefaults/ # Shared configuration
├── ChatClient/ # Node.js web client
│ ├── public/
│ │ └── index.html # Chat interface
│ ├── server.js # Express.js server
│ ├── package.json # Node.js dependencies
│ └── Dockerfile # Container configuration
├── Members/
│ └── HexMaster.Chat.Members.Api/ # Member management service
├── Messages/
│ └── HexMaster.Chat.Messages.Api/ # Message handling service
├── Realtime/
│ └── HexMaster.Chat.Realtime.Api/ # SignalR service
└── Shared/
└── HexMaster.Chat.Shared/ # Common models and utilities
Access the Aspire dashboard at https://localhost:15888 to monitor:
- Service health and status
- Distributed tracing
- Logs aggregation
- Resource utilization
- Service dependencies
dapr dashboardAccess at http://localhost:8080 for Dapr-specific monitoring.
The application uses Azure Table Storage for persistence:
- Members Table: User profiles and activity tracking
- Messages Table: Chat message history
Data is automatically cleaned up based on retention policies:
- Members: Removed after 1 hour of inactivity
- Messages: Removed after 24 hours
Used by Dapr for:
- State management
- Pub/sub messaging
- Service-to-service communication
You can run services individually for debugging:
# Members API
cd src/Members/HexMaster.Chat.Members.Api
dapr run --app-id members-api --app-port 5196 --dapr-http-port 3501 --components-path ../../../dapr -- dotnet run
# Messages API
cd src/Messages/HexMaster.Chat.Messages.Api
dapr run --app-id messages-api --app-port 5113 --dapr-http-port 3502 --components-path ../../../dapr -- dotnet run
# Realtime API
cd src/Realtime/HexMaster.Chat.Realtime.Api
dapr run --app-id realtime-api --app-port 5197 --dapr-http-port 3503 --components-path ../../../dapr -- dotnet run- Aspire Dashboard: Check the logs tab for each service
- Console Output: Each service outputs structured logs to console
- Dapr Logs: Use
dapr logs --app-id <service-name>for Dapr-specific logs
This is a demonstration application. For production deployment, consider:
- Implement proper authentication and authorization
- Use HTTPS for all endpoints
- Secure SignalR connections with authentication
- Validate and sanitize all user inputs
- Use Azure Service Bus instead of Redis for pub/sub in production
- Implement proper database scaling strategies
- Consider Azure SignalR Service for SignalR scaling
- Add rate limiting and throttling
- Implement circuit breakers and retry policies
- Add comprehensive error handling and recovery
- Use Azure Key Vault for secrets management
- Implement health checks and monitoring
- Deploy to Azure Container Apps or Azure Kubernetes Service
- Use Azure Table Storage or Azure Cosmos DB for production data
- Implement proper CI/CD pipelines
- Add automated testing suites
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.
For questions or issues:
- Check the Aspire dashboard for service health
- Review the console logs for error messages
- Ensure all prerequisites are properly installed
- Verify Docker containers are running (
docker ps) - Check Dapr components configuration in the
/daprfolder
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Members API │ │ Messages API │ │ Realtime API │
│ (Port 5196) │ │ (Port 5113) │ │ (Port 5197) │
└─────────┬───────┘ └─────────┬───────┘ └─────────┬───────┘
│ │ │
│ │ │
└──────────┬───────────┴──────────┬───────────┘
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Dapr │ │ SignalR │
│ Pub/Sub │ │ Hubs │
└─────────────┘ └─────────────┘
│
▼
┌─────────────┐
│ Redis │
│ (Container) │
└─────────────┘
┌─────────────┐
│ Azurite │
│ (Container) │
└─────────────┘
This architecture ensures loose coupling, scalability, and real-time communication capabilities while maintaining development simplicity and production readiness. This is an ASP.NET Web API written in C# that allows its visitors to chat
