Replace Tokens with My Tokens

To skip the details, jump directly to production ready VB.NET or C# code at the end of this page.

Direct Calls

If you have the source code of the component you want to integrate with and you know My Tokens will always be available you can link directly to avt.MyTokens.Core.dll. To tokenize content the simply make calls to avt.MyToken.MyTokensReplacer.ReplaceTokensAll, that has the following prototype:

VB.NET

Shared Function ReplaceTokensAll( _
    ByVal strSourceText As String, _
    ByVal cUser As UserInfo, _
    ByVal dbgMsg As Boolean, _
    ByVal cModule As ModuleInfo) As String

C#

static string ReplaceTokensAll(
    string strSourceText, 
    UserInfo cUser, 
    bool dbgMsg, 
    ModuleInfo cModule
);

VB.NET - Invoking MyTokens directly outside of Module scope:

strContent = avt.MyTokens.MyTokensReplacer.ReplaceTokensAll( _
    strContent, _
    UserInfo, _
    Not DotNetNuke.Common.Globals.IsTabPreview(), _
    Nothing
)

Invoking MyTokens directly from Module scope - note the additional parameter:

    strContent = avt.MyTokens.MyTokensReplacer.ReplaceTokensAll( _
        strContent, _
        UserInfo, _
        Not DotNetNuke.Common.Globals.IsTabPreview(), _
        ModuleSettings _
    )

C# - Invoking MyTokens directly outside of Module scope:

    strContent = avt.MyTokens.MyTokensReplacer.ReplaceTokensAll(
        strContent,
        UserInfo,
        !DotNetNuke.Common.Globals.IsTabPreview(),
        null
    );

Invoking MyTokens directly from Module scope - note the additional parameter:

    strContent = avt.MyTokens.MyTokensReplacer.ReplaceTokensAll(
        strContent,
        UserInfo,
        !DotNetNuke.Common.Globals.IsTabPreview(),
        ModuleSettings
    );

Using Reflection

Most often, you can’t rely on MyTokens being installed. Using the code above would cause a compiler error since the type is not known. It’s desirable that token replacement runs only when MyTokens is installed and reverts to a default behavior when it’s not.

VB.NET

Invoking MyTokens using reflection outside of Module scope

strContent =
    DotNetNuke.Framework.Reflection.CreateType("avt.MyTokens.MyTokensReplacer").InvokeMember( _
        "ReplaceTokensAll", _
        System.Reflection.BindingFlags.InvokeMethod, _
        Nothing, _
        Nothing, _
        New [Object]() { _
            strContent, _
            UserInfo, _
            Not DotNetNuke.Common.Globals.IsTabPreview(), _
            Nothing
        } _
    )

Invoking MyTokens using reflection from Module scope - note the additional parameter

strContent =
    DotNetNuke.Framework.Reflection.CreateType("avt.MyTokens.MyTokensReplacer").InvokeMember( _
        "ReplaceTokensAll", _
        System.Reflection.BindingFlags.InvokeMethod, _
        Nothing, _
        Nothing, _
        New [Object]() { _
            strContent, _
            UserInfo, _
            Not DotNetNuke.Common.Globals.IsTabPreview(), _
            ModuleConfiguration _
        } _
    )

C#

Invoking MyTokens using reflection outside of Module scope


strContent =
    DotNetNuke.Framework.Reflection.CreateType("avt.MyTokens.MyTokensReplacer").InvokeMember(
        "ReplaceTokensAll", 
        System.Reflection.BindingFlags.InvokeMethod, 
        null, 
        null, 
        new object[] { 
            strContent, 
            UserInfo, 
            !DotNetNuke.Common.Globals.IsTabPreview(),
            null 
        }
    ).ToString();

Invoking MyTokens using reflection from Module scope - note the additional parameter

strContent =
    DotNetNuke.Framework.Reflection.CreateType("avt.MyTokens.MyTokensReplacer").InvokeMember(
        "ReplaceTokensAll", 
        System.Reflection.BindingFlags.InvokeMethod, 
        null, 
        null, 
        new object[] { 
            strContent, 
            UserInfo, 
            !DotNetNuke.Common.Globals.IsTabPreview(),
            ModuleSettings
        }
    ).ToString();

Don’t forget to encapsulate this code inside try.. catch statements. Could be that MyTokens is not installed or there is an exception thrown that you’ll need to handle.

Production Ready Code

In practice, the solution needs to take into account other factors such as minimizing the overhead of using reflection or reverting to a default behavior.

The function below has the following features:

1.Uses reflection method so if MyTokens is not installed the website runs normally. 2.Can be called both from Module scope and from other components (Skin Objects, Services, Http Handlers, etc). 3.Implements caching so overhead that comes from reflection is eliminated 4.Reverts to standard DotNetNuke token replacement when MyTokens is not installed 5.Code can be used as it is, copy paste the function and the includes. Then, invoke it whenever you need token replacement. It’s recommended to include the method in a Business Controller Class so it’s visible to all controls. 6.It’s Thread Safe

VB.NET Complete Code Sample

Imports System.Web
Imports DotNetNuke.Entities.Modules
Imports System.Reflection
' ................................

' replace tokens in a module 
strContent = Tokenize(strContent, ModuleConfiguration, False, True)

' replace tokens outside of a module
strContent = Tokenize(strContent, Nothing, False, True)

' ................................

Public Shared Function Tokenize(strContent As String, modInfo As DotNetNuke.Entities.Modules.ModuleInfo, currentUser as DotNetNuke.Entities.Users.UserInfo, forceDebug As Boolean, bRevertToDnn As Boolean) As String
  Dim cacheKey_Installed As String = "avt.MyTokens2.Installed"
  Dim cacheKey_MethodReplace As String = "avt.MyTokens2.MethodReplace"

  Dim bMyTokensInstalled As String = "no"
  Dim methodReplace As System.Reflection.MethodInfo = Nothing

  Dim bDebug As Boolean = forceDebug
  If Not bDebug Then
    Try
      bDebug = Not DotNetNuke.Common.Globals.IsTabPreview()
    Catch
    End Try
  End If

  SyncLock GetType(DotNetNuke.Services.Tokens.TokenReplace)
    ' first, determine if MyTokens is installed
    If HttpRuntime.Cache.[Get](cacheKey_Installed) Is Nothing Then

      ' check again, maybe current thread was locked by another which did all the work
      If HttpRuntime.Cache.[Get](cacheKey_Installed) Is Nothing Then

        ' it's not in cache, let's determine if it's installed
        Try
          Dim myTokensRepl As Type = DotNetNuke.Framework.Reflection.CreateType("avt.MyTokens.MyTokensReplacer", True)
          If myTokensRepl Is Nothing Then
            Throw New Exception()
          End If
          ' handled in catch
          bMyTokensInstalled = "yes"

          ' we now know MyTokens is installed, get ReplaceTokensAll methods
          methodReplace = myTokensRepl.GetMethod("ReplaceTokensAll", System.Reflection.BindingFlags.[Public] Or System.Reflection.BindingFlags.[Static], Nothing, System.Reflection.CallingConventions.Any, New Type() {GetType(String), GetType(DotNetNuke.Entities.Users.UserInfo), GetType(Boolean), GetType(DotNetNuke.Entities.Modules.ModuleInfo)}, Nothing)

          If methodReplace Is Nothing Then
            ' this shouldn't really happen, we know MyTokens is installed
            Throw New Exception()

          End If
        Catch
          bMyTokensInstalled = "no"
        End Try

        ' cache values so next time the funciton is called the reflection logic is skipped
        HttpRuntime.Cache.Insert(cacheKey_Installed, bMyTokensInstalled)
        If bMyTokensInstalled = "yes" Then
          HttpRuntime.Cache.Insert(cacheKey_MethodReplace, methodReplace)
        End If
      End If
    End If
  End SyncLock

  bMyTokensInstalled = HttpRuntime.Cache.[Get](cacheKey_Installed).ToString()
  If bMyTokensInstalled = "yes" Then
    methodReplace = DirectCast(HttpRuntime.Cache.[Get](cacheKey_MethodReplace), System.Reflection.MethodInfo)
    If methodReplace Is Nothing Then
      HttpRuntime.Cache.Remove(cacheKey_Installed)
      Return Tokenize(strContent, modInfo, forceDebug, bRevertToDnn)
    End If
  Else
    ' if it's not installed return string or tokenize with DNN replacer
    If Not bRevertToDnn Then
      Return strContent
    Else
      Dim dnnTknRepl As New DotNetNuke.Services.Tokens.TokenReplace()
      dnnTknRepl.AccessingUser = currentUser
      dnnTknRepl.DebugMessages = bDebug
      If modInfo IsNot Nothing Then
        dnnTknRepl.ModuleInfo = modInfo
      End If

      ' MyTokens is not installed, execution ends here
      Return dnnTknRepl.ReplaceEnvironmentTokens(strContent)
    End If
  End If

  ' we have MyTokens installed, proceed to token replacement
  Return DirectCast(methodReplace.Invoke(Nothing, New Object() {strContent, currentUser, bDebug, modInfo}), String)

End Function

C# Complete Code Sample


using System.Web;
using DotNetNuke.Entities.Modules;
using System.Reflection;

// ................................

// replace tokens in a module
strContent = Tokenize(strContent, ModuleConfiguration, UserInfo, PortalId);

// replace tokens outside of a module
strContent = Tokenize(strContent, null, UserController.GetCurrentUserInfo(), PortalController.GetCurrentPortalSettings().PortalId);
// replace tokens outside of an HTTP context (from a scheduled task for example)
strContent = Tokenize(strContent, null, null, -1);

// ................................

public static string Tokenize(string strContent, DotNetNuke.Entities.Modules.ModuleInfo modInfo, DotNetNuke.Entities.Users.UserInfo user, int portalId, bool forceDebug = false, bool bRevertToDnn = true)
    {
        string cacheKey_Installed = "avt.MyTokens2.Installed";
        string cacheKey_MethodReplace = "avt.MyTokens2.MethodReplace";

        string bMyTokensInstalled = "no";
        System.Reflection.MethodInfo methodReplace = null;

        bool bDebug = forceDebug;
        if (!bDebug) {
            try { bDebug = DotNetNuke.Common.Globals.IsEditMode(); } catch { }
        }

        lock (typeof(DotNetNuke.Services.Tokens.TokenReplace)) {
            // first, determine if MyTokens is installed
            if (HttpRuntime.Cache.Get(cacheKey_Installed) == null) {

                // check again, maybe current thread was locked by another which did all the work
                if (HttpRuntime.Cache.Get(cacheKey_Installed) == null) {

                    // it's not in cache, let's determine if it's installed
                    try {
                        Type myTokensRepl = DotNetNuke.Framework.Reflection.CreateType("avt.MyTokens.MyTokensReplacer", true);
                        if (myTokensRepl == null)
                            throw new Exception(); // handled in catch

                        bMyTokensInstalled = "yes";

                        // we now know MyTokens is installed, get ReplaceTokensAll methods
                        methodReplace = myTokensRepl.GetMethod(
                            "ReplaceTokensAll",
                            System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static,
                            null,
                            System.Reflection.CallingConventions.Any,
                            new Type[] { 
                                typeof(string), 
                                typeof(DotNetNuke.Entities.Users.UserInfo), 
                                typeof(bool),
                                typeof(DotNetNuke.Entities.Modules.ModuleInfo)
                            },
                            null
                        );

                        if (methodReplace == null) {
                            // this shouldn't really happen, we know MyTokens is installed
                            throw new Exception();
                        }

                    } catch {
                        bMyTokensInstalled = "no";
                    }

                    // cache values so next time the funciton is called the reflection logic is skipped
                    HttpRuntime.Cache.Insert(cacheKey_Installed, bMyTokensInstalled);
                    if (bMyTokensInstalled == "yes") {
                        HttpRuntime.Cache.Insert(cacheKey_MethodReplace, methodReplace);
                    }
                }
            }
        }

        bMyTokensInstalled = HttpRuntime.Cache.Get(cacheKey_Installed).ToString();
        if (bMyTokensInstalled == "yes") {
            methodReplace = (System.Reflection.MethodInfo)HttpRuntime.Cache.Get(cacheKey_MethodReplace);
            if (methodReplace == null) {
                HttpRuntime.Cache.Remove(cacheKey_Installed);
                return Tokenize(strContent, modInfo, user, portalId, forceDebug, bRevertToDnn);
            }
        } else {
            // if it's not installed return string or tokenize with DNN replacer
            if (!bRevertToDnn) {
                return strContent;
            } else {
                DotNetNuke.Services.Tokens.TokenReplace dnnTknRepl = new DotNetNuke.Services.Tokens.TokenReplace();
                dnnTknRepl.AccessingUser = DotNetNuke.Entities.Users.UserController.GetCurrentUserInfo();
                dnnTknRepl.User = user ?? DotNetNuke.Entities.Users.UserController.GetCurrentUserInfo();
                dnnTknRepl.DebugMessages = bDebug;
                if (modInfo != null)
                    dnnTknRepl.ModuleInfo = modInfo;

                // MyTokens is not installed, execution ends here
                return dnnTknRepl.ReplaceEnvironmentTokens(strContent);
            }
        }

        // quick hack to pass a portal id to My Tokens
        if (modInfo == null && portalId != -1) {
            modInfo = new DotNetNuke.Entities.Modules.ModuleInfo() {
                PortalID = portalId
            };
        }
        // we have MyTokens installed, proceed to token replacement
        return (string)methodReplace.Invoke(
            null,
            new object[] {
                strContent,
                user ?? DotNetNuke.Entities.Users.UserController.GetCurrentUserInfo(),
                bDebug,
                modInfo
            }
        );

    }