WepNG_MVC Evolution Plan: From Monolith to Modern Architecture
1. Executive Summary
The WepNG_MVC solution is a classic "Big Ball of Mud" Monolith:
- Architecture: Tightly coupled (Controller -> Direct DB Access).
- Logic: Scattered between "God Controllers" (e.g.,
HomeController.cs), "Transaction Scripts" (ComponentServices), and Views. - Quality: No automated testing found. Dead code and hardcoded IDs are prevalent.
- Risk: High. Changing one part likely breaks another due to shared
EITWEP.Model(God Object).
1.1 Risk Assessment
| Risk Category | Severity | Likelihood | Impact Description | Mitigation Strategy |
|---|---|---|---|---|
| Regression | Critical | High | Touching EITWEP.Model breaks WepNG_OMGT or WepNG_Public. | Automated Regression Tests (Phase 1). Feature Toggles. |
| Data Integrity | High | Medium | "Anemic" models rely on controllers for validation; missed validation leads to bad data. | Move validation to Domain Entities (Phase 3). |
| Knowledge Loss | Medium | High | Logic hidden in WepNG_Business (745 OMGT items) is undocumented. | "Archaeology" documentation during refactoring. |
| Performance | High | Medium | N+1 queries in loops and synchronous I/O block IIS. | MiniProfiler & Async/Await (Phase 2). |
| Obsolescence | Critical | Certain | .NET Framework 4.8 is a legacy platform. Risk of EOL/Security issues. | Mandatory Migration to latest .NET (Active Support) via Hybrid Strangler. |
[!NOTE] For a deep dive into the Core Engine architecture, see OMGT Module Analysis.
For a deep dive into the Back Office (Performance Bottleneck), see BO Module Analysis.
2. Pillar 1: Maintainability (Stop the Bleeding)
The immediate goal is to stabilize the codebase and enable safe refactoring.
Strategies
- The "Boy Scout" Rule:
- Rule: Touch a file -> Clean it.
- Action: Remove commented-out code (Git is your history). Fixing indentation.
- Introduce Automated Testing:
- Problem: No safety net.
- Action: Create a
WepNG.Tests(xUnit/NUnit) project. - Start Small: Don't try to mock the DB yet. Test pure logic (static helpers, string manipulation, math).
- Static Analysis:
- Tool: SonarQube or Roslyn Analyzers.
- Goal: Identify "Dead Code", unused variables, and SQL injection risks.
Immediate "Quick Wins"
- Delete
WepNG_OMGT/Controllers/HomeController.cscommented blocks: It accounts for ~20-30% of the file size. - Centralize Strings/IDs: Move hardcoded IDs (e.g.,
1788,"SE53224") to aConstantsclass or Configuration.
2.1 Concrete "Quick Wins" & Fixes
The code review revealed specific patterns that can be fixed immediately:
A. The "Swallow Exception" Pattern
Problem: 100+ occurrences of catch (Exception) { } or catch (Exception e) { // do nothing }. This hides bugs and makes debugging impossible.
Example: WADataFeeder.cs, AspnetUserList.cs (Line 251).
Fix: Remove the try/catch or at least log the exception.
B. Business Layer Leaking HTTP
Problem: WepNG_Business should be agnostic of the web context, but it's full of HttpContext.Current.Cache (2700+ hits).
Example: AccomodationTypeNGList.cs (Line 124).
Fix: Inject an ICacheProvider interface. This is required for Step 4 (Headless) and Step 1 (Unit Testing).
C. Hardcoded Paths ("It works on my machine")
Problem: Hardcoded C:\Temp\ paths will fail in containers or other servers.
Example:
WepPartnerOMGTsController.cs:C:\Temp\partner_jsv.xlsxKeyNoteNGsController.cs:c:\temp\Fix: UseServer.MapPathor a configurableAppSetting.
D. The "Loop of Death" (OMGT Specific)
Problem: WepPartnerOMGTsController.Ts() iterates over all partners and calls a service that opens a new connection and saves changes for each one.
Example: WepPartnerOMGTsController.cs (Line 30).
Impact: 1000 Partners = 1000 DB Connections + 1000 Transactions.
Fix: Batch processing or Stored Procedure.
3. Pillar 2: Performance (Bottlenecks & Modernization)
Current performance issues are likely due to synchronous I/O and N+1 queries in loops.
Strategies
- Profiling First:
- Action: Install MiniProfiler in
WepNG_OMGT. - Goal: Visualize the SQL generated by those
foreachloops in Controllers.
- Action: Install MiniProfiler in
- Async/Await Adoption:
- Current: Synchronous actions block IIS threads.
Task.Runis used in some services (e.g.,ACLTestOMGTComponentService). - Decision (Jan 2026): While
Task.Runhas pitfalls in ASP.NET, it is kept for now as the benefits outweigh the immediate cons. See ADR-008 for details. - Target: Change ComponentService methods to
EnsureAsync(). Convert Controllers toasync Task<ActionResult>. - Guideline: See Async Strategy.
- Tactical Plan: See Async Migration Plan for prioritized hotspots.
- Evolution: For critical background tasks like payment processing, transition from
Task.Runto formal Task Queues (e.g., Hangfire or external messaging) to ensure persistence and reliability.
- Current: Synchronous actions block IIS threads.
- Database Optimization:
- Finding:
SolveFeeTitleiterates allCultureForLanguageand allOrderFeeLines. This is O(N*M) complexity. - Fix: Move batch processing logic to Stored Procedures or optimized LINQ queries (Server-side evaluation).
- Finding:
4. Pillar 3: Domain-Driven Design (DDD)
We cannot "install" DDD. We must extract it.
Current State
- Anemic Domain Model:
ACLTestOMGTis just data getters/setters. - Logic in UI:
HomeControllerorchestrates business rules.
Transition Strategy
- Identify Bounded Contexts:
- Core:
OMGT(Order Management). - Support:
CRM(Customer Relations),CMS(Content).
- Core:
- The "Service Layer" Refactoring:
- Stop: Writing logic in Controllers.
- Start: Use the Command/Query Separation (CQS) pattern.
- Example: Instead of
HomeController.CopyTicketForGroup, create aCopyTicketCommandand aCopyTicketHandler.
- Rich Domain Models:
- Move logic into the entity.
- Before:
if (order.Status == "Paid") { order.SendEmail(); }(in Controller) - After:
order.MarkAsPaid();(Entity method handles state change and triggers events).
5. Pillar 4: Headless & Decoupling (The Future)
Moving towards a frontend-agnostic backend.
Strategy: "API First"
- Stop adding MVC Views:
- For new features, do NOT create a
.cshtmlfile. - Create a REST API endpoint in
WepNG_API(or a specificWepNG.ModernAPIproject). - Create a client-side app (Vue/React) or even simple HTML/JS that consumes this API.
- For new features, do NOT create a
- Decouple the Monolith:
- Treat
WepNG_Businessas a NuGet package (conceptually) used by the API. - The API should return DTOs (Data Transfer Objects), never Entity Framework entities (avoids Serialization loops and leaks).
- Treat
6. Strategic Directive: Platform Lifecycle Management
To avoid the risk of operating on unsupported or vulnerable frameworks (End of Life - EOL), the project mandates a continuous update strategy.
Requirement: Stay on "Active Support" LTS
- Current Status: Legacy Monolith on .NET Framework 4.8 (Supported but "Classic").
- Target State: All new development (ModernAPI) must target the latest .NET Long Term Support (LTS) version (currently .NET 8, moving to .NET 10 etc.).
- Policy:
- No New Legacy Code: New modules must not lock us further into .NET Framework 4.8.
- Proactive Upgrade: The
WepNG.ModernAPIsidecar must be kept up-to-date with .NET LTS cycles to ensure access to latest security patches and performance improvements.
7. Database Health & "Blind Spots"
Why I didn't ask for access: Direct DB access is risky/blocked in many environments. I prioritized code analysis to see how the app interacts with it.
- Findings from Code:
- Context Size:
WEPV2DataContexthas 840+ DbSets. This is massive. Startup time is likely slow. - Hidden Logic:
Database.SqlQuery<int>(sqlQuery)found inWADataFeeder.csandOrderOMGTList.cssuggests strictly coupled SQL logic (potential stored procs or complex views) not visible in C#. - Relations: EF Navigation properties exist, but manual joins in LINQ (seen in
HomeController) suggest indices might be missing or FKs are not trusted.
- Context Size:
- Blind Spots:
- Stored Procedures: Are there 10 or 1000? Code calls them but doesn't define them.
- Triggers: "Magic" data changes?
- Data Volume: Is
OrderOMGT10k rows or 10M? (Affects migration strategy).
8. Alternative Options
What are we not doing?
Option A: The "Big Bang" Rewrite (Rejected)
- Concept: Build
WepNG_vNextfrom scratch in .NET 8. - Pros: Clean slate, latest tech.
- Cons: High Fail Rate. Business logic is lost; years of debugging are discarded. Feature freeze required (impossible).
Option B: The "Strangler Fig" (Recommended)
[!TIP] See the detailed Strangler Fig Pattern guide for comprehensive implementation steps specific to WepNG.
- Concept: Build new features in a new
WepNG.APIand proxy traffic. Slowly kill the old app. - Pros: Low risk, immediate value.
- Cons: Complexity of maintaining two systems (SSO, Data Sync).
6. Implementation Roadmap
Phase 1: Stabilization (Weeks 1-4)
- Setup
WepNG.Testsproject. - Install MiniProfiler to identify worst offenders.
- Clean
HomeController(Delete dead code).
Phase 2: Pilot Refactoring (Weeks 5-8)
- Pick ONE small feature (e.g.,
ACLTestOMGT). - Extract
ACLTestOMGTComponentServicelogic into a Command Handler. - Write Unit Tests for the Handler.
- Expose basic API endpoint for it.
Phase 3: Scaling (Month 3+)
- Systematically apply "Async/Await".
- Split
WepNG_Businessinto separate libraries (Wep.Core.Orders,Wep.Core.Crm) to enforce separation.
Appendix A: Alignment with Internal Audit (Jan 2026)
Context: The Expected Architectural Audit established a "Renovate, Don't Demolish" baseline.
1. Analysis of "Microservices First"
Recommendation: REJECTED.
Reasoning: Transforming a coupled Monolith with high Transaction Density (OrderMGT) into microservices would create a distributed distributed consistency nightmare.
- Decision: Adhere to the Modular Monolith. We will split code namespaces, not physical servers.
2. Analysis of "Dockerization"
Recommendation: ACCEPTED (Hybrid Strategy). Reasoning:
- Discovery: The Data Layer (
EITWEP.Model) uses Entity Framework 6.4.4, which is compatible with .NET Standard 2.1. This unlocks .NET 8 on Linux. - Strategy: Adopt a Hybrid Strangler Fig approach.
- Containerize the Legacy Monolith (Windows Containers) for CI stability.
- Build new features in a side-by-side .NET 8 API (Linux Containers) sharing the Data Layer.
- Detail: See Docker & .NET Migration Strategy for the complete roadmap.
- Decision: Proceed with Phase 1 (Windows Containers for Build) immediately.
3. Analysis of "Continuous Deployment"
Recommendation: ACCEPTED (High Priority). Reasoning: This is the fundamental enabler for all future evolution. Without an automated pipeline verifying tests, every refactoring is a high-risk operation.