ASP.NET MVC Modules

ASP.NET MVC Modules is an open source framework for web development in .NET written in C#. It allows packing all resources in the DLL: css, views, icons, and scripts with fallback to the Areas for possible overrides.

Challenge

ASP.NET MVC meets all our needs, yet the suggested Microsoft solution has the limitations of supplementary actions. These are the typical cases:

  • We have a modern application with a rich front-end and REST JSON API behind.
  • Working with ASP.NET MVC, how should we deploy the module? We need to copy a couple of files to the Scripts, Bin, Content, or Views folders. Some of them are stored in main folders and the others are in the Areas.
  • How does the Java world work? Literally, “Place your WAR file into the WebApps folder.”

As a result, we have packed everything in one DLL: code, scripts, views, and resources for particular components. Just copy your DLL file into a bin folder of your site and update the web.config.

 

 

Why ASP.NET MVC Modules

Initially, we had made a large platform with several customizations for the dozens of enterprise customers. It resulted in a half a hundred of the Visual Studio solutions with five hundred projects shared between them.

mvc web framework

Therefore, we decided to forget the Areas and go our own way. Common parts should be maintainable—no script issues during the deployment.

mvc library

How ASP.NET MVC Modules works

With ASP.NET MVC Modules, you can pack all resources in the DLL: css, views, icons, and scripts with fallback to the Areas for possible overrides. As a result, it allows creating traditional modules in the ASP.NET applications independently. It does not mean a common DLL or shared API; it stands for “applications” or “Areas” as per ASP.NET MVC terms. It works for the cases when the particular modules are completely unaware of each other. Moreover, each module uses the MVC pattern in its infrastructure.

A few lines of glue code is enough to make these modules join one big application. For instance, adding new elements to the menu bar is a result of copying one or two more DLLs to a bin folder. These “modular” DLLs register their own resource paths according to their names. They sound as follows: Storage.DLL exposes /Storage route, in the same manner as for “Area”.

User Guide

ASP.NET MVC Modules follows the same approach to the MVC pattern as that of the traditional ASP.NET MVC, but with minor differences.

In other words, ASP.NET MVC Modules is a framework that provides completely familiar tools for developers but has more advantages.

Configuration

Unlike the Java world with server-side support, to let our MVC web framework start and run, you need two things:

  1. Register modules during the application’s startup.
  2. Configure IIS in such a way that all requests are processed with the managed code.

Registration

It is a simple matter, just add the following line:

public class MvcApplication : System.Web.HttpApplication

   {

       protected void Application_Start()

       {

           MvcModules.Start();

        ...

           RouteConfig.RegisterRoutes(RouteTable.Routes);

           BundleConfig.RegisterBundles(BundleTable.Bundles)

       }

   }

All necessary components and providers will be registered.

IIS Web.config update

It is not enough to register our module loader; the IIS handles static files independently by default. We need to instruct IIS not to use StaticFileModule with its caching and bypass all the requests through our code.

The complete magic is described below:

<system.webServer>

  <modules runAllManagedModulesForAllRequests="true" />

  <handlers>

     <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />

     <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />

     <remove name="ExtensionlessUrlHandler-Integrated-4.0" />

    
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />

     <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />

     <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />


     <remove name="IISGotcha-JS" />

     <remove name="IISGotcha-CSS" />

     <remove name="IISGotcha-JPG" />

     <remove name="IISGotcha-GIF" />

     <remove name="IISGotcha-PNG" />

     <remove name="IISGotcha-SWF" />

     <remove name="IISGotcha-DEF" />

     <remove name="IISGotcha-SVG" />

     <remove name="IISGotcha-HTML" />

     <remove name="IISGotcha-WOFF" />

     <remove name="IISGotcha-TTF" />


     <add name="IISGotcha-JS" path="*.js" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-CSS" path="*.css" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-JPG" path="*.jpg" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-GIF" path="*.gif" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-PNG" path="*.png" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-SWF" path="*.swf" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-DEF" path="*.default" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-SVG" path="*.svg" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-HTML" path="*.html" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-WOFF" path="*.woff" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

     <add name="IISGotcha-TTF" path="*.ttf" verb="GET,HEAD" type="System.Web.StaticFileHandler" />

   
  </handlers>

</system.webServer>

The simple line is not enough here, and we reregister handlers by hand in the right order.

<system.webServer>

    <modules runAllManagedModulesForAllRequests="true" />

 </system.webServer>

Hello World Module

Let’s try to make a new module from scratch. First, we need a core application to insert our module into.

Take a look at how we integrate the module with the main application:

@Html.ActionLink("Hello page", "Index", "Hello",

   new { Area = "HelloModule" }, null)

It is not the only possible way, but it illustrates our approach most accurately. We strictly adhere to the Microsoft recommendations, so our bicycle has no square tyres and looks like the well-known Areas.

ASP.NET MVC usual application

To create the module with the message “Hello World” in an ASP.NET application, take the following steps:

  1. Add a new empty ASP.NET MVC Web Application in Visual Studio to .NET Framework 4.6;
  2. Install our ASP.NET MVC Modules, log4net, and Microsoft.AspNet.Web.Optimization and bootstrap (use NuGet to pin it to your new project);
  3. Add a file named BundleConfig.cs to the App_Start folder and use the code below:
using System.Web.Optimization;

namespace hello_module

{

   public class BundleConfig

   {

       // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862

       public static void RegisterBundles(BundleCollection bundles)

       {

           bundles.Add(new StyleBundle("~/Content/css").Include(

                   "~/Content/bootstrap.css"

               ));

       }

   }

}
  1. Remove an AreaRegistration.RegisterAllAreas() line and add our module init call, as stated below:
using com.scand.MvcModules;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.Mvc;

using System.Web.Optimization;

using System.Web.Routing;


namespace hello_module

{

   public class MvcApplication : System.Web.HttpApplication

   {

       protected void Application_Start()

       {

           MvcModules.Start();

           RouteConfig.RegisterRoutes(RouteTable.Routes);

           BundleConfig.RegisterBundles(BundleTable.Bundles)

       }

   }

}

5. Add a classic MVC structure to the project—views, controllers, and a layout for a Home page:

 

  1. Add the System.Web.Optimization namespace to the system.web.webPages.razor section in the web.config file from the Views folder:
<system.web.webPages.razor>

   <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral,
 PublicKeyToken=31BF3856AD364E35" />

   <pages pageBaseType="System.Web.Mvc.WebViewPage">

     <namespaces>

          <add namespace="System.Web.Mvc" />

           <add namespace="System.Web.Mvc.Ajax" />

           <add namespace="System.Web.Mvc.Html" />

<add namespace="System.Web.Optimization"/>

       <add namespace="System.Web.Routing" />

       <add namespace="test" />

     </namespaces>

   </pages>

 </system.web.webPages.razor>
  1. Add a container with the menu to the _Layout.cshtml file:
<!DOCTYPE html>

<html>

<head>

   <meta name="viewport" content="width=device-width" />

   <title>@ViewBag.Title</title>

   @Styles.Render("~/Content/css")

</head>

<body style="padding-top: 50px">

   <div class="navbar navbar-inverse navbar-fixed-top">

       <div class="container">

           <div class="navbar-collapse collapse">

               <ul class="nav navbar-nav">

                   <li>

                       @Html.ActionLink("Home page", "Index", "Home", new { Area = "" }, null)

                   </li>

                   <li>

                       @Html.ActionLink("Hello page", "Index", "Hello", new { Area = "HelloModule" }, null)

                   </li>

               </ul>

           </div>

       </div>

   </div>

   <div class="container body-content">

       @RenderBody()

   </div>

</body>

</html>

As soon as we have an application, let’s create a module for it.

ASP.NET MVC Module creation

The next step is creating a new module and using it in the main application.

  1. Add a new Class Library project named “HelloModule” and .NET Framework 4.6 to the application.
  2. Install the MVC Modules and MVC NuGet in the created project.
  3. Rename empty class “Class1.cs” to  “MvcModule.cs”.
  4. Add the following code to the MvcModule.cs file:
using com.scand.MvcModules;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;


namespace HelloModule

{

   public class MvcModule : MvcModuleBase

   {

       public override string DefaultController { get { return "Hello"; } }

       public override string DefaultAction { get { return "Index"; } }


       protected override void Init()

       {

           // register some bundles

           base.Init();

       }

   }

}
  1. Add the “Controllers” and “Views” folders to the project:

 

  1. Add the HelloController class to the Controllers folder and insert the code given below:
using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Web.Mvc;

namespace HelloModule.Controllers

{

   public class HelloController : Controller

   {

       public ActionResult Index()

       {

           ViewBag.Message = "Hello World!";

           return View();

       }

   }

}
  1. Create a new folder named “Hello” in the “Views” folder.
  2. Create a new file by the name of “Index.cshtml” in this folder.
  3. Change the Build Action property to “Embedded resource”.
  4. Add the code mentioned below to create a file:
@{

   ViewBag.Title = "Hello Page";

   Layout = "~/Views/Shared/_Layout.cshtml";

}

<h1>My Hello Page with MVC Module</h1>

@ViewBag.Message

The implementation of our simple module is completed.

Add the resulting DLL to the bin folder of the main application and do not forget to update the IIS config, as described above in the section “IIS Web.config update”.

You can run the application anytime and see the “Hello World” message:

 

As far as you can notice, the module is very similar to the standard ASP.NET MVC application, but it uses MvcModuleBase as a parent class instead of MVC Application.

Downloads

Binaries with examples

Binaries only

Source code

Customization

You can request any specific features you need — and order the development of your own custom solution, fast and cost-effective

Require a similar product development?

Support

Browse
Attachment: filename ×

Thank you for your interest in our products! We have received your message and will reply to you as soon as possible. Please check your mailbox for a confirmation letter from us.