Skip to content

Conversation

sachatrauwaen
Copy link
Contributor

@sachatrauwaen sachatrauwaen commented Sep 12, 2025

MVC Module Control Implementation

Overview

The MVC Module Control implementation provides a modern alternative to DNN's traditional WebForms-based module rendering pipeline. This new system enables DNN modules to leverage ASP.NET MVC architecture while maintaining compatibility with the existing DNN framework.

Problem Statement

DNN Platform has historically relied on the WebForms pipeline accessed through /default.aspx. As outlined in MVC pipeline - Module Pipeline / Module rendering #6679

Solution: Hybrid Pipeline Architecture

The MVC Pipeline introduces a dual-rendering mechanism:

  1. Legacy Pipeline: Traditional WebForms through /default.aspx
  2. New MVC Pipeline: Modern MVC rendering through /DesktopModules/Default/Page/{tabId}/{locale}

Module Pipeline Support Matrix

Based on the GitHub issue specifications, modules can support different pipeline patterns:

WebForms Support MVC Module Support SPA Module Support
Custom Control + Razor view Use generic Control + Custom MVC Controller as child controller (shared with WebForms pipeline) Use generic Control + return directly the html (shared with WebForms pipeline)
Render Razor Partial The generic control redirects to the controller defined in Control Src The generic Control renders the html file defined in Control Src

Module Control Class Configuration

Modules specify their MVC compatibility through:

  • MVC Control Class: Defined in module control settings and module manifest (not yet implemented)
  • Interface Implementation: Must implement IMvcModuleControl
  • Optional Interfaces: Can implement IActionable for unified action handling
  • Pipeline Detection: System can determine module compatibility and show appropriate messages

Class Diagram

classDiagram
    %% Interfaces
    class IMvcModuleControl {
        <<interface>>
        +Html(helper) IHtmlString
    }

    class IModuleControl {
        <<interface>>
        
        +string ControlPath
        +string ControlName
        +ModuleInstanceContext ModuleContext
        +string LocalResourceFile
    }
    

     %% Concrete Classes
     class MvcModuleControl {
         +Html(helper) IHtmlString
     }
     note for MvcModuleControl "MVC controller"

    class SpaModuleControl {
        +Html(helper) IHtmlString
    }
    note for SpaModuleControl "Html with tokens"

    %% Abstract Classes
    
    class DefaultMvcModuleControlBase {
        +Html(helper) IHtmlString
    }

    class RazorModuleControlBase {
        
        +Invoke() IRazorModuleResult
    }
    note for RazorModuleControlBase "Razor view from model"

    %% Relationships
    IMvcModuleControl ..|> IModuleControl : extends

    DefaultMvcModuleControlBase ..|> IMvcModuleControl : implements
    
    MvcModuleControl --|> DefaultMvcModuleControlBase : extends
    RazorModuleControlBase --|> DefaultMvcModuleControlBase : extends
    SpaModuleControl --|> DefaultMvcModuleControlBase : extends
    

Loading

Core Components

1. IMvcModuleControl Interface

public interface IMvcModuleControl : IModuleControl
{
    IHtmlString Html(HtmlHelper htmlHelper);
}

The base interface that all MVC module controls must implement, extending the standard IModuleControl with MVC-specific rendering capabilities. This interface enables:

  • Pipeline Compatibility Detection: The system can determine if a module supports the MVC pipeline
  • Unified Rendering: The Html() method provides access to HtmlHelper with information about HttpContext, controller, and page model
  • Flexible Rendering Options: Modules can use HTML helpers to render content (Razor partials, child action controllers, or other helpers)

2. DefaultMvcModuleControlBase

The abstract base class that provides common functionality for all MVC module controls:

  • Dependency Injection: Integrated service provider access
  • Module Context: Access to DNN module configuration and settings
  • Portal Context: Portal settings, user information, and localization
  • Resource Management: Localization helpers and resource file management
  • URL Generation: Helper methods for creating edit URLs

Key Features:

  • Service scoped dependency injection
  • Automatic resource file path resolution
  • Portal and user context access
  • Module settings management
  • Edit URL generation with MVC support

3. Module Control Implementations

MvcModuleControl

The standard MVC module control for traditional MVC controllers and actions.

Features:

  • Parses .mvc control source to extract controller and action names
  • Supports routing with namespaces: {namespace}/{controller}/{action}
  • Automatic query string parameter mapping
  • Route value dictionary construction for MVC action execution
  • Localization resource file resolution

Control Source Format:

{namespace}/{controller}/{action}.mvc

SpaModuleControl

Specialized control for Single Page Applications.

Features:

  • HTML5 file rendering with token replacement
  • Automatic CSS and JavaScript file inclusion
  • File existence caching for performance
  • Support for HTML5 module token system
  • Content caching with file dependency tracking

Supported Files:

  • .html or custom HTML5 files
  • Automatic .css file inclusion (same name)
  • Automatic .js file inclusion (same name)

RazorModuleControlBase

Abstract base for modules using Razor view rendering.
This use MVC 5 razor views.
Recomended for Weforms control migrations.
Folows the ViewComponent patern of .net Core for easy future trasition to .net Core

Features:

  • Direct Razor view rendering
  • Model binding support
  • Custom view context management
  • Flexible view name resolution
  • Request/Response context integration

Usage Pattern:

public class MyModuleControl : RazorModuleControlBase
{
    public override IRazorModuleResult Invoke()
    {
        var model = GetMyModel();
        return View("MyView", model);
    }
}

4. Extension Methods (MvcModuleControlExtensions)

Provides convenient extension methods for all MVC module controls:

  • Localization: LocalizeString(), LocalizeSafeJsString()
  • URL Generation: EditUrl() with various overloads
  • Settings Access: GetModuleSetting<T>() with type conversion
  • State Checking: EditMode(), IsEditable()

5. Resource Management

IResourcable Interface

Modules can implement this interface to automatically manage CSS and JavaScript resources.

ModuleResources System

  • Automatic resource registration
  • Priority-based loading
  • File existence validation
  • Caching for performance
  • Independent of the pipeline

6. Utilities

MvcModuleControlRenderer

Provides rendering capabilities for Razor-based module controls outside of the normal MVC pipeline.

MvcViewEngine

A powerful utility class for rendering MVC views to strings outside of the standard MVC request pipeline.
It runs only inside a httpcontext.
It can render a razor partial or a Html helper to a string.
It differ from the actual RazorEngine in the fact that it use mvc 5 razor syntax an can use all features of a mvc 5 partial (@model, Html helper, ...).

Core Methods:

// Render full view with layout
string html = MvcViewEngine.RenderView("~/Views/MyView.cshtml", model);

// Render partial view without layout
string partial = MvcViewEngine.RenderPartialView("~/Views/_MyPartial.cshtml", model);

// Render HtmlHelper delegates
string html = MvcViewEngine.RenderHtmlHelperToString(helper => 
    helper.Action("MyAction", "MyController"), model);

Wrapper Implementation for WebForms

The WebForms folder includes demonstration classes that show practical implementation examples:

WrapperModule.cs

A WebForms-compatible module that bridges to the MVC pipeline, demonstrating how to integrate MVC module controls within the traditional DNN WebForms infrastructure.

Key Features:

  • Hybrid Bridge Pattern: Inherits from PortalModuleBase to maintain WebForms compatibility
  • MVC Integration: Uses MvcUtils.CreateModuleControl() to instantiate MVC module controls
  • MvcViewEngine Integration: Demonstrates MvcViewEngine.RenderHtmlHelperToString() usage
  • Interface Support: Handles IActionable and IResourcable interfaces automatically
  • Lifecycle Management: Proper ASP.NET control lifecycle implementation

Implementation Pattern:

public class WrapperModule: PortalModuleBase, IActionable
{
    protected override void OnInit(EventArgs e)
    {
        // Create MVC module control
        var mc = MvcUtils.CreateModuleControl(this.ModuleConfiguration);
        
        // Render using ViewRenderer
        html = MvcViewEngine.RenderHtmlHelperToString(helper => mc.Html(helper));
        
        // Handle optional interfaces
        if (mc is IActionable actionable)
            this.ModuleActions = actionable.ModuleActions;
            
        if (mc is IResourcable resourcable)
            resourcable.RegisterResources(this.Page);
    }
}

Demo Implementation

The Demo folder includes demonstration classes that show practical implementation examples:

DemoModuleControl.cs

A concrete implementation of RazorModuleControlBase showing how to create custom MVC module controls with dynamic view selection.

Key Features:

  • Dynamic View Routing: Uses query string parameters to determine which view to render
  • Multiple View Support: Demonstrates rendering different views based on user input
  • Custom View Paths: Shows how to specify custom view file locations
  • Model Passing: Illustrates passing data models to views

Implementation Example:

public class DemoModuleControl : RazorModuleControlBase
{
    public override IRazorModuleResult Invoke()
    {
        // Dynamic view selection based on query parameters
        switch (Request.QueryString["view"])
        {
            case "Terms":
                return View("~/Views/Default/Terms.cshtml", "Terms content");
            case "Privacy": 
                return View("~/admin/Portal/Views/Privacy.cshtml", "Privacy content");
            default:
                return View("~/admin/Portal/Views/Terms.cshtml", "Default content");
        }
    }
}

Usage Scenarios:

  • **Migration **: Use WrapperModule to run MVC controls within WebForms pages
  • Development Reference: DemoModuleControl shows best practices for Razor module implementation
  • Integration Patterns: Demonstrates how to handle multiple interfaces (IActionable, IResourcable)
  • View Management: Shows flexible view path configuration and model binding

Bridge Pattern Benefits:
The WrapperModule demonstrates the bridge pattern that allows:

  • Gradual migration from WebForms to MVC
  • Using MVC controls within existing WebForms infrastructure
  • Maintaining compatibility with existing DNN module architecture
  • Automatic handling of module actions and resource registration

Remarks about db modifications

There is a sql migration scripts in this pull request created on version 10.99.00 for testing.

  • core 10.99.00.SqlDataProvider

@sachatrauwaen sachatrauwaen self-assigned this Sep 19, 2025
@sachatrauwaen sachatrauwaen changed the title [WIP] Module control MVC pipeline - Module control Sep 19, 2025
@sachatrauwaen sachatrauwaen marked this pull request as ready for review September 19, 2025 12:59
@sachatrauwaen sachatrauwaen moved this to In review in MVC pipeline Sep 19, 2025
@sachatrauwaen sachatrauwaen removed their assignment Sep 20, 2025
@bdukes bdukes added this to the Future: Major milestone Sep 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

2 participants