Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

984 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Work Order Management System

A work order management application built with .NET 10.0 implementing Onion Architecture. The system uses Blazor WebAssembly for the UI, Entity Framework Core for data access, MediatR for CQRS, and deploys to Azure Container Apps.

This codebase serves as both a working application and a teaching reference for software architecture. The 51 architectural patterns cataloged below are all demonstrated in the source code.

Solution Structure

src/
  Core/                  Domain layer — models, interfaces, queries (no dependencies)
  DataAccess/            EF Core, MediatR handlers (references Core only)
  Database/              DbUp schema migrations
  UI/Server/             Blazor Server host, Lamar DI
  UI/Client/             Blazor WebAssembly frontend
  UI/Api/                Web API endpoints
  UI.Shared/             Shared UI types
  LlmGateway/            Azure OpenAI integration
  Worker/                Background hosted service
  ChurchBulletin.AppHost/         .NET Aspire orchestration
  ChurchBulletin.ServiceDefaults/ Aspire service defaults
  UnitTests/             NUnit + Shouldly
  IntegrationTests/      NUnit, LocalDB / SQL Server / SQLite
  AcceptanceTests/       NUnit + Playwright

Prerequisites

  • .NET 10.0 SDK
  • One of the following database options:
    • Windows: SQL Server LocalDB (included with Visual Studio)
    • Linux/macOS with Docker: SQL Server 2022 runs automatically in a container
    • Linux/macOS without Docker: SQLite (automatic fallback)
  • PowerShell 7+ (cross-platform, required for build scripts)
  • Playwright browsers (for acceptance tests only)

Build

# Quick build (Windows)
.\build.bat

# Quick build (Linux/macOS)
./build.sh

# Full build — clean, compile, unit tests, DB migration, integration tests
. .\build.ps1 ; Build

# dotnet CLI directly
dotnet build src/ChurchBulletin.sln --configuration Release

Run Tests

# Unit tests
dotnet test src/UnitTests --configuration Release

# Integration tests
dotnet test src/IntegrationTests --configuration Release

# Acceptance tests (install Playwright browsers first)
pwsh src/AcceptanceTests/bin/Debug/net10.0/playwright.ps1 install
dotnet test src/AcceptanceTests --configuration Debug

Quick start — Run locally

The repository supports three common local development workflows. Pick the one that matches your environment.

  • Windows (Visual Studio / LocalDB)

    1. Open the solution in Visual Studio (ChurchBulletin.sln).
    2. Ensure LocalDB is available and your launch profile is configured.
    3. Run UI.Server from Visual Studio or:
      cd src/UI/Server
      dotnet run

    Note: Visual Studio launch profiles may override ConnectionStrings in launchSettings.json. Use the Environment configuration below if you need to override.

  • Linux / macOS (recommended with Docker)

    1. Start a SQL Server container:
      docker run --name churchbulletin-mssql \
        -e 'MSSQL_SA_PASSWORD=churchbulletin-mssql#1A' \
        -e 'ACCEPT_EULA=Y' \
        -p 1433:1433 \
        -d mcr.microsoft.com/mssql/server:2022-latest
    2. Set environment variables and run the server:
      export ConnectionStrings__SqlConnectionString="server=localhost,1433;database=ChurchBulletin;User ID=sa;Password=churchbulletin-mssql#1A;TrustServerCertificate=true;"
      export ASPNETCORE_ENVIRONMENT=Development
      # Must set APPLICATIONINSIGHTS_CONNECTION_STRING or set to an empty string to avoid the Azure Monitor exporter crashing:
      export APPLICATIONINSIGHTS_CONNECTION_STRING=""
      # Prevent the app from attempting to contact Azure OpenAI (leave empty if not used)
      export AI_OpenAI_ApiKey=""
      export AI_OpenAI_Url=""
      export AI_OpenAI_Model=""
      cd src/UI/Server
      dotnet run --no-launch-profile --urls "https://localhost:7174;http://localhost:5174"

    Important: use --no-launch-profile on Linux/macOS to avoid the Windows LocalDB connection string from launchSettings.json overriding your env vars.

  • SQLite fallback (no Docker)

    1. Set the database engine and run the build scripts:
      export DATABASE_ENGINE=SQLite
      cd src
      pwsh -NoProfile -ExecutionPolicy Bypass -File ./PrivateBuild.ps1

    The build scripts will use SQLite when Docker is not available.

Health and URLs

Architecture diagrams

  • See the arch/ folder for PlantUML sources and rendered images. The architecture docs (arch/README.md) explain rendering and icon configuration.
  • To regenerate PlantUML images locally: use the helper scripts:
    • PowerShell: pwsh arch/render-diagrams.ps1
    • Bash: ./arch/render-diagrams.sh
  • A CI job (.github/workflows/render-diagrams.yml) validates that diagram images are kept in sync on pull requests.
  • To install the optional pre-commit hook that re-renders diagrams when .puml files are staged, run the repository setup script.
    • Bash (Linux/macOS/Git Bash): ./scripts/setup-dev-env.sh
    • PowerShell (Windows): pwsh ./scripts/setup-dev-env.ps1

Playwright (acceptance tests)

  • Install browsers (PowerShell):
    pwsh src/AcceptanceTests/bin/Debug/net10.0/playwright.ps1 install
  • Run acceptance tests:
    dotnet test src/AcceptanceTests --configuration Debug

gRPC (work orders)

  • Protobuf contract: src/UI/Server/Protos/workorders.proto
  • Generated C# (checked in): src/UI/Server/Generated/Protos/
  • To regenerate the C# files after editing .proto, run the Grpc.Tools generation on an x64 machine and replace the checked-in generated files (Grpc.Tools can be unstable on ARM).

Architecture Patterns Reference

A catalog of 51 architectural patterns and design concepts demonstrated in this codebase, annotated with authoritative reference URLs suitable for student learning.


Domain & Application Architecture

1. Onion Architecture

Layered architecture where dependencies point inward. Inner layers define interfaces; outer layers implement them. Core has zero outward dependencies.

2. CQRS (Command Query Responsibility Segregation)

Separates read models (queries) from write models (commands), allowing each to be optimized independently.

3. Mediator Pattern

A behavioral design pattern where a mediator object encapsulates how objects interact, promoting loose coupling. Implemented here via the MediatR library.

4. Domain Model

An object model of the business domain that incorporates both behavior and data. Business logic lives inside the domain objects themselves.

5. Layer Supertype (Entity Base Class)

An abstract base class that provides common behavior (identity, equality) for all domain entities in a layer.

6. Value Object

An immutable object defined entirely by its attributes rather than a unique identity. Two value objects with the same attributes are considered equal.

7. Enumeration Class (Smart Enum)

Replaces primitive enum types with full classes that carry behavior, enabling richer domain modeling and avoiding primitive obsession.

8. State Machine Pattern

Objects transition through a set of defined states via validated transitions, preventing invalid state changes.

9. Repository Pattern

Abstracts data access behind a collection-like interface, decoupling the domain from persistence technology. Implemented implicitly via EF Core's DbContext.

10. Unit of Work

Tracks all changes made during a business transaction and commits them as a single atomic operation. Implemented implicitly via EF Core's SaveChanges.


Dependency Management & Wiring

11. Dependency Injection / Inversion of Control

Components declare their dependencies through constructor parameters; an external container resolves and provides them at runtime.

12. Service Registry

A well-known object that other objects use to find common services. Centralized registration of services in a single registry class.

13. Convention over Configuration

The framework automatically discovers and registers services by scanning assemblies, reducing explicit configuration in favor of naming and structural conventions.


UI & Presentation Architecture

14. Blazor WebAssembly (Client-Side SPA)

A single-page application framework that runs .NET code directly in the browser via WebAssembly, eliminating the need for JavaScript.

15. Server-Side Rendering with Client Hydration

Initial rendering occurs on the server for fast first paint; the client-side framework then takes over for interactivity.

16. Backend for Frontend (BFF)

A dedicated API layer tailored to the needs of a specific frontend, rather than a generic API serving all consumers.

17. Shared Kernel

A shared set of types and interfaces used across bounded contexts or UI boundaries, maintained as a single shared project.


Data & Persistence

18. Evolutionary Database Design (Database Migrations)

Incremental, versioned schema changes applied via numbered migration scripts, allowing the database to evolve alongside application code.


Infrastructure & Deployment

19. Containerization

Packaging an application and its dependencies into a lightweight, portable container image that runs consistently across environments.

20. Container Orchestration

A managed runtime that handles container deployment, scaling, networking, and revision management.

21. Continuous Integration

Automatically building and testing every code change when pushed, providing rapid feedback on integration errors.

22. Continuous Delivery

An automated pipeline that ensures code is always in a deployable state, from commit through testing environments to production.

23. Environment Parity (Dev/Prod Parity)

Keeping development, staging, and production environments as similar as possible to reduce deployment surprises.

24. Blue-Green / Revision-Based Deployment

Deploying a new version alongside the old one, then switching traffic, enabling zero-downtime releases and easy rollback.

25. Strangler Fig (Dual Pipeline)

Incrementally replacing a legacy system by routing functionality to a new implementation while the old one is gradually retired. Applied here to the migration from Azure DevOps to GitHub Actions.

26. Infrastructure as Code

Defining infrastructure declaratively in version-controlled files (ARM templates, pipeline YAML, Octopus OCL) rather than through manual configuration.

27. Configuration as Code

Deployment processes, variables, and settings stored as code in the repository, enabling versioning, diffing, and review of deployment configuration.

28. Semantic Versioning

A versioning scheme (MAJOR.MINOR.PATCH) with defined rules about when each number increments, communicating the nature of changes to consumers.

29. Immutable Build Artifacts

The same compiled artifact flows unchanged through all environments (TDD, UAT, Prod). What was tested is what gets deployed.

30. Approval Gates / Environment Promotion

Requiring manual reviewer approval before deploying to higher environments, enforcing governance over the release pipeline.

31. Release Management

Separating the concerns of "build" from "deploy" with a dedicated release management tool that tracks what version is in which environment.


Health & Observability

32. Health Endpoint Monitoring Pattern

Dedicated endpoints that report system health, enabling load balancers, orchestrators, and deployment pipelines to verify application readiness.

33. Health Check Gating (Deployment Verification)

Blocking deployment progression (e.g., acceptance test execution) until health endpoints confirm the application is ready.

34. Client-Side Health Checks (Distributed Health Monitoring)

Health checks executed from the client perspective (Blazor WASM) back to the server, providing end-to-end health visibility beyond server-side checks alone.


Testing Patterns

35. Test Pyramid

A layered testing strategy with many fast unit tests at the base, fewer integration tests in the middle, and a small number of end-to-end acceptance tests at the top.

36. Test Double (Stub Pattern)

Replacing real dependencies with simplified implementations ("stubs") during testing. This codebase uses the "Stub" prefix convention rather than "Mock."

37. Test Data Builder

Generating test data with fluent builder objects (via AutoBogus), producing valid domain objects without verbose manual construction.

38. Arrange-Act-Assert (AAA)

Structuring each test method into three phases: set up preconditions, execute the action under test, and verify the result.

39. Acceptance Testing with Browser Automation

End-to-end tests that drive a real browser to verify the application behaves correctly from the user's perspective.

40. Component Testing (bUnit)

Unit testing individual UI components in isolation by rendering them in a test host without a browser.

41. Multi-Database Engine Testing

Running the same test suite against multiple database engines (SQL Server, SQLite, LocalDB) to validate that data access logic is not vendor-specific.

42. Multi-Architecture CI (Platform Matrix Testing)

Running CI builds in parallel across multiple CPU architectures (x86_64, ARM64) to verify cross-platform compatibility.


Design Patterns (GoF & Other)

43. Factory Pattern

Creates objects without exposing the instantiation logic, letting subclasses or configuration determine which concrete class to create.


.NET Platform Patterns

44. Hosted Service / Background Worker

Long-running background tasks implemented as hosted services within the .NET generic host, running alongside the web application.

45. .NET Aspire (Service Orchestration)

Development-time orchestration of distributed services, wiring connection strings, health checks, and service discovery for local development.

46. Nullable Reference Types (Compile-Time Null Safety)

Static analysis annotations that help the compiler detect potential null reference errors at compile time rather than runtime.

47. NuGet Package as Deployment Artifact

Using the NuGet package format not just for library distribution but as the deployment unit that flows through the release pipeline.


AI / LLM Integration

48. AI/LLM Gateway Pattern

An abstraction layer between the application and AI services, encapsulating connection management, health checks, and model configuration.


Architecture Documentation

49. C4 Model

Documenting software architecture at four hierarchical levels of abstraction: System Context, Container, Component, and Code (Class).

50. 4+1 Architectural View Model

Describing architecture from five concurrent viewpoints: Logical, Development, Process, Physical, and Scenarios — each addressing different stakeholder concerns.

51. Architecture Documentation as Code

Maintaining architecture diagrams (PlantUML, Mermaid) as source files checked into version control alongside application code, enabling versioning, diffing, and review.

🕐 Last updated: 2026-03-25T21:50:00Z

Deployment Verification

Deployments are verified in the UAT environment before release.

Deployment Verification 20260727-081828

Deployment run 20260727-081828 is verified in the UAT environment before release.

Deployment Verification 20260727-090150

Deployment run 20260727-090150 is verified in the UAT environment before release.

Deployment Verification 20260727-094548

Deployment run 20260727-094548 is verified in the UAT environment before release.

Deployment Verification 20260727-132512

Deployment run 20260727-132512 is verified in the UAT environment before release.

Deployment Verification 20260727-201015

Deployment run 20260727-201015 is verified in the UAT environment before release.

Deployment Verification 20260727-210050

Deployment run 20260727-210050 is verified in the UAT environment before release.

Deployment Verification 20260727-222027

Deployment run 20260727-222027 is verified in the UAT environment before release.

Deployment Verification 20260727-231313

Deployment run 20260727-231313 is verified in the UAT environment before release.

Deployment Verification 20260728-000302

Deployment run 20260728-000302 is verified in the UAT environment before release.

Deployment Verification 20260728-041350

Deployment run 20260728-041350 is verified in the UAT environment before release.

Deployment Verification 20260728-200157

Deployment run 20260728-200157 is verified in the UAT environment before release.

Deployment Verification 20260728-203209

Deployment run 20260728-203209 is verified in the UAT environment before release.

Deployment Verification 20260728-210121

Deployment run 20260728-210121 is verified in the UAT environment before release.

Deployment Verification 20260728-220129

Deployment run 20260728-220129 is verified in the UAT environment before release.

Deployment Verification 20260729-012310

Deployment run 20260729-012310 is verified in the UAT environment before release.

Deployment Verification 20260729-060151

Deployment run 20260729-060151 is verified in the UAT environment before release.

Deployment Verification 20260729-172838

Deployment run 20260729-172838 is verified in the UAT environment before release.

Deployment Verification 20260729-203926

Deployment run 20260729-203926 is verified in the UAT environment before release.

About

Training application for Clear Measure's .NET Bootcamp including AI-driven development

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages