A former twenty something in technology

Server Side Caching in DotNetNuke

Categories: DotNetNuke
Comments: No

The most expensive bottleneck in your application is asking for data from your SQL database. The fact of the matter is that it doesn’t matter is it doesn’t how many rows of data you request, the sheer request itself is costly.

The function below illustrates how easy it is to cache an object in DotNetNuke. It’s as simple as calling a standard function; checking in the cache if the value already exists; if not go get the data and then add it to the cache; return the cached object.

public static int GetInfoObject(int contentId)
{
	var cache = DataCache.GetCache(Constants.ModuleCacheKey + Constants.ContentType + contentId.ToString());
	if (cache == null)
	{
		var timeOut = 20 * Convert.ToInt32(Host.PerformanceSetting);
		cache = controller.GetInfoObject(contentId);
	if (timeOut > 0 & cache != null)
	{
		DataCache.SetCache(Constants.ModuleCacheKey + Constants.ContentType + contentId.ToString(), cache, TimeSpan.FromMinutes(timeOut));
	}
	}
	return cache;
}

When you should cache an object

Any time you will need to request that action more than once in a user single request
Any time that data is likely not going to change for several user requests
Any time you are sorting or filtering the same collection of data multiple times.
When not to cache

When the amount of data exceeds the amount of memory on your server.
Data is only going to be access by one person every few days.
The point is that almost all data should be cached in some shape or form. If your application contains a forum with millions of entries then you obviously can’t cache them all. But perhaps then consider only caching the top 100 posts that 90% of your users are going to see every time they hit the homepage of your forum.

Reminders when caching

When adding or updating a row in your database. Make your SQL provider call as normal but have your business logic layer update that object into your cache as well. This will eliminate the need to make another return trip back to the database to get the same data.
DotNetNuke caching provider is capable of updating all web heads automatically with any changes to the cache
In my next blog I’ll discuss the benefits of client side caching.

DotNetNuke SuperFan Recap 2011

Categories: DotNetNuke
Comments: No

I had a blast during the voting process with Clint, Richard, Gifford, Ralph and all the others who entered the contest. I was really nervous that Clint was going to beat me so I enlisted everyone I knew to check out DotNetNuke and vote for me every chance they got. Even then I was still worried! By the time we got to DNN World I was just excited about all the cool things that we did with this contest and the friendships I made. I’m just glad DNN cake was pre-contest or I would have lost for sure!

Special thank you goes out to Will Strohl who not only put on the contest but was an amazing host during my visit to DNN Corp HQ. Had such a great time traveling through Silicon Valley and seeing all the other local companies like Apple, Yahoo, and Google

During my visit to DNN’s HQ in San Mateo I got to sit down and really talk tech and the future of DotNetNuke. Chief Marketing Officer Mitch Bishop’s vision on showcasing what DNN has to offer to everyone in the community is amazing and I can’t wait to see all those ideas come into reality.

Joe Brinkman was even on hand to sit down w/ me and talk about what the cloud has to offer for DotNetNuke and ways myself and everyone can get the most out of it.

What I found the most inviting is how passionate everyone who is working on DotNetNuke is, everyone from HR to sales down to the accounts who have a great spirit and joined into all the festivities. Including some DNNFoos which Will Strohl and I dominated Chris Hammond and Richard Dumas.

I also got to see some of the other office tech equipment in the conference room where I video linked to Scott Willhite the Directory of Community Programs and Co-Founder of DotNetNuke. It was nice to get a real in depth look at the beginning of DNN .

I hope DNN Corp plans on holding the DNN Superfan again next year at the DNN World conference and I would love the opportunity to pass the crown to the next Super Fan.

DotNetNuke ships with a URL provider that over the years has gone through several updates in how it can handle URLs

Original Method – Default.aspx?TabId=52

Second Version – /Home/TabId/52/Default.aspx

Human Friendly (Current Default) – /Home.aspx

The new human friendly is great but still requires that the user append the .aspx to the end of the page names.

Case Study

Lets say you have a business card or promotion and you want to advertise a specific page on your site that people could actually type in

“www.domain.com/promo”

Typically what you would do is FTP into your DotNetNuke root directory, create a folder called promo and then create a default.htm page to redirect to www.domain.com/promo.aspx

Rewriting the URL

With IIS7 and Url Rewriting you can now add some lines to your web.config file and handle urls without the .ASPX extension. Below is an example of such a rewrite rule and you will place this inside of your node.

<rewrite>
    <rules>
        <rule name="sanitize aspx">
          <match url="(^.*)" />
          <conditions logicalGrouping="MatchAll">
            <add negate="true" input="{REQUEST_FILENAME}" matchType="IsFile" />
            <add negate="true" input="{REQUEST_FILENAME}" matchType="IsDirectory" />
            <add input="{URL}" pattern="(.*).(.*)" negate="true" />
          </conditions>
          <action url="{R:1}.aspx" type="Rewrite" />
        </rule>
    </rules>
</rewrite>

This code works by first making sure that a file or directory with the /promo does not already exist. If it does then the physical file will take precedence over the rewrite rule. Second it will then take the domain url and append the .aspx to the end if it does not exist. So when you type in /promo behind the scenes it is serving up the page /promo.aspx. This is done without redirecting or changing the url.

Now all your URLs in DotNetNuke can be simple and even more pretty.

Update 1/25/2012: Here is an alternative version if you want to do 301 redirects to the page name vs rewriting the url.

<rewrite>
    <rules>
        <rule name="sanitize aspx" stopProcessing="true">
          <match url="(^.*)" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            <add input="{URL}" pattern="(.*).(.*)" negate="true" />
          </conditions>
          <action type="Redirect" url="{R:1}.aspx" redirectType="Permanent" />
        </rule>
    </rules>
</rewrite>

Recover Your DotNetNuke Host Password

Categories: DotNetNuke
Comments: 20

Many times users will only have the portal admin account and not the host account which contains the highest level of permissions and allows for installing modules and overall portal maintenance.

One of the most common issues website owners have is they outsource the setup and maintenance of their website then for one reason or another they need to bring in another developer and the first thing that developer will ask is: “What is your HOST password?”.

If you don’t have the answer to that question don’t worry there are a few ways to recover this password. The long way is to find a user whos password you do know replace the encrypted password and salt key of the host user with the user you do know. That works fine and is useful and all but requires a firm understanding of using SQL and the inner workings of DNN. But there is a better way.

Forgot Password system will not work.

DotNetNuke for security reasons will not return a password in the forgot password system when sending emails to the host user accounts.

 

I have FTP access to my website.

If you have FTP access to your website you can recover your host password with a little bit of coding. Follow the steps below and we’ll create a webpage that will return your host password.

  • Create a new text file called RecoverPassword.aspx
  • Paste in the follow code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
<%@ Page Language="C#" %>
<script runat="server">
void Page_Load(object sender, System.EventArgs e)
{
DotNetNuke.Entities.Users.UserInfo uInfo =
DotNetNuke.Entities.Users.UserController.GetUserById(0, 1);
if (uInfo != null)
{
string password =
DotNetNuke.Entities.Users.UserController.GetPassword(ref uInfo, String.Empty);
Response.Write("Password: " + password);
}
else
{
Response.Write("UserInfo object is null");
}
}
</script>
<html>
<head>
<title>Recover Password</title>
</head>
<body>
</body>
</html>
view raw file1.cs This Gist brought to you by GitHub.
  • Now upload the file to the root of your DotNetNuke installation and visit the page.
  • Copy the password and REMEMBER to delete this page IMMEDIETELY so you don’t forget and your host password is exposed.

Slight variations to this script can be made if the developer removed the default host user account or you simply want to retrieve the password for another user.

This will be a quick post. If anyone is like me and using the 4.1 version of the core DotNetNuke blog module than you’ve probably noticed that the “Written by:” is blank when viewing an individual blog entry.

I did a little debugging and found the problem in the ViewEntry.ascx.vb on Line 119

If m_oBlog.ShowFullName Then
lblUserID.Text = m_oBlog.UserFullName
Else
lblUserID.Text = m_oBlog.UserName
End If

This needs to be changed to:

If m_oBlog.ShowFullName Then
lblUserID.Text = m_oEntry.UserFullName
Else
lblUserID.Text = m_oEntry.UserName
End If

I’ve provided the details and a link to a fixed version of the DLL on codeplex

But if you you don’t want to do that. You can use a little jQuery magic like I originally did to fix the problem until an official update is released.

<script type="text/javascript">

jQuery(document).ready(function(){
jQuery(".blog_author").html("Written by: Jonathan Sheely");
});
</script>

[Update: 7/12/2011] Original DLL posted to Codplex required DNN version 5.6.2. I’ve updated codeplex with a newer DLL that only requires DNN 4.7.0 or later. You can also download that DLL here from my blog

How to Backup DotNetNuke

Categories: DotNetNuke
Comments: No

This guide is for those who have a dedicated server and need to backup your DotNetNuke websites on a regular basis to prevent a disaster.

There is plenty of software out there that will take care of backing up your website but the problem is it is either A. Too expensive or B. Doesn’t backup everything you need.

Here is how I backup my websites and you can take some of these steps and bend them into what works best for you. These methods utilize simple command line and batch scripts to accomplish everything you’ll need. You will also need to install 7-Zip to handle the compression

Step 1: Backing up your databases

This script was primarily written for SQL Express in order to give you a scheduled backup that Full SQL has but is just as viable to use with the full version of SQL. The result of this script will leave you with a directory of .BAK files of every database in your installation with a date stamp.

DECLARE @BackupFile varchar(255), @DB varchar(30), @Description varchar(255), @LogFile varchar(50)
DECLARE @Name varchar(30), @MediaName varchar(30), @BackupDirectory nvarchar(200)
SET @BackupDirectory = E:\SQL Data\Backup\'
--Add a list of all databases you don't want to backup to this.
DECLARE Database_CURSOR CURSOR FOR SELECT name FROM sysdatabases
WHERE name <> 'tempdb' AND name <> 'model' AND name <> 'Northwind'
OPEN Database_Cursor
FETCH next FROM Database_CURSOR INTO @DB
WHILE @@fetch_status = 0

BEGIN
SET @Name = @DB + '( Daily BACKUP )'
SET @MediaName = @DB + '_Dump' + CONVERT(varchar, CURRENT_TIMESTAMP , 112)
SET @BackupFile = @BackupDirectory + + @DB + '_' + 'Full' + '_' +
CONVERT(varchar, CURRENT_TIMESTAMP , 112) + '.bak'
SET @Description = 'Normal' + ' BACKUP at ' + CONVERT(varchar, CURRENT_TIMESTAMP) + '.'

IF (SELECT COUNT(*) FROM msdb.dbo.backupset WHERE database_name = @DB) > 0 OR @DB = 'master'
BEGIN
SET @BackupFile = @BackupDirectory + @DB + '_' + 'Full' + '_' +
CONVERT(varchar, CURRENT_TIMESTAMP , 112) + '.bak'
SET @Description = 'Full' + ' BACKUP at ' + CONVERT(varchar, CURRENT_TIMESTAMP) + '.'
END
ELSE
BEGIN
SET @BackupFile = @BackupDirectory + @DB + '_' + 'Full' + '_' +
CONVERT(varchar, CURRENT_TIMESTAMP , 112) + '.bak'
SET @Description = 'Full' + ' BACKUP at ' + CONVERT(varchar, CURRENT_TIMESTAMP) + '.'
END
BACKUP DATABASE @DB TO DISK = @BackupFile
WITH NAME = @Name, DESCRIPTION = @Description ,
MEDIANAME = @MediaName, MEDIADESCRIPTION = @Description ,
STATS = 10
FETCH next FROM Database_CURSOR INTO @DB
END
CLOSE Database_Cursor
DEALLOCATE Database_Cursor

Now that you have the ability to backup all your databases. We need to schedule this to run on a regular basis and clean up old versions so we don’t end up filling up our entire hard drive. For this step I’ve created a batch file that will

  1. Runs SQLCMD which comes with MS SQL connecting to (period = localhost. Your installation may be at .\SQLEXPRESS instead) your SQL installation and run the above SQL script
  2. Utilizes 7-Zip to go through every .BAK file in this directory and compress it to save space
  3. Deletes the no longer needed .BAK files
  4. Removes any file in this directory that is longer than 14 days.
sqlcmd -S . -i "E:\SQL Data\Scripts\Backup_All_Databases.sql"
forfiles /p "E:\SQL Data\Backup" /s /m *.bak /c "CMD /c C:\Progra~1\7-zip\7z.exe a -tzip -mx=10 @PATH.zip @PATH"
forfiles /p "E:\SQL Data\Backup" /s /m *.bak /c "CMD /C del /Q @FILE"
FORFILES /p "E:\SQL Data\Backup" /s /m *.* /d -14 /c "CMD /C del /Q @FILE"

All that’s left now is to create a Scheduled Task to run the above batch file every night and you have SQL backups!

Step 2: Backing up your website

An important step that is OFTEN overlooked is backing up the website files associated with your website AS WELL as the databases. Backing up your websites can be just as easy as the databases. All you need is another batch file:

  1. Gets a date stamp in the format of 20110514 to use to append to file names
  2. Gets a list of all the directory names where your websites are stored. (Recommend that all your websites be stored in a directory by their domain name. ex: C:\webs\twentytech.net”). This will then send that directory to 7-Zip for compression and output the results of that zip file to your C:\Backup directory
  3. Removes any file in any of the sub directories that is older than 14 days.
for /f "tokens=2-4 delims=/ " %%a in ('date /t') do (set mydate=%%c%%a%%b)
for /f %%a IN ('dir C:\webs\ /b /ad') do C:\Progra~1\7-zip\7z.exe a -tzip -mx=10 "C:\Backups\%%a\%%a_%mydate%.zip" "C:\webs\%%a"
forfiles /p "C:\Backups" /s /m *.* /d -14 /c "CMD /C del /Q @FILE"
Like before just create a scheduled task to run this batch file every night and you will have a 14 day backup of your website.

Remove the Useless WWW from DotNetNuke

Categories: DotNetNuke
Comments: No

If you’re like me and find the use of WWW in URLs both unnecessary and annoying then here is a little tip for you to easily remove it from all your urls.

Note: Before you proceed make sure you have an DNS (A) record setup already for your domain with and without the www.

DotNetNuke provides a FriendlyURL Provider that allows for regular expression matches in Host Settings. Here you can create a new rule that removes the WWW and issues a 302 redirect to the non-www domain.

Create a new rule that:

  • Matches: (.*)www.(.*)
  • Replaces: $1$2

RemoveWWW

The DNN EventLog contains a great deal of information. It Includes everything from critical errors to mundane items such as when a user logs in. All of which enables it to fill up very quickly and can be a burden to manage if you have multiple installations of DotNetNuke.

In order to solve this problem I wrote a SQL script that can be run as part of your server’s maintenance plan or ad-hoc. The goal of the script is to find all the DotNetNuke databases on your server and truncate the EventLog table.

How it works:

  • Searches through all your databases.
  • Locates the databases that contain a DotNetNuke application.
  • Finds the EventLog even if an object qualifier has been added to the tables.
  • Truncates the table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
--Application: Clear EventLog in all DotNetNuke Databases
--Created By: Jonathan Sheely
DECLARE @DEBUG BIT
SET @DEBUG=1 --Switch from EXEC to PRINT
DECLARE @dbname NVARCHAR(100)
DECLARE @EventLogTableName NVARCHAR(100)
DECLARE @ParmDefinition NVARCHAR(100)
DECLARE @sqlstr NVARCHAR(MAX)
DECLARE @sqlout NVARCHAR(100)
SET @ParmDefinition = N'@objOut nvarchar(100) output';
DECLARE databases CURSOR FOR
SELECT [name] FROM sys.databases
OPEN databases
FETCH databases INTO @dbname
WHILE (@@FETCH_STATUS<>-1)
BEGIN
SET @sqlstr='USE [' + @dbname + '];
SELECT @objOut=1
FROM sys.tables
WHERE [name] = ''aspnet_Applications'';'
SET @sqlout=NULL
EXEC sp_executeSQL @sqlstr,@ParmDefinition,@objOut[email protected]sqlout OUTPUT
IF @sqlout=1
BEGIN
SET @sqlstr='USE [' + @dbname + '];
SELECT @objOut=loweredApplicationName
FROM aspnet_Applications;'
SET @sqlout=NULL
EXEC sp_executeSQL @sqlstr,@ParmDefinition,
@objOut[email protected]sqlout OUTPUT
IF @sqlout='dotnetnuke'
BEGIN
SET @sqlstr='USE [' + @dbname + '];
SELECT @objOut=[name]
FROM sys.tables
WHERE [name] like ''%EventLog'';'
SET @sqlout=NULL
EXEC sp_executeSQL @sqlstr,@ParmDefinition,
@objOut[email protected]sqlout OUTPUT
IF @sqlout IS NOT null
BEGIN
SET @EventLogTableName[email protected]sqlout
SET @sqlstr = 'USE [' + @dbname + '];
TRUNCATE TABLE ' + @EventLogTableName +';'
IF @DEBUG=0
BEGIN
EXEC sp_executeSQL @sqlstr
END
ELSE
BEGIN
PRINT @sqlstr
END
END
END
END
FETCH databases INTO @dbname
END
CLOSE databases
DEALLOCATE databases
view raw file1.sql This Gist brought to you by GitHub.