Showing posts with label DNN. Show all posts
Showing posts with label DNN. Show all posts

Thursday, July 18, 2013

Copy modules as reference from one DNN page to another using SQL script

If (you are a dev in hurry with a TL waiting for your output)
    Then simply skip to script at bottom of this page, edit variables in first three lines as per your requirement and test results.
else
    Keep Reading :)

Is it difficult to hold a glass of water for a minute! No, not at all. But how will it be if you are supposed to hold it for 100 hrs :) This post is about tackling one such case.

Problem statement:
Copy modules as reference from one DNN page to another using SQL script.

One of my friend who administers multiple DNN portals, was having around 7-8 html modules on a page and was copying them across some 50 odd existing pages I guess. Copying modules using dnn UI is pretty simple as described here, but is very slow as you have to do it one by one and every-time it performs a certain set of steps. So he asked me to devise some alternative and i came-up with below.

Solution:

DNN keeps track of modules and their instances in below tables:

  • dbo.DesktopModules and dbo.ModuleDefinitions - These tables track what all modules are installed in site.
  • dbo.Modules - This table tracks instances of modules added on pages, means an entry is created in this table when you add a new instance of a module on some page
Apart from above three tables, there is another table named dbo.TabModules which keeps track of info that which module is placed on which tab(In dnn teminology, a tab represents a page). This table gets one entry for every instance of module whether it is reference copy of an existing module or added a fresh.

So after knowing above bit of information, I coded a small script which takes three parameters as below
name of source page  : from where to copy
name of target page   : where to paste 
list of module titles     : that need to be copied from source page to target page

With these parameters my script simply creates an entry in dbo.TabModules table and updates VersionGuid column for related modules for every entry of module title.


      *  name of a DNN page can be retrieved through page settings
    **  module title can be duplicate. Though script i wrote is smart enough to point you on such cases but I still advise to choose unique module titles while copying modules
  ***  I have also used a function "udf_List2Table" to get table from pipe delimited list of module. This function can be found here at my favorite SQL blog.  
****  This script creates copy of existing modules, means changing content in one will automatically update that in other.

-------------------Script goes below------------------------

DECLARE @CopyFromPage VARCHAR(1000) = 'Test Page'       --U can get this from page settings
DECLARE @CopyToPage VARCHAR(1000) = 'Child Page 5'
DECLARE @OriginalModuleTitles VARCHAR(MAX) = 'ModuleA||ModuleB||ModuleC||ModuleD||ModuleE' --Hoping u have added only one module with this title on from page


DECLARE @OriginalModuleTitle VARCHAR(1000)
DECLARE @TabIdFromPage INT
DECLARE @TabIdToPage INT
DECLARE @ModuleId INT
DECLARE @HostUserId INT

SELECT @TabIdFromPage = TabID FROM dbo.Tabs WHERE TabName = @CopyFromPage
SELECT @TabIdToPage = TabID FROM dbo.Tabs WHERE TabName = @CopyToPage

IF(@TabIdFromPage > 0 AND @TabIdToPage > 0)
BEGIN

       --Convert pipe delimited module names to table
       DECLARE @tempTable TABLE (moduleName varchar(1000))
       INSERT INTO @tempTable
       SELECT * FROM udf_List2Table(@OriginalModuleTitles, '||')

       WHILE EXISTS (SELECT * FROM @tempTable)
       BEGIN
              SELECT TOP 1 @OriginalModuleTitle = moduleName FROM @tempTable

              IF EXISTS (SELECT * FROM dbo.TabModules WHERE TabID = @TabIdToPage AND ModuleTitle = @OriginalModuleTitle)
                     PRINT 'Module with title ''' + @OriginalModuleTitle + ''' already exists in page ''' + @CopyToPage + ''''
              ELSE
              BEGIN
      
                     IF ((SELECT COUNT(*) FROM dbo.TabModules WHERE TabID = @TabIdFromPage AND ModuleTitle = @OriginalModuleTitle) = 1)
                     BEGIN

                           SELECT @ModuleId = ModuleID FROM dbo.TabModules WHERE TabID = @TabIdFromPage AND ModuleTitle = @OriginalModuleTitle
                           SELECT @HostUserId = UserID FROM dbo.Users WHERE Username = 'host'
             
                           DECLARE @NewVersionGuid UNIQUEIDENTIFIER = NEWID()
                           DECLARE @CreatedOnDate DATETIME = GETDATE()
             
                           INSERT INTO [dbo].[TabModules]
                                  ([TabID], [ModuleID], [PaneName], [ModuleOrder], [CacheTime], [Alignment], [Color], [Border], [IconFile],
                                  [Visibility], [ContainerSrc], [DisplayTitle], [DisplayPrint], [DisplaySyndicate], [IsWebSlice], [WebSliceTitle],
                                  [WebSliceExpiryDate], [WebSliceTTL], [CreatedByUserID], [CreatedOnDate], [LastModifiedByUserID],
                                  [LastModifiedOnDate], [IsDeleted], [CacheMethod], [ModuleTitle], [Header], [Footer], [CultureCode],
                                  [UniqueId], [VersionGuid], [DefaultLanguageGuid], [LocalizedVersionGuid])
             
                           SELECT
                                  @TabIdToPage, [ModuleID], [PaneName], [ModuleOrder], [CacheTime], [Alignment], [Color], [Border], [IconFile],
                                  [Visibility], [ContainerSrc], [DisplayTitle], [DisplayPrint], [DisplaySyndicate], [IsWebSlice], [WebSliceTitle],
                                  [WebSliceExpiryDate], [WebSliceTTL], @HostUserId, GETDATE(), @HostUserId,
                                  GETDATE(), [IsDeleted], [CacheMethod], [ModuleTitle], [Header], [Footer], [CultureCode],
                                  NEWID(), @NewVersionGuid, [DefaultLanguageGuid], [LocalizedVersionGuid]
                           FROM [dbo].[TabModules]
                           WHERE TabID = @TabIdFromPage AND ModuleTitle = @OriginalModuleTitle

                           --Update version Guids for related modules
                           UPDATE dbo.TabModules SET VersionGuid = @NewVersionGuid WHERE ModuleID = @ModuleId

                           PRINT 'Module Copied Successfully.'

                     END
                     ELSE
                           PRINT 'Module title you entered either doesn''t exists in from page or you have multiple modules with this title on from page.'

              END

              DELETE FROM @tempTable WHERE moduleName = @OriginalModuleTitle
       END

       PRINT 'You need to clear site cache [Host >> Host Settings >> Clear Cache] to view results.'

END
ELSE
       PRINT 'Either or both of Copy to/from page name is incorrect'


-------------------Script ends here------------------------ 


 You need to clear your DNN cache to view results of this script on your portal.




Friday, February 22, 2013

Can´t upload a new attachement in DNN 6 with forum 5.0.3

Today one of my friend pinged me to help on an issue with DNN forum module(05.00.03), he was using it on DNN 06.01.05. Problem was "Upload new attachment failing repeatedly with some exception". He was getting below exception:

Error: is currently unavailable. DotNetNuke.Services.Exceptions.ModuleLoadException: The underlying system threw an exception. ---> DotNetNuke.Services.FileSystem.FolderProviderException: The underlying system threw an exception. ---> System.ArgumentNullException: Value cannot be null. Parameter name: content at DotNetNuke.Services.FileSystem.StandardFolderProvider.AddFile(IFolderInfo folder, String fileName, Stream content) at DotNetNuke.Services.FileSystem.FileManager.MoveFile(IFileInfo file, IFolderInfo destinationFolder) --- End of inner exception stack trace --- at DotNetNuke.Services.FileSystem.FileManager.MoveFile(IFileInfo file, IFolderInfo destinationFolder) at DotNetNuke.Common.Utilities.FileSystemUtils.MoveFile(String strSourceFile, String strDestFile, PortalSettings settings) at DotNetNuke.Modules.Forum.WebControls.AttachmentControl.cmdUpload_Click(Object sender, EventArgs e) --- End of inner exception stack trace ---

So as usual firstly I googled the error and found that many people are having similar error, but none of them were having a solution so I thought that it might be some permissions issue and messed up with folder permissions, but all failed.

So finally I debugged the code and found that line that was breaking was calling method "FileSystemUtils.MoveFile" which got deprecated in DNN 6 

So I replaced it with method call for "RenameFile" and there you go!!

Below is the culprit line under method cmdUpload_Click in file "AttachmentControl.ascx.vb"
FileSystemUtils.MoveFile(ParentFolderName + FileName, ParentFolderName + destFileName, PortalSettings)

 and here is its replacement

DotNetNuke.Services.FileSystem.FileManager.Instance.RenameFile(DotNetNuke.Services.FileSystem.FileManager.Instance.GetFile(DotNetNuke.Services.FileSystem.FolderManager.Instance.GetFolder(PortalId, BaseFolder), FileName), destFileName)


If you are also having this error, then just download the module's source code from codeplex, open it in visual studio, replace lines as I mentioned, build this module. Now go to your filesystem, grab new DLL for forum module and replace it in your DNN apps bin directory.

Sorry I forgot to write earlier, please take backup before doing this to your production site.

Hope this will help!!

Thanks,
Ravi

Tuesday, December 18, 2012

DNN UserController.GetUsersByProfileProperty

Today while traversing through DNN code I found that method UserController.GetUsersByProfileProperty returns all available records if we pass -1 as pageIndex!

DNN handles pageIndex -1 at AspNetMembershipProvider class. Below is its implementation present in that class.

Public Overrides Function GetUsersByProfileProperty(ByVal portalId As Integer, ByVal propertyName As String, ByVal propertyValue As String, ByVal pageIndex As Integer, ByVal pageSize As Integer, ByRef totalRecords As Integer) As ArrayList
            If pageIndex = -1 Then
                pageIndex = 0
                pageSize = Integer.MaxValue
            End If


            Return UserController.FillUserCollection(portalId, dataProvider.GetUsersByProfileProperty(portalId, propertyName, propertyValue, pageIndex, pageSize), totalRecords)
        End Function

Saturday, June 25, 2011

Page_Load getting called twice

Hi All,

While working on one of my assignments past week I faced a strange problem. The problem was that my Page_Load event handler was getting called twice for apparently no reason. I was absolutely stumped. Then after a bit of trouble shooting and hit & trial, I found that the problem was a image tag.

My page gets post backed twice only in scenarios when source attribute's value of image control was rendering empty. So I just arranged a no image url in cases when there was no actual image url and got rid of my problem.

Similar problem I also faced a few months back, at that time I was working with link button. Then I was using link button for redirect user to some other page on link click. At that time I solved my problem by using hyperlink control in place of link button control.

Both these cases were, more or less magical for me ;)

I shared with you how I got my problem solved but if you know why was this problem occurring then kindly spare a few minutes to share it here. One more thing in both of these cases I was working on DNN.

Monday, June 20, 2011

Creating a DNN skin object

Hi All,

Below is a demonstration of how to create a DNN skin object. I’ll demonstrate this by creating a skin object that will display total number of users in your dnn site. Here we go:
Ø      Create a new project with template type “DotNetNuke Compiled Module”. Some other project type like class library project might also do but this one is easiest to start with.
Ø      I created a new project with name “CurrentUsersInfoSkinObject” and then cleaned it up by deleting all of the files from it, except below:
o       ViewCurrentUsersInfoSkinObject.ascx
o       ViewCurrentUsersInfoSkinObject.ascx.cs
o       App_LocalResources/ ViewCurrentUsersInfoSkinObject.ascx.resx
o       CurrentUsersInfoSkinObject.dnn
Ø      SkinObjects inherit from SkinObjectBase so change line
o       partial class ViewCurrentUsersInfoSkinObject : PortalModulebase
o       to
o       partial class ViewCurrentUsersInfoSkinObject : SkinObjectBase
Ø      Now add a literal control to ascx page, like below:
o       <asp:Literal ID="litUsersCount" runat="server" Mode="PassThrough" EnableViewState="false">asp:Literal>
o       pay attention on Mode and EnableViewState property.
Ø      Add one line to the resource file as below. This will serve as the base string to be shown in skin object.


Ø      Now place three lines of code in code behind file of view control.
o       string templateText = Localization.GetString("UsersCountDisplayTemplate", Localization.GetResourceFile(this, _myFileName));
o       templateText = templateText.Replace("[USERSCOUNT]", UserController.GetUsers(PortalSettings.PortalId).Count.ToString());
o       litUsersCount.Text = templateText;
o       In above three lines, first line reads resource file to get source string. Second line replaces placeholder [USERCOUNT] with number of users and set literal control to show this value.
Ø      Now just build this project, place dll in bin folder of your DNN installation.
Ø      Now place ascx and resource file in desktop modules folder, I placed these as shown in below image.

Ø      Now go to your dnn skin file. For me it was at,
Portals\_default\Skins\MinimalExtropy\ index leftmenu 1024.ascx
Ø      Add a line to register your newly added control. Like

<%@ Register TagPrefix="dnn" TagName="ViewCurrentUsersCount" src="~/DesktopModules/SkinObjects/ViewCurrentUsersInfoSkinObject.ascx" %>
Ø       Now add a line to place it at your desired place in skin. I placed it along with login control, like below:
<dnn:ViewCurrentUsersCount runat="server" id="UserCount" />
Ø      That’s all that you need to do to see your first skin object working.

Monday, May 23, 2011

Display DNN user profile properties in column format

Hi All,

A few days back in one of the DNN portals that I manage I was required to provide functionality to download user info including user profile properties in column format. Initially what I did was using DNNs built in API for getting users and then iterate through their profile properties by using UserInfo.Profile.ProfileProperties

This worked fine initially but once the number of users started growing, this started tooking great deal of time and ultimately started timing out. So I thought that I should design my own procedure for doing this and hence I came up with below solution. Probably this may save a few hours of your time.


            SELECT u.UserID, u.Username,
            upo2.PropertyValue as [ContactType],
upo3.PropertyValue AS [Title],
upo4.PropertyValue AS [FirstName],
            upo5.PropertyValue AS [LastName],
upo6.PropertyValue  AS [Position],
UPO7.PropertyValue  AS [Company],
UPO8.PropertyValue  AS [MembershipPeriod], UPO9.PropertyValue  AS [MembershipJoinDate],
UPO10.PropertyValue  AS [MembershipExpiryDate], UPO11.PropertyValue  AS [Address1],
            UPO12.PropertyValue  AS [Address2],
UPO13.PropertyValue  AS [Address3],
UPO14.PropertyValue  AS [Town],
            UPO15.PropertyValue  AS [County],
UPO16.PropertyValue  AS [Post Code],
UPO17.PropertyValue  AS [Country],
            UPO18.PropertyValue  AS [MainPhone],
UPO19.PropertyValue  AS [AlternativePhone],
            UPO20.PropertyValue  AS [Email],
UPO21.PropertyValue  AS [MembershipNumber]

            FROM Users u

            LEFT OUTER JOIN UserProfile UPO1
            ON upo1.UserID = u.UserID AND upo1.PropertyDefinitionID = 394

            LEFT OUTER JOIN UserProfile UPO2
            ON upo2.UserID = u.UserID AND upo2.PropertyDefinitionID = 398

            LEFT OUTER JOIN UserProfile UPO3
            ON upo3.UserID = u.UserID AND upo3.PropertyDefinitionID = 393

            LEFT OUTER JOIN UserProfile UPO4
            ON upo4.UserID = u.UserID AND upo4.PropertyDefinitionID = 362

            LEFT OUTER JOIN UserProfile UPO5
            ON upo5.UserID = u.UserID AND upo5.PropertyDefinitionID = 364

            LEFT OUTER JOIN UserProfile UPO6
            ON upo6.UserID = u.UserID AND upo6.PropertyDefinitionID = 382

            LEFT OUTER JOIN UserProfile UPO7
            ON upo7.UserID = u.UserID AND upo7.PropertyDefinitionID = 381

            LEFT OUTER JOIN UserProfile UPO8
            ON upo8.UserID = u.UserID AND upo8.PropertyDefinitionID = 395

            LEFT OUTER JOIN UserProfile UPO9
            ON upo9.UserID = u.UserID AND upo9.PropertyDefinitionID = 396

            LEFT OUTER JOIN UserProfile UPO10
            ON UPO10.UserID = u.UserID AND UPO10.PropertyDefinitionID = 397

            LEFT OUTER JOIN UserProfile UPO11
            ON upo11.UserID = u.UserID AND UPO11.PropertyDefinitionID = 383

            LEFT OUTER JOIN UserProfile UPO12
            ON UPO12.UserID = u.UserID AND UPO12.PropertyDefinitionID = 384

            LEFT OUTER JOIN UserProfile UPO13
            ON UPO13.UserID = u.UserID AND UPO13.PropertyDefinitionID = 385

            LEFT OUTER JOIN UserProfile UPO14
            ON UPO14.UserID = u.UserID AND UPO14.PropertyDefinitionID = 386

            LEFT OUTER JOIN UserProfile UPO15
            ON UPO15.UserID = u.UserID AND UPO15.PropertyDefinitionID = 502

            LEFT OUTER JOIN UserProfile UPO16
            ON UPO16.UserID = u.UserID AND UPO16.PropertyDefinitionID = 391

            LEFT OUTER JOIN UserProfile UPO17
            ON UPO17.UserID = u.UserID AND UPO17.PropertyDefinitionID = 370

            LEFT OUTER JOIN UserProfile UPO18
            ON UPO18.UserID = u.UserID AND UPO18.PropertyDefinitionID = 392

            LEFT OUTER JOIN UserProfile UPO19
            ON UPO19.UserID = u.UserID AND UPO19.PropertyDefinitionID = 388

            LEFT OUTER JOIN UserProfile UPO20
            ON UPO20.UserID = u.UserID AND UPO20.PropertyDefinitionID = 389

            LEFT OUTER JOIN UserProfile UPO21
            ON UPO21.UserID = u.UserID AND UPO21.PropertyDefinitionID = 399

In above query, numbers in red are PropertyDefinitionIds for respective profile properties. You will need to change these numbers as per your database. To get PropertyDefinitionID, you can use below query in your dnn database.

select * from profilepropertydefinition where portalid= order by propertyName

Take special care of PortalId while retrieving propertiesDefinitionIds as their can be several versions of profile property, i.e., one for each portal.

Thursday, May 19, 2011

DNN cache problem

Hi All,

Today I faced a very strange problem on one of the DNN sites that I manage. The problem was reported by my client and as per him some profile properties shown on user accounts screen were showing incorrect data sometimes. At first I thought that, a few changes that we made to display extra profile properties on user accounts screen might be posing problems, so I rechecked my code twice. But all went to wane. Then I thought it may be due to DNN cache, so I placed a single line code to clear cache everytime a new user is created. And lol!, the problem was resolved.

Code I used to clear cache
DataCache.ClearCache()

Monday, May 9, 2011

More than one view or edit controls in a custom DNN module

In DNN custom modules, we can have multiple view/edit controls.

Below are the steps to do so:

  • Add a new control to your module, to do so go to
Host Menu >> Module Definition >> Edit module by clicking pencil icon on left


  • On clicking “Add Module Control”, you will get a screen as below
    • Enter a key; this will serve as id when you will like to traverse to this control from some other control.
    • Select control from drop down list (of course the control needs to already exist in modules folder which in turn is under desktop modules folder). Things will look somewhat like below image.

  • Adding a new landing control
    • Edit your previous landing control by editing it and assigning it a control key.

At this point of time if you will visit any page with this module added, you will get a blank page as there is no specified landing control for your module.

    • Now add a new control in similar way as above with just a single difference. This time you don’t have to assign the control query. A control with no control key serves as a landing page.

  • Now its all set, put up your required logic on controls and access your newly added controls. To access these, you can use below code snippet
hlnkNewView.NavigateUrl = Globals.NavigateURL(PortalSettings.ActiveTab.TabID, "newView", "mid=" + ModuleId.ToString());

o       You can find Globals.NavigateURL under DotNetNuke.Common class.
o       First parameter of NavigateURL method is TabId of current page.
o       Second parameter is control id given by us ("newView" in our case here).
o       Third parameter is moduleId of current module.

Here hlnkNewView is an ASP Hyperlink control; you can use some other also ;)

This is all that needs to be done for having more than one view/edit controls in a single custom DNN Module.

Apart from this approach you can use ASP.NET MultiView control to manage multiple views. Rafe Kemmis has a great post about it at Managing Views In Your DotNetNuke Module

About Me

My photo
Delhi, India
Fun, music, travel and nature loving, always smiling, computer addict!!