Learn More





DNN Community Blog

The Community Blog is a personal opinion of community members and by no means the official standpoint of DNN Corp or DNN Platform. This is a place to express personal thoughts about DNNPlatform, the community and its ecosystem. Do you have useful information that you would like to share with the DNN Community in a featured article or blog? If so, please contact .

The use of the Community Blog is covered by our Community Blog Guidelines - please read before commenting or posting.

DotNetNuke Tips and Tricks #20: Module Action Menu Links

Very early in the life of DotNetNuke, modules were fairly limited in their functionality.  Modules could have multiple behaviors attached to them by the framework which were displayed as a list of link buttons.  Very quickly this UI became very cumbersome as we continued to add more and more behaviors to the standard list of behaviors. This UI greatly limited the amount of actions that could be attached to a module and at the time the list of behaviors was fairly static. 

One of the first enhancements that I worked on for my own modules was the ability to create a menu that was attached to the module.   This menu was intended to be customizable by the module developer and the framework and would remove the space limitations that plagued the early framework.  When I showed Shaun the menus he instantly saw the potential and we incorporated them into the framework.

The module action menus were originally designed to be extremely flexible.  I wanted to be able to create links that could perform client-side actions as well as trigger events on the server side, depending on the needs of the module developer.  Many module developers have taken advantage of the server side functionality over the years, but I have not seen many modules which have taken advantage of the client-side functionality.  When I first created the menus, I documented the API using XML Comments, which were not being used anywhere else in the framework.  Until recently the project was not even publishing the API documentation, so these comments went largely unnoticed by the developer community.  I am happy to say that with 5.5 that has changed and the API documentation for the core framework is now available with the rest of the Community Edition download packages.

In this post I’ll walk through a few of the various options for the module action menus.  For my examples I’ll be forgoing the use of the many constructor overloads in favor of using the various properties which I think make the code more readable.

As most module developers are aware, the first step in using the Module Action Menus is to have your module implement the IActionable interface.  This interface defines a single property which returns a collection of ModuleActions.

Namespace DotNetNuke.Modules.MenuExample

  Partial Class View
    Inherits Entities.Modules.PortalModuleBase
    Implements DotNetNuke.Entities.Modules.IActionable

    Public ReadOnly Property ModuleActions As ModuleActionCollection 
			Implements ModuleActions

        Dim modActions As New ModuleActionCollection()
        Return modActions
      End Get
    End Property
  End Class

End Namespace

Inside of this property we’ll add whichever actions are appropriate for the module.  Using the module action menus, it is possible to define a JavaScript method which is called when the associated menu item is selected.  I usually use this in my own modules when I want to popup a form for the user that I have created using jQuery or some other client-side script.  This minimizes postbacks and makes for a much more responsive UI.

' JavaScript Example
Dim jsAction As New ModuleAction(ModuleContext.GetNextActionID())
With jsAction
  .Title = "JavaScript Example"
  .CommandName = ModuleActionType.AddContent
  .ClientScript = "alert('Isn\'t this cool!')"
  .Secure = Security.SecurityAccessLevel.Edit
End With

There are times when you will want to redirect the user to some specific URL within the current site or even on another site.  You might want to provide access to the latest documentation or link the user to the relevant support forum on your website.  This behavior is controlled by the URL property.

' URL Example
Dim urlAction As New ModuleAction(ModuleContext.GetNextActionID())
With urlAction
  .Title = "Url Example"
  .CommandName = "redirect"
  .Url = ""
  .Secure = Security.SecurityAccessLevel.Edit
End With

While linking to a URL is good, you will probably want to open the URL in a new window so that the user doesn’t lose their place on the website where they were using your module.  To do this, just set the NewWindow property to true.

' New Window Example
Dim newAction As New ModuleAction(ModuleContext.GetNextActionID())
With newAction
  .Title = "New Window Example"
  .CommandName = "newwindow"
  .Url = ""
  .NewWindow = True
  .Secure = Security.SecurityAccessLevel.Edit
End With

Occasionally, you will want to do some additional processing on the server-side before taking further action.  Setting the UseActionEvent will override the behavior of the URL setting and force a server side event to be triggered.

' URL Postback Example
Dim urlEventAction As New ModuleAction(ModuleContext.GetNextActionID())
With urlEventAction
  urlEventAction.Title = "Action Event Example"
  urlEventAction.CommandName = "redirect"
  urlEventAction.CommandArgument = "cancel"
  urlEventAction.Url = ""
  urlEventAction.UseActionEvent = True
  urlEventAction.Secure = Security.SecurityAccessLevel.Edit
End With

In order to respond to the event you will need to register an event handler in the Init event of your module control.

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init

  'Add an Action Event Handler to the Skin
  AddActionHandler(AddressOf MyActions_Click)
End Sub

Once you have registered the ActionHandler you are free to process the action using whatever business rules are appropriate for your specific module.

Private Sub MyActions_Click(ByVal sender As Object, ByVal e As Entities.Modules.Actions.ActionEventArgs)
  Skins.Skin.AddModuleMessage(Me, _
	  String.Format(Localization.GetString("ClickMessage", LocalResourceFile), e.Action.CommandName), _

Select Case e.Action.CommandName.ToLowerInvariant
  Case "redirect"
    If e.Action.CommandArgument.ToLowerInvariant <> "cancel" Then
      Skins.Skin.AddModuleMessage(Me, _
        "Canceled the Redirect", _
        End If
  End Select
End Sub

This post highlights just a few of the hidden capabilities of the Module Action Menu.  I urge you to take a few minutes in the documentation exploring some of the features.  I also recommend that you examine some of the many examples of how others are using Module Action Menus.  The HTML/Text module is a great place to start.



I have done this in my DNN 6 installation and it worked great. Now that I upgraded to DNN 7, it doesn't work anymore. What changed? Is there a way I can make it work?

Thank you!
Mona Thursday, February 20, 2014 8:10 AM (link)

Comment Form

Only registered users may post comments.


2sic Daniel Mettler (124)
Aderson Oliveira (15)
Alec Whittington (11)
Alex Shirley (10)
Andrew Nurse (30)
Anthony Glenwright (5)
Antonio Chagoury (28)
Ash Prasad (22)
Ben Schmidt (1)
Benjamin Hermann (25)
Benoit Sarton (9)
Beth Firebaugh (12)
Bill Walker (36)
Bob Kruger (5)
Brian Dukes (2)
Brice Snow (1)
Bruce Chapman (20)
Bryan Andrews (1)
cathal connolly (55)
Charles Nurse (163)
Chris Hammond (203)
Chris Paterra (55)
Clinton Patterson (28)
Cuong Dang (21)
Daniel Bartholomew (2)
Dave Buckner (2)
David Poindexter (3)
David Rodriguez (2)
Doug Howell (11)
Erik van Ballegoij (30)
Ernst Peter Tamminga (74)
Geoff Barlow (6)
Gifford Watkins (3)
Gilles Le Pigocher (3)
Ian Robinson (7)
Israel Martinez (17)
Jan Blomquist (2)
Jan Jonas (3)
Jaspreet Bhatia (1)
Jenni Merrifield (6)
Joe Brinkman (270)
John Mitchell (1)
Jon Henning (14)
Jonathan Sheely (4)
Jordan Coopersmith (1)
Joseph Craig (2)
Kan Ma (1)
Keivan Beigi (3)
Ken Grierson (10)
Kevin Schreiner (6)
Leigh Pointer (31)
Lorraine Young (60)
Malik Khan (1)
Matthias Schlomann (15)
Mauricio Márquez (5)
Michael Doxsey (7)
Michael Tobisch (3)
Michael Washington (202)
Mike Horton (19)
Mitchel Sellers (28)
Nathan Rover (3)
Navin V Nagiah (14)
Néstor Sánchez (31)
Nik Kalyani (14)
Peter Donker (52)
Philip Beadle (135)
Philipp Becker (4)
Richard Dumas (22)
Robert J Collins (5)
Roger Selwyn (8)
Ruben Lopez (1)
Ryan Martinez (1)
Salar Golestanian (4)
Sanjay Mehrotra (9)
Scott McCulloch (1)
Scott S (11)
Scott Wilkinson (3)
Scott Willhite (97)
Sebastian Leupold (80)
Shaun Walker (237)
Shawn Mehaffie (17)
Stefan Cullmann (12)
Stefan Kamphuis (12)
Steve Fabian (31)
Timo Breumelhof (24)
Tony Henrich (3)
Torsten Weggen (2)
Vicenç Masanas (27)
Vincent Nguyen (3)
Vitaly Kozadayev (6)
Will Morgenweck (37)
Will Strohl (163)
William Severance (5)
Try Evoq
For Free
Start Free Trial
a Demo
See Evoq Live
Need More Information?