ASP.Net MVC Modular Component Architecture

I have started adding a little bit more structure to our ASP.Net MVC project to start separating out the various components.  We needed to do this to create a framework that allowed multiple people to work on the application and modularize the code to make it more maintainable.

The basic architecture is to separate the various components in the web application in to the HTML and JavaScript components to reduce the coupling between them.   The HTML is moved in to Partial Views, similar to controls under Web Forms, and the JavaScript is separated in to a namespace hierarchy with separate modules for each of the components.

Partial Views

Separate the various components of the website in to partial views to allow them to be designed independently, shared between views, and to simplify the layout of the page.  This is very similar to how controls work in WebForms.

To do this, create a virtual page:

  1. Select the view directory to place the partial view, “Common” for those shared between different controllers, or in the View folder related to the controller, and select “Add->View”.
  2. Give the view a name, select “Create a partial view (.ascx)”, and “Add” the partial view.
  3. Copy the HTML layout in to the partial view.
    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
    <div id="TimedPopup" class="popup hide">
      <div class="popupHeader">
        <div class="popupTitle">Message</div>
      </div>
      <div class="TimedMessageStyle">
        <div id="TimedMessageText"></div>
      </div>
    </div>
  4. Insert the Partial View in to the Views where it is needed.
       <% Html.RenderPartial("TimedPopup"); %>

Create the Namespace

Namespaces can be used to separate the code in to different separate blocks to avoid naming conflicts.

The namespaces that I we are using for our project is:

  • S1S: Root namespace for all code
  • UI: User interface code
  • <component>: The individual component code
  1. Define the namespace
    For this component the namespace will be “S1S.UI.TimedPopup”
  2. Add the component to the directory tree
    The scripts directory is segmented in to a hierarchy that maps to the namespace.  Add the component under the appropriate directory.  In this case add “TimedPopup.js” to “~/Scripts/S1S/UI”.
  3. Add the namespace setup to the javascript file
    Create the appropriate variables, being careful not to destroy previous objects.

    if (typeof S1S == "undefined" || !S1S) {
    S1S = {};
    }
    if (typeof S1S.UI == "undefined" || !S1S.UI) {
    S1S.UI = {};
    }

 Create the Component Module

  1. Now create a module for the actual logic for the component.  Use a basic module based on the following format:
    S1S.UI.TimedPopup = (function() {
     
      // Private Stuff Here
     
      return {
        // Public Stuff Here 
        Display: function(message) {
        }
      }
    } ());
  2. Implement the component functionality
    Finally implement the component functionality encapsulating the functionality in the module.  For instance you could have a private event handler:

    S1S.UI.Error = (function() {
      /* Close the Popup */
      var onOK = function() {
        $('#ErrorMessage').hide();
        $('#blanket').hide();
      };
     
      return {
        /* Display the Popup */
        Display: function(errorText) {
          // stuff
          $('#OK').one("click", onOK);
          }
        }
    } ());
  3. Use the Component
    To use the component, first add the JavaScript file to the view:

    <script src="<%= Url.Content("~/Scripts/S1S/UI/TimedPopup.js") %>" type="text/javascript"></script>

    and call the method as required:

    S1S.UI.TimedPopup.Display("Item successfully added!");