RentalRepairs - Building Workflow Applications for Multi-User Scenarios with Clean Architecture and DDD
A practical exploration of designing workflow-driven, multi-user applications using Clean Architecture, Domain-Driven Design (DDD), and modern .NET 8 technologies.
This is a reference implementation demonstrating production-ready architectural patterns for building complex business applications. It showcases Clean Architecture, Domain-Driven Design, and CQRS patterns applied to a real-world rental property maintenance workflow system.
Project Status: Active development - suitable for learning, reference, and portfolio demonstration.
Note: The demo runs on cost-optimized Azure infrastructure with serverless SQL. Initial load may take 20-30 seconds if the database has auto-paused due to inactivity.
Demo Credentials:
- Admin: [email protected] / Demo123!
- Tenant: [email protected] / Demo123!
- Worker: [email protected] / Demo123!
- 417 C# files across 9 projects (4 core + 4 test + 1 composition root)
- 600+ passing tests with comprehensive coverage (83 test files)
- 4 Core Aggregates with sophisticated business logic
- 45+ CQRS Handlers for command and query operations
- 20+ Domain Events enabling event-driven architecture
- 15+ Value Objects ensuring data integrity
This application models a rental property maintenance system where tenants submit maintenance requests, superintendents coordinate repairs, and workers complete the work.
| Entity | Description | Key Responsibilities |
|---|---|---|
| Property | Rental building managed by a superintendent | Manages units, tracks occupancy, enforces property-level rules |
| Tenant | Resident living in a property unit | Submits maintenance requests, subject to rate limiting |
| TenantRequest | Maintenance request with full lifecycle | Tracks status, enforces business rules, manages workflow transitions |
| Worker | Skilled tradesperson (plumber, electrician, etc.) | Receives assignments, reports completion, tracks availability |
The TenantRequest entity follows a rich state machine with business rule enforcement at each transition:
stateDiagram-v2
[*] --> Draft
Draft --> Submitted : Submit Request
Submitted --> Scheduled : Assign Worker
Submitted --> Declined : Decline Request
Scheduled --> Done : Complete Successfully
Scheduled --> Failed : Work Failed
Failed --> Scheduled : Reschedule
Done --> Closed : Close Request
Declined --> Closed : Close Request
Closed --> [*]
note right of Submitted
Business Rules:
• Max 5 requests per 24h
• Max 2 emergency per 7 days
• No duplicate active requests
end note
note right of Scheduled
Worker Assignment:
• Skill specialization matching
• Availability verification
• Max 2 assignments per day
• Emergency priority handling
end note
- Tenant Request Lifecycle: From submission through completion with rich validation
- Worker Assignment Logic: Intelligent matching based on skills, availability, and workload
- Emergency Handling: Priority routing and specialized response protocols
- Multi-Role Notifications: Automated communication to all stakeholders
This project showcases modern software architecture patterns with proper separation of concerns.
- Clean Architecture with proper dependency inversion
- Domain-Driven Design with rich domain models
- CQRS (Command Query Responsibility Segregation) with MediatR
- Repository Pattern for data access abstraction
- Specification Pattern for complex queries
- Domain Events for cross-cutting concerns
- Domain Layer: Contains business entities, value objects, domain services, and business rules
- Application Layer: Implements use cases using CQRS pattern with command and query handlers
- Infrastructure Layer: Handles data persistence, external services, and cross-cutting concerns
- Presentation Layer: Razor Pages with proper separation of concerns and responsive design
- Commands: Write operations with business validation
- Queries: Read operations optimized for specific use cases
- Handlers: Separate handlers for each command and query
- DTOs: Proper data transfer objects for each layer
The domain layer implements Domain-Driven Design with rich aggregates and event-driven communication:
graph TB
subgraph "Core Aggregates"
P[Property<br/>• Manages units<br/>• Tracks occupancy<br/>• Superintendent oversight]
T[Tenant<br/>• Lives in unit<br/>• Submits requests<br/>• Rate limiting rules]
TR[TenantRequest<br/>• Rich workflow<br/>• Status transitions<br/>• Business validation]
W[Worker<br/>• Specialized skills<br/>• Availability tracking<br/>• Assignment logic]
end
subgraph "Business Flows"
P -.->|registers| T
T -.->|creates| TR
TR -.->|assigned to| W
W -.->|completes work for| TR
end
subgraph "Key Features"
BL[Complex Business Logic<br/>• 15+ validation rules<br/>• Rate limiting<br/>• Emergency handling]
WA[Smart Worker Assignment<br/>• Skill matching<br/>• Availability checking<br/>• Performance scoring]
ES[Event-Driven Architecture<br/>• 20+ domain events<br/>• Async processing<br/>• Loose coupling]
end
TR --> BL
W --> WA
P --> ES
T --> ES
TR --> ES
W --> ES
- Aggregates:
Property,Tenant,Worker,TenantRequestwith proper boundaries - Value Objects:
PropertyAddress,PersonContactInfo,SchedulingSlot - Domain Events: For decoupled communication between aggregates
- Specifications: For complex query logic encapsulation
- 4 Core Aggregates with sophisticated business logic encapsulation
- 15+ Value Objects ensuring data integrity and business rule enforcement
- 20+ Domain Events enabling loose coupling and async workflows
- Complex Business Rules: Rate limiting, emergency prioritization, worker-request matching
- Rich Status Workflows with validation at each transition
- .NET 8.0 - Latest .NET framework with C# 12
- ASP.NET Core Razor Pages - Server-side rendering
- Entity Framework Core 8.0.11 - ORM with SQL Server
- MediatR 12.2.0 - CQRS implementation
- Mapster 7.4.0 - Object-to-object mapping
- FluentValidation 11.8.0 - Input validation
- xUnit 2.6.2 - Comprehensive testing framework
- Moq 4.20.69 - Mocking framework
- FluentAssertions 6.12.0 - Assertion library
src/
├── Domain/ # Pure business logic (no dependencies)
├── Application/ # Use cases and application logic
├── Infrastructure/ # External concerns (database, email, etc.)
├── WebUI/ # Razor Pages presentation layer
├── CompositionRoot/ # Dependency injection configuration
└── *.Tests/ # Comprehensive test coverage
- Rich domain entities with encapsulated business logic
- Value objects for data integrity
- Domain events for decoupled communication
- Specification pattern for complex queries
- Domain services for cross-aggregate operations
- CQRS with 45+ command and query handlers
- Application services for workflow orchestration
- DTOs with proper mapping strategies
- Comprehensive validation pipeline
- Clean separation of read/write operations
- Repository pattern implementations
- Entity Framework configurations
- Authentication and authorization
- External service integrations
- Caching and performance optimizations
- Clean Razor Pages with proper separation
- View models and mapping
- Role-based authentication
- Responsive design with Bootstrap 5
- .NET 8 SDK (Download)
- SQL Server LocalDB (included with Visual Studio) or SQL Server Express
- Visual Studio 2022 or VS Code
Verify prerequisites:
# Check .NET version
dotnet --version
# Should show 8.0.x or higher
# Check SQL Server LocalDB (Windows)
sqllocaldb info
# Should list available instances# Clone the repository
git clone https://github.com/akhmelevtsov/RentalRepairs.CleanArchitecture.git
cd RentalRepairs.CleanArchitecture
# Restore packages
dotnet restore
# Run the application (database will be created automatically on first run)
dotnet run --project src/WebUI/
# Access the application
# Navigate to: https://localhost:5001What happens on first run:
- Database is automatically created in SQL Server LocalDB
- Demo data is seeded (properties, tenants, workers, requests)
- Demo credentials are generated and saved to
src/WebUI/development-credentials.md
Standard demo credentials (check src/WebUI/development-credentials.md if these don't work):
- Admin: [email protected] / Demo123!
- Tenant: [email protected] / Demo123!
- Worker: [email protected] / Demo123!
Note: If the application doesn't start or credentials don't work, check the generated
development-credentials.mdfile in the WebUI directory for the actual usernames and passwords created in your environment.
This project includes production-ready Azure Bicep templates for deploying the entire application infrastructure to Azure.
The Bicep templates deploy a complete, cost-optimized infrastructure with:
- App Service - Windows-based web hosting with .NET 8 runtime
- Azure SQL Database - Serverless compute for cost efficiency (auto-pause after 60 min)
- Key Vault - Secure secrets and configuration management
- Application Insights - Performance monitoring and diagnostics
Cost Optimizations:
- Storage Account and CDN removed (saves ~$35-51/month)
- Static files (7 KB) served directly from App Service
- Uses public CDNs (jsDelivr, Cloudflare) for Bootstrap/Font Awesome
- Estimated cost: $0.84-$20/month depending on SQL activity (as of January 2025)
graph TB
subgraph Azure["Azure Subscription"]
subgraph RG["Resource Group (4 resources)"]
AS["App Service<br/>(Web App)<br/>~$13/mo"]
KV["Key Vault<br/>(Secrets)<br/>~$0.03/mo"]
AI["App Insights<br/>(Monitoring)<br/>~$2-5/mo"]
SQL["SQL Server<br/>(Serverless)<br/>~$0.84-20/mo"]
MI["Managed<br/>Identity"]
end
end
AS -->|Uses| KV
AS -->|Telemetry| AI
AS -->|Auth| MI
MI -->|Access| SQL
MI -->|Access| KV
Using PowerShell (Windows):
# Navigate to bicep directory
cd bicep
# Copy and configure parameters
Copy-Item parameters.example.json parameters.json
# Edit parameters.json with your values
# Login to Azure
az login
az account set --subscription "YOUR_SUBSCRIPTION_ID"
# Deploy infrastructure
az deployment sub create `
--name "rentalrepairs-$(Get-Date -Format 'yyyyMMddHHmmss')" `
--location canadacentral `
--template-file main.bicep `
--parameters '@parameters.json'Using Bash (Linux/macOS):
# Navigate to bicep directory
cd bicep
# Copy and configure parameters
cp parameters.example.json parameters.json
# Edit parameters.json with your values
# Login to Azure
az login
az account set --subscription "YOUR_SUBSCRIPTION_ID"
# Deploy infrastructure
az deployment sub create \
--name "rentalrepairs-$(date +%Y%m%d%H%M%S)" \
--location canadacentral \
--template-file main.bicep \
--parameters @parameters.jsonComprehensive documentation is available in the bicep/docs/ directory:
- README.md - Overview and quick reference for Bicep templates
- DEPLOYMENT_GUIDE.md - Step-by-step deployment instructions with troubleshooting
- GETTING_STARTED.md - Quick start checklist for first-time deployment
- QUICK_REFERENCE.md - Common commands and operations
- BUDGET_MANAGEMENT.md - Cost management and optimization strategies
The infrastructure is optimized for minimal cost (estimated as of January 2025, subject to change):
| Configuration | Cost/Month |
|---|---|
| Demo/Dev (F1 + Serverless SQL, mostly idle) | $0.84 - $3.50 |
| Light Production (B1 + Serverless SQL, active) | $15 - $20 |
| Traditional Setup (B1 + Basic SQL) | $18 - $25 |
Key cost-saving features:
- Serverless SQL Database - Auto-pauses after inactivity (~84-98% savings)
- Free App Service Option - F1 tier completely free for demos
- Local Redundant Storage - No geo-replication overhead
Note: Azure pricing changes frequently. Use the Azure Pricing Calculator for current estimates.
All infrastructure is defined in Bicep for:
- Version Control - Track infrastructure changes in Git
- Reproducibility - Consistent deployments across environments
- Automation - Integrate with CI/CD pipelines
- Documentation - Self-documenting infrastructure
See bicep/main.bicep and the modules/ directory for complete template details.
# Run all tests (600+ tests)
dotnet test
# Run tests with detailed output
dotnet test --verbosity normal
# Run specific test project
dotnet test src/Domain.Tests/
dotnet test src/Application.Tests/
dotnet test src/Infrastructure.Tests/
dotnet test src/WebUI.Tests/# Generate coverage report
dotnet test --collect:"XPlat Code Coverage"- Domain Tests: 365 tests - Business logic and entity behavior
- Application Tests: 3 tests - CQRS handler integration
- Infrastructure Tests: 65 tests - Data access and services
- WebUI Tests: 167 tests - Page model integration and workflows
- Total: 600+ passing tests
Test coverage includes:
- Entity creation and business rule validation
- Status transitions and workflow logic
- Domain service operations
- Command/query handler execution
- Repository operations with in-memory EF
- Authentication and authorization
- Event publishing and handling
- Error handling and edge cases
Database Connection Failures:
# Verify SQL Server LocalDB is installed
sqllocaldb info
# Create a new instance if needed
sqllocaldb create MSSQLLocalDB
sqllocaldb start MSSQLLocalDBPort Already in Use:
- The application runs on ports 5000 (HTTP) and 5001 (HTTPS)
- Change ports in
src/WebUI/Properties/launchSettings.json
SSL Certificate Issues:
# Trust the development certificate
dotnet dev-certs https --trustDemo Credentials Not Working:
- Check
src/WebUI/development-credentials.mdfor generated credentials - Delete the database and restart to regenerate demo data
- Database location:
%LOCALAPPDATA%\Microsoft\Microsoft SQL Server Local DB\Instances\MSSQLLocalDB\
Build Errors:
# Clean and rebuild
dotnet clean
dotnet restore
dotnet buildFor more issues, check the GitHub Issues page.
- Simple Demo Guide - Quick 4-step workflow demonstration showing core functionality
- Complete Domain Model Diagrams - Comprehensive technical documentation with 10+ detailed Mermaid diagrams
- Architecture Highlights - Portfolio-focused architectural overview
- Business Rules Documentation - Detailed business logic and validation rules
- Getting Started Guide - Development setup and deployment
- Development Setup - Local development configuration
- Architecture Implementation - Deep dive into architectural patterns
- Bicep Infrastructure Guide - Azure infrastructure overview and quick reference
- Deployment Guide - Detailed step-by-step deployment instructions
- Getting Started - Azure - Quick start checklist for Azure deployment
- Quick Reference - Common Azure commands and operations
- Budget Management - Cost optimization strategies
This project is licensed under the MIT License - see the LICENSE file for details.
- Clean Architecture principles by Robert C. Martin
- Domain-Driven Design by Eric Evans
- MediatR library by Jimmy Bogard
- .NET and ASP.NET Core teams at Microsoft