StyleSheetsManage class for DotNetNuke

I found that code to create CSS links is duplicated in a few places. I’ve created a common class, that can be used from Default.aspx,ComponentsSkinsSkin.vb and third-party modules if required.

Originally I’ve posted it to DNN support , but it is not searchable by Google. So I desided to post it here as well.

 The code is the following:

Imports System.Diagnostics

Imports System.IO

Imports Microsoft.VisualBasic

Imports DotNetNuke

Imports DotNetNuke.Framework


Public Class StyleSheetsManage

    ‘Based on C:ProjectsFuncSolnFSDNNDefault.aspx.vb ManageStyleSheets

    Public Shared Sub AddStyleSheetFile(ByVal objCSS As Control, ByVal sFileName As String)

        ‘ initialize reference paths to load the cascading style sheets

        ‘Dim objCSS As Control = Me.FindControl(“CSS”)

        Dim ID As String

        Dim PortalSettings As PortalSettings = PortalController.GetCurrentPortalSettings

        Dim sHref As String = “”

        Dim objCSSCache As Hashtable = CType(DataCache.GetCache(“CSS”), Hashtable)

        If objCSSCache Is Nothing Then

            objCSSCache = New Hashtable

        End If

        If Not objCSS Is Nothing Then

            Select Case (sFileName.ToLower())

                Case “default.css”

                    AddStyleSheetLink(objCSS, Common.Globals.HostPath, sFileName)

                Case “skin.css”

                    ‘ skin package style sheet

                    sHref = AddToCacheIfRequired(objCSSCache, PortalSettings.ActiveTab.SkinPath, “skin.css”)

                    If sHref <> “” Then

                        AddStyleSheetLink(objCSS, PortalSettings.ActiveTab.SkinPath, sFileName)

                    End If

                Case “skinsrc”

                    ‘ skin file style sheet

                    ID = CreateValidID(Replace(PortalSettings.ActiveTab.SkinSrc, “.ascx”, “.css”))

                    sHref = AddToCacheIfRequired(objCSSCache, ID, “”)

                    If sHref <> “” Then

                        AddStyleSheetLink(objCSS, ID, “”)

                    End If

                Case “portal.css”

                    AddStyleSheetLink(objCSS, PortalSettings.HomeDirectory, “portal.css”)

                Case Else


            End Select

        End If

    End Sub

    Public Shared Function AddStyleSheetLink(ByVal objCSS As Control, ByVal sPath As String, ByVal sFileName As String) As String

        Dim sHref As String = “”

        If Not objCSS Is Nothing Then

            Dim objLink As HtmlGenericControl = New HtmlGenericControl(“LINK”)

            Dim ID As String = CreateValidID(sPath)

            objLink.ID = ID

            objLink.Attributes(“rel”) = “stylesheet”

            objLink.Attributes(“type”) = “text/css”

            sHref = sPath & sFileName

            objLink.Attributes(“href”) = sHref


        End If

        Return sHref

    End Function

    Public Shared Function AddToCacheIfRequired(ByVal objCSSCache As Hashtable, ByVal sPath As String, ByVal sFileName As String)

        Dim PortalSettings As PortalSettings = PortalController.GetCurrentPortalSettings

        Dim sHref As String = “”

        Dim ID As String = CreateValidID(sPath)

        If objCSSCache.ContainsKey(ID) = False Then

            If File.Exists(HttpContext.Current.Server.MapPath(sPath) & sFileName) Then

                sHref = sPath & sFileName

            End If

            objCSSCache(ID) = sHref

            If Not Common.Globals.PerformanceSetting = Common.Globals.PerformanceSettings.NoCaching Then

                DataCache.SetCache(“CSS”, objCSSCache)

            End If


            sHref = objCSSCache(ID)

        End If

        Return sHref

    End Function

End Class

DotNetNuke function FindControlRecursive -not clear name.

DotNetNuke has function FindControlRecursive. Initially I assumed that it search down hierarchy, but it doesn’t work as I expected.
After reading code it seems that it searched siblings or parens siblings up to the top of hierarchy.
So the name is misleading.

Fortunately  there is a separate function FindControlRecursiveDown, that does what I needed.

Using Web Application Project(WAP) for development of DotNetNuke modules with Edit and Continue Support

I am using Web Application Project(WAP) for development of DotNetNuke modules.

The general approach is discussed in DNN forum thread here.


My VS solution consists of main WAP Project and one or more User Control Libraries similar to described in Tutorial 6: Creating and Using User Control Libraries.

The main WAP Project basically includes one DNNDebug.aspx  file (as well as web.config and global.asax),  that allows me to load and test my user controls.

The User Control Libraries(DNN modules) are physically located in DesktopModules subfolder of the main project, so I  don’t need to copy ascx files from control library to main project subfolders as it is recommended in  the Tutorial.


Main WAP project has references to module projects, which ensures that module DLLs are copied to main project bin folder by VS.


The using simple main WAP project has an advantage compare to Vladan’s BlankModule approach solution can use Development Web Server and “Edit and Continue” will work!


When I am satisfied with testing and debugging of a new module with DNNDebug.aspx, the next step is to copy the module to normal DNN Web Site Project. It is required to copy module DLL to bin directory and ASCX files to WSP DesktopModules subfolder. I also need to remove CodeBehind attribute From Ascx files, because I do not want copy source code ascx.vb files to the WSP project. The procedure how to set the project to do it automatically described in the thread “How to use WAP User Control Libraries from Web Site Project and my blog  article “Utility to Remove CodeBehind attribute From Ascx files .   

DotNetNuke: InstallationDate entry in web.Config can be missing.

We had couple sites when during install of DotNetNuke(4.0.3) there was a known “Nothing to Install At This Time” message.
I’ve tried to investigate , how it could happen.
At the first installation the function Install.InstallApplication (InstallInstall.aspx.vb) checks web.config file.
If InstallationDate  is missing, it tries to call Config.UpdateMachineKey, which should add InstallationDate element and save web.config.
If the save not succced, the DotNetNuke Configuration Error“ error(403-3.htm) is reported.
However if the new DotNetNuke Web Application  with web.config file is attached to database with DNN tables installed,
 Install.InstallApplication is not called and InstallationDate element is not added.

However in event handler Application_BeginRequest(App_CodeGlobal.asax.vb) web.config file is checked if InstallationDate  is missing:
            Dim installationDate As String = Config.GetSetting(“InstallationDate”)
            If installationDate Is Nothing Or installationDate = “” Then
            End If

mode=none invokes NoUpgrade() method(InstallInstall.aspx.vb) which doesn’t do any installation, but compares database and assembly version and shows link to install or shows  “Nothing to Install At This Time” message.

It will be good if
1.NoUpgrade() name will be changed to more descriptive WriteResponseIfUpdatesRequired
2.the function will also check
InstallationDate element in web.config and add clear instruction/link to update if the element is missing.

I’ve posted my suggestion to DNN support

DotnetNuke: increment copyright year in the source code made it harder to identify the changes.

I’ve downloaded new 4.3.1 version and wanted to find which files were changed. Using VSS directory differences, I found that ALL files have been changed. Looking for details, I understood, that in most files only Copyright year was changed from 2005 to 2006. I think that it was a bad idea, because it make harder for users of DNN core source code to identify the changes. More…

Meaning “IsPublic” for DotNetNuke Roles.

DotNetNuke Roles have “IsPublic” attribute. I wandered what the business meaning of the value. After reading the 4.0.2 code my understanding that if IsPublic=true, user is able to subscribe to the role, if it is free (see DotNetNukeadminSecurityRegister.ascx.vb).
I didn’t find any more business logic coded.
It seems that even if public=false, role is visible to user and even available for payed subscription.
(I haven’t tested it yet.)


Lazy roles Synchronization in DotNetNuke.

There is a thread: Role SynchronizationMode that asked what the meaning of the parameter in core AddRole method.
I investigated ability to syncronize roles from custom database to DNN and can post answer for this question(according to 4.0.2 core).

Parameter SynchronizationMode is used to implement “lazy” synchronization for roles.

If new role has been added to AspNet_Roles DNN calls synchronization to update satellite dnn_Roles table.


Parameter SynchronizationMode is used in RoleController.AddRole to indicate whether the role should be added to both the AspNet_Roles and dnn_Roles(SynchronizationMode=false) or to dnn_Roles only (SynchronizationMode=true).

The common use is to call AddRole(ByVal objRoleInfo As RoleInfo) overload, which corresponds to SynchronizationMode=false.


The call stack for syncronization (SynchronizationMode=true )is the following:

DotNetNukeadminSecurityRoles.ascx.vb: BindData ->

RoleController.GetPortalRoles(PortalId, True)->


objRoleController.AddRole(objRoleInfo, True)


There is also method

RoleController.GetRoleByName(ByVal PortalId As Integer, ByVal RoleName As String, ByVal SynchronizeRoles As Boolean) that also can be called to synchronize roles,  

but I didn’t find that is is called from anywhere with SynchronizeRoles=true.