Final Project Structure
The new architecture follows the Clean Architecture pattern, with clearly separated layers and responsibilities:
Component | Description |
---|---|
Core | DI lifetimes and extension methods |
Model | Entities and DTOs |
Logic | Use cases and framework logic |
WinServices | Console apps and background services |
Websites | Three web apps: Public API, Customer Portal, Admin Panel |
Housekeeping & Cleanup
- Removed outdated test projects and proof-of-concepts, reducing total projects from 75 to 60.
- Organized the solution into structured folders aligned with architectural layers.
Migration POC
- Reviewed official .NET documentation and created proof-of-concepts for background services and web apps in the new environment.
Migration Strategy
- Inside-out approach: Migrated class libraries to .NET Standard 2.0 first.
- Moved
System.Web
dependencies out of reusable libraries and confined them to web-level projects.
Migration Priorities
- Queue Handler Service – Rebuilt critical parts and offloaded some components to AWS Lambda.
- API Layer – Migrated service endpoints and core logic to .NET 8.
- Admin Panel – Updated dashboard and admin tools for compatibility.
Key Challenges & Solutions
Decoupling web dependencies
System.Web
dependencies were tightly integrated across the codebase.
Solution: Used Unity DI to define interfaces and inject platform-specific implementations, allowing lower layers (Core, Model, Logic) to compile independently using .NET Standard.
Razor Template Engine
The legacy Razor engine was central to generating reports, customer views, and emails.
Solution: Replaced the built-in Razor engine with RazorEngineCore
, an open-source NuGet package supporting .NET Standard and .NET 8.
Replacing Legacy Charting
System.Web.UI.DataVisualization.Charting
was incompatible with .NET 8.
Solution: Migrated all reporting and visual chart elements to ScottPlot
, which is actively maintained and cross-platform compatible.
Migrating Entity Framework 6
The original codebase relied heavily on EF6.
Solution: Used the latest version of Entity Framework 6, which supports .NET 8, to maintain compatibility without rewriting all DB logic from scratch.
Async in Sync Contexts
Many updated NuGet packages (like Amazon.S3
) required async calls.
Solution: Used Nito.AsyncEx
to bridge async calls within sync workflows, avoiding large-scale rewrites while maintaining stability.
Additional Contributions
- Built a shared configuration layer for both legacy and .NET 8 environments.
- Ported Unity-based DI configuration to work seamlessly in .NET 8.
This migration demonstrates deep knowledge of architectural refactoring, legacy modernization, cross-platform dependency management, and incremental delivery within enterprise systems.