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
Get
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
modActions.Add(jsAction)
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 = "http://www.dotnetnuke.com"
.Secure = Security.SecurityAccessLevel.Edit
End With
modActions.Add(urlAction)
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 = "http://www.dotnetnuke.com"
.NewWindow = True
.Secure = Security.SecurityAccessLevel.Edit
End With
modActions.Add(newAction)
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 = "http://www.dotnetnuke.com"
urlEventAction.UseActionEvent = True
urlEventAction.Secure = Security.SecurityAccessLevel.Edit
End With
modActions.Add(urlEventAction)
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), _
ModuleMessage.ModuleMessageType.BlueInfo)
Select Case e.Action.CommandName.ToLowerInvariant
Case "redirect"
If e.Action.CommandArgument.ToLowerInvariant <> "cancel" Then
Response.Redirect(e.Action.Url)
Else
Skins.Skin.AddModuleMessage(Me, _
"Canceled the Redirect", _
ModuleMessage.ModuleMessageType.YellowWarning)
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.