A comprehensive repository demonstrating the evolution of a .NET application from a legacy Web Forms architecture using the Model-View-Presenter (MVP) pattern to a modernized, container-ready Blazor application.
This repository is split into two main project tracks to demonstrate modernization strategies:
A "legacy" simulated application built using ASP.NET Web Forms (.NET Framework 4.8). It implements a strict MVP pattern to decouple business logic from the Web Forms lifecycle.
- Core: Domain entities (
Product.cs) and repository/service contracts. - Infrastructure: Data access via SQLite and Dapper, including a simple custom IoC container for Dependency Injection.
- Presentation: Contains the Presenters and View interfaces that drive the UI.
- Web: The actual ASP.NET Web Forms project (.aspx pages).
A modern take on the same functional requirements using .NET 9 and Blazor.
- ProductApp.Domain: Clean domain models.
- ProductApp.Application: Application services and business logic.
- ProductApp.Infrastructure: Modern data persistence.
- ProductApp.Web: A modern Blazor Web UI.
├── source
│ ├── MyModelViewPresenter/ # Legacy Web Forms Track
│ │ ├── Core/ # Domain entities & Interfaces
│ │ ├── Infrastructure/ # SQLite Repositories & DI Container
│ │ ├── Presentation/ # MVP Presenters & View Interfaces
│ │ └── Web/ # ASP.NET Web Forms UI
│ ├── MVPModernized/ # Modern .NET 9 Track
│ │ ├── ProductApp.Domain/ # Modern Domain Layer
│ │ ├── ProductApp.Application/ # Business Logic
│ │ ├── ProductApp.Infrastructure/ # Data Access
│ │ └── ProductApp.Web/ # Blazor Web Application
│ └── Denormalization/ # Support utilities & Docker tools
The legacy project demonstrates how to make Web Forms maintainable and testable:
- Model: Encapsulated in the
ProductServiceandProductRepository. - View: ASP.NET
.aspxpages implement a C# interface (e.g.,IProductView). - Presenter: A pure C# class that handles events from the View and interacts with the Service layer.
The modern track moves toward a layered architecture:
- Decoupling: Infrastructure and UI both depend on the Application and Domain layers.
- Testability: Designed for easy unit and E2E testing.
- Single Responsibility: Separate classes for data access, business logic, and UI orchestration.
- Dependency Inversion: High-level modules depend on abstractions (Interfaces), not concrete implementations.
- Visual Studio 2022 or JetBrains Rider.
- .NET Framework 4.8 (for Legacy track).
- .NET 9 SDK (for Modern track).
- SQLite (used as the database for both tracks).
- Open
source/MyModelViewPresenter/MyModelViewPresenter.sln. - Set the
Webproject as the Startup Project. - The SQLite database is automatically initialized in
App_Data/products.dbon the first run.
- Open
source/MVPModernized/MVPModernized.sln. - Run the
ProductApp.Webproject.
The repository includes multiple testing strategies:
- Unit Tests: Located in
ProductApp.Tests, focusing on service logic. - E2E Tests: Found in
ProductApp.Tests.E2E, utilizing Playwright for automated browser testing.
The project includes GitHub Action workflows for both tracks:
build.yml: Handles MSBuild and NuGet restoration for the .NET Framework legacy app.mvp-modernized-ci.yml: A modern CI pipeline for .NET 9, including unit tests, Playwright E2E tests, and code analysis.
- Implementing a REST API layer for the legacy application to support a "Strangler Fig" migration pattern.
- Adding containerization (Docker) for the modernized Blazor application.
- Integrating a centralized logging framework (Serilog/NLog).