11/27/2008

How to promote a regular DotNetNuke user to a superuser

I found this in Kevin Southworth's blog and I think it's worth mentioning since it may save your life in case you have forgotten your superuser's password. Using SQL, you can promote a regular DNN user to a superuser like this:

 

-- Promote regular user to SuperUser

DECLARE @username varchar(50)

SET @username = 'theUsernameToPromote'

UPDATE 
   
Users 
SET 
   
IsSuperUser = 1 
WHERE 
   
username = @username

DELETE FROM 
   
UserPortals 
WHERE 
   
UserId = 
   
(SELECT UserID 
   
FROM Users 
   
WHERE username = @username)

 

Simply replace 'theUsernameToPromote' with the user name you need.

 

Thanks Kevin!

Read more...

11/23/2008

Persisting large values in Module Settings when creating a custom module

So you want to create a simple custom module. At first, it seems easy. Just two or three settings to take care of, no need for complicated, custom tables and unistall/uninstall scripts. DNN's built-in module settings API seems to be enough. But suddenly, needs grow a lot. There are some large values you need to store and the ModuleSettings table won't allow large chunks of information per row. It seems that you have to switch to a custom table which will be holding your settings...

 
...or use my class :)

 

I came upon the need of storing just one large value (a serialized object, to be more specific) in a custom module I was creating. I didn't have any way to know how large the serialized (XML) sting would be, since the object was a collection, and I HAD to store it in module settings. I thought it wouldn't be worth to create a custom table and the accompanying code to store settings in a case like this, so I decided to extend DNN's ModuleController class instead.


What I did was to write a new ModuleControllerExtended class which inherits from ModuleController (so I could use it in its place) and add two methods to it:


1. UpdateLargeTabModuleSetting: This method is essentially an extension of the UpdateTabModuleSetting method of the ModuleController class which allows storing large string values in the ModuleSettings table by breaking them into smaller chunks and storing multiple name/value pairs. If a value is small enough to fit into a single row of the ModuleSettings table, then it's stored normally, as it would with the UpdateTabModuleSetting method.


When the value is large, it's stored in 2KB chunks in several rows using a numeric prefix (in the form of _x) for each row, based on the initial name given for the setting. For example, a setting named "SerializedObject" with a value sized at 5KB would be stored in 3 rows with names "SerializedObject_0", "SerializedObject_1" and "SerializedObject_2" accordingly.


The method also takes care to delete rows from the ModuleSettings table every time an update takes place to ensure that there are no leftovers should you specify a value of a smaller size (and probably fewer chunks) than the one that may be already stored.

 

2. ReadLargeTabModuleSetting: This one reads a large setting doing all the work needed to give you back its string value, but it can also read single-row settings. This is a shared method, and it was added to the class only for consistency. It does not extend any of the known methods of the ModuleController class, meaning you can always remove it from the definition of the class and use it as stand-alone code.

 

To use the method, you will need the hashtable containing the module's settings, which you can easily get by using the base class GetModuleSettings() method. You feed the method with the hashtable, the module's id and the name of the setting you want and you get a string value containing the "large" value for the setting you specified, or just a setting value should the setting be a "normal" one.

 

It's not really complicated and it should save you a lot of time when dealing with situations like the one I described above. I would love to hear your comments, though.

 

Here's the code:

 


Imports Microsoft.VisualBasic
Imports System.Collections.Generic

Public Class ModuleControllerExtended
   
Inherits DotNetNuke.Entities.Modules.ModuleController

Public Sub New()
   
MyBase.new()
End Sub

Public Sub UpdateLargeTabModuleSetting( _
  
ByVal tabModuleSettings As Hashtable _
 
, ByVal tabModuleID As Int32 _
 
, ByVal settingName As String _
 
, ByVal settingValue As String)

   
Dim cntDel As Int32 = 0
   
Dim o As Object
   
Dim continueDeleting As Boolean
   
continueDeleting = True

   
'Delete all multiple-value module settings, if they exist. 
    While continueDeleting = True
       
o = tabModuleSettings(settingName + "_" + cntDel.ToString)
       
If Not o Is Nothing Then
           
DeleteTabModuleSetting(tabModuleID, settingName + "_" + cntDel.ToString)
           
cntDel += 1
       
Else
           
continueDeleting = False
       
End If
   
End While

   
'Guard - if setting value is less than 2KB, update normally and exit 
    If settingValue.Length < 2000 Then
       
'Normal value 
        UpdateTabModuleSetting(tabModuleID, settingName, settingValue)
       
Exit Sub
   
End If

   
'If we get to this point, then setting value is more than 2KB. 
    'Delete the original setting (if it exists) so as not to get confused. 
    DeleteTabModuleSetting(tabModuleID, settingName)


   
'Split the value in 2KB chunks 
    Dim stringList As New List(Of String)
   
Dim sb As New StringBuilder(settingValue)

   
While sb.Length >= 2000
       
stringList.Add(sb.ToString.Substring(0, 1999))
       
sb.Remove(0, 1999)
   
End While

   
'Add the last chunk 
    If sb.Length > 0 Then stringList.Add(sb.ToString)

   
'Now do the update changing the setting name with the suffix _x (x=0,1,2,etc.) for 
    'each update 
    Dim cnt As Int32 = 0
   
For Each s As String In stringList
       
UpdateTabModuleSetting(tabModuleID, settingName + "_" + cnt.ToString, s)
       
cnt += 1
   
Next

End Sub

Public Shared Function ReadLargeTabModuleSetting( _
    
ByVal tabModuleSettings As Hashtable _
   
, ByVal tabModuleID As Int32 _
   
, ByVal settingName As String) As String

   
'Guard - if there is a single setting, just return that and exit 
    Dim objTester As Object
   
objTester = tabModuleSettings(settingName)
   
If Not objTester Is Nothing Then
       
Return (CType(objTester, String))
   
End If

   
'If we got to this point, there's a large value stored. 
    'Loop through the records and reconstruct the value. 
    Dim sb As New StringBuilder
   
Dim cnt As Int32 = 0
   
Dim o As Object
   
Dim continueAdding As Boolean
   
continueAdding = True

   
While continueAdding = True
       
o = tabModuleSettings(settingName + "_" + cnt.ToString)
       
If Not o Is Nothing Then
           
sb.Append(CType(o, String))
           
cnt += 1
       
Else
           
continueAdding = False
       
End If
   
End While

   
Return sb.ToString

End Function

End Class

Read more...

11/07/2008

Creating pages based on templates - eventually!

All my attempts to use custom templates when creating new DNN pages for my portals were frustrating. Even though I exported the template from a page using the Export feature, the new template would not show up at all in the combo box when creating a new page, although it existed in the file system. Even the default template wouldn't show up!

Here's a simple solution to make those template files appear when you create a new page:

1. Go to Host Settings - Other Settings and locate the "File Upload Extensions" section. Add "template" (without the quotes) there and save your changes.

2. Click "Restart Application" in Host Settings.

3. Go to the File Manager and synchronize files with the "recursive" option set.

4. Optionally, clear the portal's cache in Host Settings (only if it doesn't seem to work differently).

Now you'll have access to your custom templates when creating new pages. Hope that helps.

Read more...

10/24/2008

Adding Javascript to the BODY tag in DNN

When working with .ascx skin files, you will sometimes need to add some Javascript to the BODY tag, such as something that runs when the OnLoad event triggers.

Well, you can always add a BODY tag inside your .ascx file along with the Javascript you like and hope that the browser will understand that. Essentially, you'll end up having two BODY tags in your source code-one that is generated by DNN and one that is typed by you. Some browsers (like Chrome) understand what's happening and try to transfer the Javascript to the actual BODY tag when rendering the page, but others don't.

What you can do, though, is create a Page_Init event handler inside your .ascx file and put this code there:

Dim body As System.Web.UI.HtmlControls.HtmlGenericControl = CType(Page.FindControl("body"), System.Web.UI.HtmlControls.HtmlGenericControl) 
body.Attributes("onload") = "blablablaJavascript"


Where blablablaJavascript is your Javascript. Of course, you can do that for other events (even for other tags) as well.

If you're using a single .ascx file with no code-behind (like most do), you'll want to define a Page_Init event there. You can do that like this:

<script runat="server">

 
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init 

'Add your code here

   
End Sub 

</script>

Read more...

Thickbox and Google Maps API - avoiding random thickbox initialization problems

Thickbox is a very nice JQuery-based Javascript plugin that allows you to present images and other stuff (even whole pages!) in your page in a popup manner but without leaving the current page or opening a new one. Essentially, it's considered an evolution of the Lightbox script which only works with images.

Many developers use Thickbox with Google maps, in order to provide clickable links on Google Map bubbles that lead to enlarged photos or other info. Some of them (including me) noticed, to their surprise, that suddenly Thickbox wouldn't work correctly inside Google Maps. Specifically, it would work once in a while, and the only way to ensure it worked would be to click on a bubble, close it an then click on another. Then all Thickbox links inside bubbles would work.

There seems to be a problem with the new version of the Google Maps API that kills the functionality of Thickbox. According to this discussion on Google Groups, a way to ensure Thickbox is working correctly is to "lock" on version 2.122 of the Google Maps API inside the Javascript that creates the markers. That is, use: google.load("maps", "2.122"); instead of google.load("maps", "2.x");

I've been using Thickbox and Google Maps in some DNN sites and I was panicked to see this happening in the first place. Although this post is not exactly DNN-related, I think it'll be useful to all of you working with DNN out there. I was very happy to know that there wasn't anything wrong with my DNN development, it was only Google's API.

Hope it helps.

Read more...

9/26/2008

Finding a tab's parent by level

This is a simple but useful user defined function I have implemented in order to recursively find a tab's parent on a specific level. Syntax is as follows:

select dbo.udfGetParentByLevel (level, tabid)

where level is the level you need (0,1,2 etc.) and tabid is the id of the tab for which you need to find the parent.

Nothing much, but can save you in certain scenarios.


CREATE FUNCTION udfGetParentTabByLevel
(
-- Add the parameters for the function here
@parentlevel int, @initialtabid int
)
RETURNS int
AS
BEGIN

declare @level int
declare @tabid int
declare @parentid int

select @level = level, @tabid=tabid, @parentid=parentid from tabs where tabid=@initialtabid

while @level > @parentlevel
begin
select @level = level, @tabid=tabid, @parentid=parentid from tabs where tabid=@parentid
end
-- Return the result of the function
RETURN @tabid

END
GO

Read more...

9/19/2008

Copying settings between DNNArticle modules

ZLDNN's DNNArticle is a really cool article module, loaded with a ton of features. Unfortunately, sometimes you'll have to add more than one modules on your site, and a ton of features typically comes with a ton of settings. In order not to have a hard time setting all the options from scratch, here is a script you can use to copy all those nifty settings you'll find in the "DNNArticle Settings" area from an already existing module.

You need to know three things: The source and destination module ids (NOT the tab ids, the actual module ids) and the tab id which will be used for the presentation of an article.

In the script given, I'm copying settings from module id 430 to module id 1232, with a view tab id of 986. Be sure to put your own numbers there.

Also, before running the script, make sure you have visited the settings area of the (newly added) DNNArticle module to be updated and have pressed "update" there (even if you haven't changed anything) so that the corresponding records are created in the ModuleSettings table.

The script is fairly straightforward, use at your own risk as always. Enjoy.

/* 
------------------------------------------------------ 
Start of values to be changed each run 
------------------------------------------------------ 
*/
 

-- This is the module id we are copying settings FROM 
declare @originalmodule int 
set @originalmodule=430 

-- This is the module id we are copying settings TO 
declare @moduletobeupdated int 
set @moduletobeupdated = 1232 

-- This is the view tab id for the module we are updating, in case it is 
-- different than the one of the source module. 
declare @viewtab int 
set @viewtab=986 

/* 
------------------------------------------------------ 
End of values to be changed each run 
------------------------------------------------------ 
*/
 

-- Some variables to hold table data 
declare @settingname nvarchar(50) 
declare @settingvalue nvarchar(2000) 

-- Get a cursor and start updating 
declare cur cursor fast_forward for 
select 
    
settingname 
   
,settingvalue 
from 
   
modulesettings 
where 
   
moduleid=@originalmodule 

open cur 
fetch next from cur into @settingname, @settingvalue 

while @@fetch_status=0 
begin 
   
if @settingname='ViewTab' 
   
begin 
       
update 
           
modulesettings 
       
set 
           
settingvalue=@viewtab 
       
where 
           
settingname=@settingname and moduleid=@moduletobeupdated 

   
end 

else 

begin 

       
update 
           
modulesettings 
       
set 
           
settingvalue=@settingvalue 
       
where 
           
settingname=@settingname and moduleid=@moduletobeupdated 

end 

fetch next from cur into @settingname, @settingvalue 

end 

close cur 
deallocate cur

Read more...
Related Posts with Thumbnails

Recent Comments

Free DotNetNuke Stuff

Free DotNet Videos

  © Blogger template The Professional Template by Ourblogtemplates.com 2008

Back to TOP