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
                Response.Redirect(“~/Install/Install.aspx?mode=none”)
            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)->


RoleController.SynchronizeRoles(PortalId)->


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.


 

Reset DotNetNuke windows authentication back to normal.

In my previous posts (here and here)  I described the problems that I had to implemented mixed Authentication for DotNetNuke.
Important step for administrator is “Before switching to Windows Authentication ensure that your LAN acoount has host/administrative permissions for the portal.”.


If it wasn’t done, you can’t access administrative features. It is possible to use SQL command to re- activated Windows Authentication.


I am using call to SP  ModuleSettings_SiteSettings_Save that I’ve created previously.


exec dnn_ModuleSettings_SiteSettings_Save ‘WindowsAuthentication’,’false’


Note that DNN admin SQL page is not available and administrator should use some other SQL client to access your DNN database.


 SP ModuleSettings_SiteSettings_Save is the following:


CREATE PROCEDURE {databaseOwner}.[{objectQualifier}ModuleSettings_SiteSettings_Save]


      — Add the parameters for the stored procedure here


      @SettingName nvarchar(50),


      @SettingValue nvarchar(2000)


AS


BEGIN


 


declare @SiteSettingsModuleId int


select @SiteSettingsModuleId={objectQualifier}Modules.ModuleID


FROM    dnn_Modules  INNER JOIN


                      {databaseOwner}dnn_ModuleDefinitions ON {objectQualifier}Modules.ModuleDefID = {objectQualifier}ModuleDefinitions.ModuleDefID INNER JOIN


                      {databaseOwner}dnn_DesktopModules ON {objectQualifier}ModuleDefinitions.DesktopModuleID = {objectQualifier}DesktopModules.DesktopModuleID


WHERE     ({objectQualifier}DesktopModules.FriendlyName = N’Site Settings’)


 


if NOT exists (select * from dbo.{objectQualifier}ModuleSettings WHERE  ({objectQualifier}ModuleSettings.SettingName = @SettingName) AND {objectQualifier}ModuleSettings.ModuleID =@SiteSettingsModuleId )


      INSERT INTO   {objectQualifier}ModuleSettings (ModuleID,SettingName,SettingValue)


      values(@SiteSettingsModuleId,@SettingName,@SettingValue)   


else


      update    {objectQualifier}ModuleSettings


      set SettingValue=@SettingValue


      FROM         {objectQualifier}ModuleSettings


      WHERE     ({objectQualifier}ModuleSettings.SettingName = @SettingName) AND  {objectQualifier}ModuleSettings.ModuleID =@SiteSettingsModuleId


END


 


go


 

Create CSS Links in DotNetNuke.

I wanted to have another page (not default.aspx) in DotNetNuke based application. I found that there is no common code to generate CSS links. Actually, core code to create CSS links is duplicated in a few places. I’ve created a common class, that can be used in my custom page, as well as  from Default.aspx and ComponentsSkinsSkin.vb . The class is posted in comment to the isssue. 

Use VS 2005 Web Deployment Project with DotNetNuke

Some time ago I blogged that my attempt to use VS 2005 Web Deployment Project  failed with not very helpful Aspnet_merge.exe Exited With Code 1 message.  As it is described in the thread, the actual error reported was
An error occurred when merging assemblies: ILMerge.Merge: ERROR!!: Duplicate type ‘DotNetNuke.UI.Skins.Controls.SolPartMenu’ found in assembly ‘App_Web_k5hhsnh0’.


I found that there are 2 files “adminSkinssolpartmenu.ascx“ and “adminSkinsmenu.ascx“ referring to the  same SolPartMenu.ascx.vb. 2 files generated partial classes with the same name and caused “Duplicate type” error during merge.


I didn’t find where “adminSkinsmenu.ascx“ is used, so I just excluded it from the project.


The recomendation how to fix the problem in general are described in MS article “Common Web Project Conversion Issues and Solutions”, issue 26.


After this I’ve got the next error “Duplicate type ‘DotNetNuke.UI.WebControls.SolPartActions’” , that I fixed by excluding adminContainersactions.ascx from the project.


After this I was able to build Deployment project without any errors, that gave me one DLL per subfolder. 


The problem is reported to DNN Support.

DotNetNuke error reporting requires improvement

I found that DotNetNuke code often doesn’t report exceptions to user, but hides them.This style of error handling is natural for VB developers, who had the favorite comand “on error resume next”.(I hope that DNN developers are from different school).


 In some cases, exception are written it to EventLog table, but it is not always easy to access. E.g. if errors are occured during install and portal is not created yet, View log Web UI obviously is not available.


I’ve posted the suggestion to DNN support.
Below I listed places where I’ve added exception reporting. I am going to add more as far I will find reporting missing, but useful for my debugging.


In Upgrade.InstallDNN


                ‘After Parse the script nodes


              If Len(strExceptions) > 0 Then ‘mnF 12/4/2006


                    HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, “Exceptions were reported to Default Data Provider log file”)


                    strExceptions = “” ‘reset


                End If


  ‘And After installMemberRole


                If Len(strExceptions) > 0 Then ‘mnF 12/4/2006


                    HtmlUtils.WriteFeedback(HttpContext.Current.Response, 0, strExceptions)


                    strExceptions = “” ‘reset


                End If


 


In LibraryComponentsPortalPortalController.vb AddPortalInfo


In catch added Trace exception


 


 


In DNNLibraryComponentsProvidersLoggingException LoggingExceptionLogController.vb


  Sub AddLog(ByVal objException As Exception, ByVal LogType As ExceptionLogType)


            Trace.WriteLine(“DotNetNuke.Services.Log.EventLog.ExceptionLogController.AddLog: “ & LogType.ToString() & ” – “ & objException.ToString())


 


In DNNLibraryComponentsUpgradeUpgrade.vb


‘InstallMemberRoleProvider should save to log any exceptions (if any) in the same way as Upgrade.ExecuteScript does


            If Len(strExceptions) > 0 Then ‘mnf 13/4/2006


                FSHelperLib.StreamHelper.SaveStringToFile(strExceptions, strProviderPath & “InstallMemberRoleProvider.log”)


            End If


 


In DNNLibraryComponentsUsersUserController.vb


Function AddUser


                If Status = UserRegistrationStatus.AddUser Then


‘Existing code removed for brevity


                Else ‘mnf 13/4/2006


                    If UserId < 0 Then ‘TODO may be throw exception


                        Trace.WriteLine(“Unable to AddUser “ & objUser.Membership.Username & ” – “ & Status.ToString())


                    End If


                End If


 


 Function DeleteAllUsers


Catch exc As Exception
                Trace.WriteLine(exc.ToString())


InstallInstall.aspx.vb Function InstallApplication


‘After backing up old web.config
                Catch ex As Exception
                    ‘Error backing up old web.config
                    ‘This error is not critical, so can be ignored
                    System.Diagnostics.Trace.WriteLine(“InstallApplication ” & backupFolder & “web_old.config” & ” error ” & ex.ToString()) 
                End Try


DNNLibraryComponentsSecurityRolesRoleController.vb AddUserRole
                Try
                    AspNetSecurity.Roles.AddUserToRole(objUser.Membership.Username, objUserRole.RoleName)
                Finally ‘instead of Catch ex As Exception
                   
‘Reset the Application Name
    
                    
Common.Globals.SetApplicationName(originalAppName)
                End Try


DNNLibraryComponentsTabsTabController.vb Function GetTab


            Try


                Return FillTabInfo(dr)


            Catch exc As Exception


                System.Diagnostics.Trace.WriteLine(“ComponentsTabsTabController.vb GetTab “ & TabId & ” error “ & exc.ToString())


            Finally


                If Not dr Is Nothing Then


                    dr.Close()


                End If


            End Try


            Return Nothing


DNNLibraryComponentsSkinsSkin.vb in Page_Init


                Dim arrModuleControls As ArrayList = objModuleControls.GetModuleControlsByKey(Key, objModule.ModuleDefID)


                If arrModuleControls.Count = 0 Then


                    System.Diagnostics.Trace.WriteLine(“DotNetNuke.UI.Skins.Skin.Page_Init GetModuleControlsByKey returned 0 controls for key “ & Key)


                End If


DNNLibraryControlsDotNetNuke.WebUtilityClientAPI.vb GetClientAPICapsDOM


Try


                    strFileName = System.Web.HttpContext.Current.Server.MapPath(ScriptPath & “/ClientAPICaps.config”)


                Catch ex As Exception


                    System.Diagnostics.Trace.WriteLine(“DotNetNuke.UI.Utilities.ClientAPIs.GetClientAPICapsDOM “ & ex.ToString())


                    ‘ignore error – worried about people with reverse proxies and such…


                End Try


NEW for DNN 4.4.
LibraryProvidersMembershipProvidersAspNetMembershipProviderAspNetMembershipProvider.vb  CreateUser


Catch exc As Exception ‘ an unexpected error occurred

LogException(exc)  ‘ WHY it is COMMENTED?????????

createStatus = UserCreateStatus.UnexpectedError


End Try

NEW for DNN 4.4.
adminSecuritySendPassword.ascx.vb  cmdSendPassword_Click


                            Try


                                objUser.Membership.Password = UserController.GetPassword(objUser, txtAnswer.Text)


                            Catch ex As Exception


‘Actual exception should be logged


                                canSend = False


                                strMessage = Localization.GetString(“PasswordRetrievalError”, Me.LocalResourceFile)


                            End Try


AND


                              Try


                                Mail.SendMail(objUser, MessageType.PasswordReminder, PortalSettings)


                                strMessage = Localization.GetString(“PasswordSent”, Me.LocalResourceFile)


                            Catch ex As Exception


‘Actual exception should be logged


                               

canSend =
False

                            End Try


C:ProjectsFuncSolnDNNLibraryComponentsFrameworkPageBase.vb PageCulture
Try
preferredLocale = HttpContext.Current.Request(“language”)


…code is omitted


Catch
‘Actual exception should be logged

End Try


 

Data change checking features in DotNetNuke pages.

I’ve used  data change checking features  described by Eric Woodruff in my ASP.NET application. When I converted the ASP.NET application to DotNetNuke, I still needed to have the same functionality.


Unfortunately .Net doesn’t allow multiple inheritanse,  so I had to re-factor EWSoftware.Web.BasePage.


I created an interface IDataChangeChecking, that described the public methods, relevant to data change checking:
//described in http://www.codeproject.com/aspnet/EWSWebPt2.asp
string
[] BypassPromptIds
bool CheckForDataChanges
bool Dirty
string[] SkipDataCheckIds
StateBag ControlViewState
//expose protected ViewState


and created public class DataChangeCheckingImpl with methods extracted from original BasePage






{
// Methods
public DataChangeCheckingImpl(Control owner);
public static void BypassChangesNotSavedPrompt(Control container, string ClientID);
public static void BypassChangesNotSavedPromptIDs_Add(Control container, string[] ClientIDs);
public void OnInit(EventArgs e);
public void OnPreRender(EventArgs e);
public static void SetCheckForDataChanges(Control container, bool value);
public static bool SetPageDirty(Control container, bool Value);
public static void SkipDataChangesCheckIDs_Add(Control container, string[] ClientIDs);

// Properties
public string[] BypassPromptIds { get; set; }
public bool CheckForDataChanges { get; set; }
public string ConfirmLeaveMessage { get; set; }
public bool Dirty { get; set; }
private HttpRequest Request { get; }
public string[] SkipDataCheckIds { get; set; }
public StateBag ViewState { get; }

// Fields
private bool bIsDirty;
private Control m_ctlOwner;
private IDataChangeChecking m_IDataChangeChecking;
}


Finally I’ve created DataChangeCheckingDefaultPage class, derived from DotNetNuke.Framework.CDefault and implementing IDataChangeChecking interface.


Additionaly OnInit event handler created DataChangeCheckingImpl object and methods
DataChangeCheckingImpl.OnInit and OnPreRender are called from the corresponding DataChangeCheckingDefaultPage event handlers.

Now I can configure data editing DotNetNuke modules, that user will see warning if he/she try to exit without saving data. 

Emailable DotNetNuke Module

I’ve used an e-Mailable ASP.Net web page described by Eric Woodruff in an ASP.NET application. When I converted the ASP.NET application to DotNetNuke, I still wanted to have the same functionality-ability to e-mail rendered content of the DotNetNuke module.

I created the class EmailableModule based on DotNetNuke.Entities.Modules.PortalModuleBase and copied and paste the content of EMailPage class. There are a few places where I changed references to page to references to DNN module.I was able to use helper Event and Exception classes from the original EMailPage without changes.

Now I can use the same class derived from EmailableModule in DNN application and in generated e-mails.

Related Links: As an alternative to Eric Woodruff‘s solution see Scott Mitchell‘s:  

  • Emailing the Rendered Output of an ASP.NET Web Control
  • Enhancing the ‘Email the Rendered Output of an ASP.NET Web Control’ Code
  • Emailing the Rendered Output of an ASP.NET Web Control in ASP.NET 2.0