Thoughts from the Wet Coast

The musings of an ASP.NET Developer from Canada's We(s)t Coast

Module Development in DNN 8: 6 - Handling Module Actions in MVC and SPA modules

Category: DotNetNuke
Last Modified: May 2 2017
Jul 15 2015

This blog was originally posted on the DNN Community blog

DNN 8 will support creating modules using ASP.NET MVC version 5.1 (or later) as well as using a SPA (Single Page Application) module using HTML 5, JavaScript and ASP.NET Web API.  In previous blogs in this series I have described how these modules can be built and I have shown how localization is handled.  One topic still to describe is how both of these approaches can register module actions so they show on DNN’s module action menu.

ModuleAction attribute

I will start with how Module Actions can be registered for MVC modules.  In a Web Form’s code-behind file you can add Module Actions by implementing the IActionable interface.  This approach is not possible in an MVC Controller as the Controller can have many “Views” and each View would need its own set of Module Actions.  We therefore decided to add a new ModuleAction attribute implemented as an MVC Action Filter.  This attribute allows you to define a Module Action.

Listing 1: The ModuleAction Attribute

   1:  [HttpGet]
   2:  [ModuleAction(ControlKey = "Edit", TitleKey = "AddContact")]
   3:  public ActionResult Index()
   4:  {
   5:      var contacts = _repository.GetContacts(PortalSettings.PortalId);
   7:      return View(contacts.ToList());
   8:  }

Each ModuleAction attribute will add a single Module Action to the Module Actions menu.  In this case, the Module Action is the “Edit” action and its title is defined by the Localization key “AddContact”.  The ModuleAction attribute exposes the following properties:

  • ControlKey – the key used to identify the Module Control to load
  • Icon – the Url for the Icon to use
  • SecurityAccessLevel – the SecurityAccessLevel setting
  • Title – the title (text) displayed in the Actions menu
  • TitleKey – the localization key for the Title (if present this overrides the Title setting)

Each ModuleAction attribute defines a single Module Action.  For complex modules this could mean that an Action method could have a lot of ModuleAction attributes.  In addition the attribute only defines a subset of the ModuleAction properties – it is designed to provide a simple solution to cover the 80% use case.  To cover more complex situations we have also included a ModuleActionItems attribute.

ModuleActionItems attribute

The ModuleActionItems attribute is also implemented as an Action Filter.  It has two parameters:

  • Type – the type of a class (if not present this will default to the current Controller)
  • MethodName – the name of a method to call in the class defined by the Type parameter.  If not present this defaults to “Get{ActionMethos}Actions” where {ActionMethod} is the name of the Action Method where the attribute is applied.

As an example lets replace the single ModuleAction attribute in Listing 1 with the ModuleActionItems attribute.  The code changes are shown in Listing 2.

Listing 2: The ModuleActionItems attribute

   1:  [ModuleActionItems]
   2:  public ActionResult Index()
   3:  {
   4:      var contacts = _repository.GetContacts(PortalSettings.PortalId);
   6:      return View(contacts.ToList());
   7:  }
   9:  private ModuleActionCollection GetIndexActions()
  10:  {
  11:      var actions = new ModuleActionCollection();
  13:      actions.Add(new ModuleAction(-1)
  14:                  {
  15:                      CommandName = ModuleActionType.AddContent,
  16:                      CommandArgument = String.Empty,
  17:                      Icon = String.Empty,
  18:                      Title = LocalizeString("AddContact"),
  19:                      Url = ModuleContext.EditUrl("Edit"),
  20:                      Secure = SecurityAccessLevel.Edit,
  21:                      UseActionEvent = false,
  22:                      Visible = true,
  23:                      NewWindow = false
  24:                  });
  26:      return actions;
  27:  }

Essentially the ModuelActions attribute works just like IActionable, returning a collection of module actions.

Module Actions in SPA modules

One of the tenets of SPA modules is that they are built using a Single Page Application style.  This essentially means that the module shouldn’t need any Module Actions to load a secondary “page”.  However for completeness we have added a ModuleAction token.  The ModuleAction Token works like the other JSON based tokens I described in my previous blog, and works like the ModuleAction attribute exposing the same set of parameters.

  • controlKey
  • icon
  • securityAccessLevel
  • title
  • titleKey

It also adds an extra parameter so you can identify the “localResourceFile” to use for the titleKey field.  For example the token for the Edit ModuleAction used above would be:

(ModuleAction : {controlKey: “Edit”, securityAccessLevel : “Edit”,  titleKey: ”AddContent”, localResourceFile:”~/DesktopModules/Dnn/ContactList/App_LocalResources/ContactList.resx” })

*Note - as this blog uses token replace to render its templates, I have replaced the square token syntax with a normal (). 

So now you can add Module Actions to your MVC or SPA modules – have fun with this new development style and let us know what you think.

For more information


The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.