posted on Friday, February 22, 2008 8:20 AM |

If you have been writing your own DotNetNuke modules for any amount of time you have probably run across the concept of Inter-Module Communication (IMC for short). IMC particularly refers to the facility that the DotNetNuke framework provides to allow data to be passed between modules during the ASP.Net page life cycle. It is a very elegant solution for passing data between modules, on the server side. That said, it tends to be a topic that most first-time IMC users have trouble getting right. The documentation is thin, and there aren’t too many examples out there. So in this article we will be tackling this subject as well as taking a look at a few examples.

In my follow-up post I want to discuss alternative ways for modules to communicate. There are numerous ways to pass data between modules, both on the server and on the client side.We will see how to use JavaScript, DNN Event Messaging, Bubbling Events, Control Nesting, the DNN Client API, ASP Sessions, and the Query String, all to communicate between modules.

That is a lot to cover, so let’s get started!

DotNetNuke Inter-Module Communication (IMC)

As general as the term “Inter-Module Communication” may sound, when DNN module developers use the term IMC they are specifically referring to the facility within the DNN framework which allows you to use VB.Net or C# in your code-behind in order to pass information between modules. IMC communication always occurs somewhere within the ASP.Net page life cycle. Therefore this method of passing data between modules requires exactly one execution of the page life cycle. If user interaction is required to trigger the communication, then a post-back will need to occur from the browser to trigger the page life cycle in which the IMC will take place.

How IMC Works

IMC functionality is divided into two parts: Communicating (sending messages) and Listening (receiving messages). In order to add one or both of these functionalities to a modules, you must have the module class implement the respective IMC interfaces which the DNN Framework has defined for you.

The IModuleCommunicator and IModuleListener Interfaces

Both IModuleCommunicator and IModuleListener live inside the DotNetNuke.Entities.Modules.Communications namespace, so you may find it convenient to reference these namespaces at the top of your code. You will find that I have included such references throughout my examples.

Implementing the IModuleCommunicator interface allows your module to dispatch messages to all the modules on the page that are listening for IMC messages. On the flip side of the equation, implementing the IModuleListener interface allows your module to receive all the messages sent from modules on the same page.

Implementing IModuleCommunicator

To implement IModuleCommunicator all you need to do is define an instance of the ModuleCommunicationEvenHandler delegate as an event named ModuleCommunication within your class.

 

C# Example:

using System;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Communications;

public partial class SampleCommunicatorCS : 
    PortalModuleBase, IModuleCommunicator
{
    public event ModuleCommunicationEventHandler ModuleCommunication;
}

VB Example:

Imports DotNetNuke.Entities.Modules
Imports DotNetNuke.Entities.Modules.Communications

Partial Class SampleCommunicatorVB
    Inherits PortalModuleBase
    Implements IModuleCommunicator

    Public Event ModuleCommunication(ByVal sender As Object, _
        ByVal e As ModuleCommunicationEventArgs) _
        Implements IModuleCommunicator.ModuleCommunication
End Class

 

When you implement the IModuleCommunicator interface, the DotNetNuke framework knows that your module has an instance of the ModuleCommunicationEventHandler delegate type named ModuleCommunication. This guarantees that the DotNetNuke core can wire-up to your module so that it can be notified when you raise an IMC communication event. Somewhere deep in the DNN core code, there is likely a line that adds an event handler to your delegate if your module implements IModuleCommunicator:

 

if (yourModuleInstance is IModuleCommunicator)
{
    yourModuleInstance.ModuleCommunication +=
        new ModuleCommunicationEventHandler(notifyIMCListeners);
}

 

By doing this, the DNN core can respond to every ModuleCommunication event that your module raises.

You Raise a ModuleCommunication Event to Send an IMC Message

Sending an IMC message is as simple as raising your module's ModuleCommunication event. In C# you simply call ModuleCommunication(...), passing to it a reference to your module, and an instance of ModuleCommunicationEventArgs.

 

ModuleCommunication(this, mcArgs);

 

To raise the ModuleCommunication event in VB.Net, you use the RaiseEvent keyword in addition to calling ModuleCommunication(...), passing to it a reference to your module, and an instance of ModuleCommunicationEventArgs.

 

RaiseEvent ModuleCommunication(Me, mcArgs)

 

Creating the Event Args Object

When you raise the ModuleCommunication event you are required to pass in an instance of the ModuleCommunicationEventArgsDotNetNuke class which is found in the Entities.Modules.Communications namespace. This class is like an envelope that you use to send IMC messages out to other modules. You need to instantiate a copy and set its properties before you pass it to the ModuleCommunication call.

 

C# Example:

// the IMC message data gets stored inside
// a ModuleCommunicationEventArgs object
ModuleCommunicationEventArgs mcArgs = 
    new ModuleCommunicationEventArgs();
mcArgs.Sender = "SampleCommunicatorModule";
mcArgs.Target = "Arbitrary Text";
mcArgs.Text = "Your payload text";
mcArgs.Type = "Your custom type";
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("path/to/xml/doc.xml");
mcArgs.Value = xmlDoc;

// if ModuleCommunication is null,
// the cache settings for your module
// might need to be set to 0 (turned off)
if (ModuleCommunication != null)
{
    // calling your ModuleCommunication delegate event
    // will cause the event to be raised
    ModuleCommunication(this, mcArgs);
}

VB Example:

Dim mcArgs As ModuleCommunicationEventArgs _
    = New ModuleCommunicationEventArgs()

mcArgs.Sender = "SampleCommunicatorModule - VB"
mcArgs.Target = "Arbitrary Text"
mcArgs.Text = "Your Payload Text"
mcArgs.Type = "Your Custom Type"
Dim xmlDoc As System.Xml.XmlDocument = New System.Xml.XmlDocument()
xmlDoc.Load("path/to/xml/doc.xml")
mcArgs.Value = xmlDoc

RaiseEvent ModuleCommunication(Me, mcArgs)

 

All of the ModuleCommunicationEventArgs properties can be used any way you see fit. It is important to remember that every IMC message that your module sends out will be received by every module that implements IModuleListener. There are no built-in mechanisms for directing IMC messages to particular modules. Therefore, it is up to the module developer to establish their own consistent use of the ModuleCommunicationEventArgs properties in order to identify the messages that a particular module needs to listen for.

 The Sender, Target, Text, and Type properties of the ModuleCommunicationEventArgs class are of type String. The Value property is of type object. In the example above I set the Value property to an instance of XmlDocument just to demonstrate that you can pass types other than String in this property.

Implementing IModuleListener

In order for your module to receive IMC messages it must implement the IModuleListener interface. This interface requires your class to have a method named OnModuleCommunication which takes two parameters, and Object type and a ModuleCommunicationEventArgs type, respectively.

C# Example:

using System;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Communications;

public partial class SampleListenerCS : 
    PortalModuleBase, IModuleListener
{
    public void OnModuleCommunication(object s, 
        ModuleCommunicationEventArgs e)
    {
        throw new NotImplementedException();
    }
}

VB Example:

Imports DotNetNuke.Entities.Modules
Imports DotNetNuke.Entities.Modules.Communications

Partial Class SampleListenerVB
    Inherits PortalModuleBase
    Implements IModuleListener

    Sub OnModuleCommunication(ByVal s As Object, _
                              ByVal e As ModuleCommunicationEventArgs) _
        Implements IModuleListener.OnModuleCommunication

    End Sub
End Class

 

Your OnModuleCommunication Method Executes Every Time Any Module Raises a ModuleCommunication Event

When you implement the IModuleListener interface the DotNetNuke framework automatically adds your OnModuleCommunication method to the delegate that responds to all the ModuleCommunication events. When your OnModuleCommunication method is executed, it is passed a reference to the module that raised the ModuleCommunication even, this is the first argument of your OnModuleCommunication method. Your method also gets passed the ModuleCommunicationEventArgs object that contains all the information that was defined by the object that raised the event.

ModuleCommunicationEventArgs is Key

The ModuleCommunicationEventArgs objec is the key piece of the IMC framework because it is the single channel in which the communication happens. Anything placed into the ModuleCommunicationEventArgs object from inside the module that raises the ModuleCommunication event gets passed along to every OnModuleCommunication method of the modules that implement the IModuleListener interface.

 

Full Examples For Your Dissecting Pleasures - C#

Communicator XML File in C# - SampleCommunicatorCS.ascx:

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeFile="SampleCommunicatorCS.ascx.cs" 
    Inherits="SampleCommunicatorCS" %>

 

Communicator Code-Behind File in C# - SampleCommunicatorCS.ascx.cs:

using System;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Communications;
using System.Xml;

public partial class SampleCommunicatorCS : 
    PortalModuleBase, IModuleCommunicator
{
    public event ModuleCommunicationEventHandler ModuleCommunication;

    protected void Page_Load(object sender, EventArgs e)
    {
        // the IMC message data gets stored inside
        // a ModuleCommunicationEventArgs object
        ModuleCommunicationEventArgs mcArgs = 
            new ModuleCommunicationEventArgs();
        mcArgs.Sender = "SampleCommunicatorModule";
        mcArgs.Target = "Arbitrary Text";
        mcArgs.Text = "Your payload text";
        mcArgs.Type = "Your custom type";
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load("path/to/xml/doc.xml");
        mcArgs.Value = xmlDoc;

        // if ModuleCommunication is null,
        // the cache settings for your module
        // might need to be set to 0 (turned off)
        if (ModuleCommunication != null)
        {
            // calling your ModuleCommunication delegate event
            // will cause the event to be raised
            ModuleCommunication(this, mcArgs);
        }
    }
}

Listener XML File in C# - SampleListenerCS.ascx:

<%@ Control Language="C#" AutoEventWireup="true" 
    CodeFile="SampleListenerCS.ascx.cs"
    Inherits="SampleListenerCS" %>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>

 

Listener Code-Behind in C# - SampleListenerCS.ascx.cs:

using System;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Communications;

public partial class SampleListenerCS : 
    PortalModuleBase, IModuleListener
{
    public void OnModuleCommunication(object s, 
        ModuleCommunicationEventArgs e)
    {
        if (e.Target == "Pizza Inspectors")
        {
            if(e.Text.ToLower().Contains("garlic")
            {
                Label1.Text = "Garlic Detected In Pizza";
            }
        }
    }
}

 

Full Examples For Your Dissecting Pleasures - VB

 

Communicator XML File in VB - SampleCommunicatorVB.ascx

<%@ Control Language="VB" AutoEventWireup="true"
     CodeFile="SampleCommunicatorVB.ascx.vb" 
     Inherits="SampleCommunicatorVB" %>

Communicator Code-Behind in VB - SampleCommunicatorVB.ascx.vb

Imports DotNetNuke.Entities.Modules
Imports DotNetNuke.Entities.Modules.Communications

Partial Class SampleCommunicatorVB
    Inherits PortalModuleBase
    Implements IModuleCommunicator

    Public Event ModuleCommunication(ByVal sender As Object, _
        ByVal e As ModuleCommunicationEventArgs) _
        Implements IModuleCommunicator.ModuleCommunication

    Protected Sub Page_Load(ByVal sender As Object, _
                            ByVal e As System.EventArgs) Handles Me.Load

        Dim mcArgs As ModuleCommunicationEventArgs _
            = New ModuleCommunicationEventArgs()

        mcArgs.Sender = "SampleCommunicatorModule - VB"
        mcArgs.Target = "Arbitrary Text"
        mcArgs.Text = "Your Payload Text"
        mcArgs.Type = "Your Custom Type"
        Dim xmlDoc As System.Xml.XmlDocument = New System.Xml.XmlDocument()
        xmlDoc.Load("path/to/xml/doc.xml")
        mcArgs.Value = xmlDoc

        RaiseEvent ModuleCommunication(Me, mcArgs)

    End Sub
End Class

 

Listener XML File in VB - SampleListenerVB.ascx

<%@ Control Language="VB" AutoEventWireup="false" 
    CodeFile="SampleListenerVB.ascx.vb" 
    Inherits="SampleListenerVB" %>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>

 

Listener Code-Behind in VB - SampleListenerVB.ascx.vb

Imports DotNetNuke.Entities.Modules
Imports DotNetNuke.Entities.Modules.Communications

Partial Class SampleListenerVB
    Inherits PortalModuleBase
    Implements IModuleListener

    Sub OnModuleCommunication(ByVal s As Object, _
                              ByVal e As ModuleCommunicationEventArgs) _
        Implements IModuleListener.OnModuleCommunication
        If e.Target = "Pizza Inspectors" Then
            If e.Text.ToLower.Contains("garlic") Then
                Label1.Text = "Garlic Detected In Pizza!"
            End If
        End If

    End Sub
End Class
Comments Leave Yours...
Aaron
2/27/2008 2:07 PM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Perfect! thanks for the write up exactly the tutorial I was looking for.

Rafe Kemmis
2/27/2008 7:59 PM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Glad you found it useful Aaron.

Patrick
2/29/2008 1:14 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

I read your article and implemented in in my module. However, I have a problem. On the event my ModuleCommunication object is null. Does it has to do something with the cache of the module? I have set it to 0.

Perhaps you have an answers to my problem?

Thanks in advance

Rafe Kemmis
2/29/2008 7:32 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Patrick,

There are two different cache settings. Make sure they're both sent to 0. The first setting is on the module instance's settings page, in the Page Settings section. The second cache setting is inside your module definition, you can find it under Host menu > Module Definitions > Your Module Name.

I'd be happy to take a look at your code if you're still having troubles. Just email me. (rafe at surfingdogsoft.com)

Andrea
3/13/2008 5:29 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

very helpful

Diogy
3/19/2008 8:28 PM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Hi Rafe,

Thanks for sharing this article. However, I've also experienced ModuleCommuncator being null. I'm using DotNetNuke 4.8 and SmartDNNModule for my C# user controls. My cache settings are already in 0. Is there anything else I should be checking?

Rafe Kemmis
3/28/2008 6:33 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Diogy, I'm not quite sure what might be going on. Feel free to email me your code, or at least some more details as to your problem. You might also jump on the dnn forums @ dotnetnuke.com.

Bernd T.
4/23/2008 2:47 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Hi Rafe

Thanks for that tutorial - I'm looking forward to your next articles in this series regarding the alternative ways of IMC (client-side, ...)

greetings,
Bernd

Attila
6/16/2008 9:08 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Nice article very specific. Thanks!

Vee
6/19/2008 6:06 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Interesting & useful article there!

Do you know if I can use it to pass data between modules in different pages?

Rafe
6/19/2008 8:26 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Vee,

As you know, the method I've described here only works for sending messages between module instances on the same page, within a single ASP.Net page life-cycle. IMC can not send message between pages, or between two separate page life-cycles (between post-backs).

I think the best solution is to create your own ad-hoc messaging system by storing and checking for messages in a custom database table. If your modules already have a data-access layer written, then the code to add ad-cod messaging should be minimal.

Another alternative is to just use the query-string to pass values between pages. Ultimately this option might not be appropriate because the data has to be sent out to the client before it reaches the destination page.

Eric
6/25/2008 10:50 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Thank you. It is a very nice article!

Sarkie
10/10/2008 4:50 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

Very nice and concise article, thumbs up!

smitaM
10/21/2008 6:08 AM
# re: DotNetNuke Inter-Module Communication or: How Your Modules Can Get Their Chat On

thanx for the very useful article :)

Post Your Comment

Title
Required
Name
Required
Email
Optional
Url
Optional
Comment  
Please add 5 and 2 and type the answer here:

Who Is Rafe

rafe

I Am Rafe Kemmis

I am an audacious entrepreneur with a double bachelor of science in Computer Science and Mathematics. I specialize in Microsoft ASP.Net web application development as well as accredited information systems auditing.

Questions?

Always a thoughtful response. You may post your question on an article, or contact me directly.

Hire Me.

I provide custom solutions to complex problems. I can help your business no matter how large or small.

Contact me now.

Subscribe