First time at my blog? Check out the table of contents!
posted on Thursday, October 18, 2007 8:20 AM |

This is part II of the Making Your DotNetNuke Module Do More For You series. In Part I of this series I showed you how to start modifying your data access layer to achieve such things as passing stored procedure output parameter values up into your business logic layer and presentation layer.

Today I want to show you how to tackle some common tasks so that you can begin doing so right away. We will be focusing on how your module can change properties on the page as well as how you can set your module to change based on what page it lives on. Here is what we will be covering:

· How to modify data inside the <head> section of the DotNetNuke page.

· How to work with the DotNetNuke page URL.

· How to store and retrieve settings for an instance of your module.

So let’s get it on.

Changing the DotNetNuke Page Title and <head> Section Meta Data

In a typical .Net web application you can change the title of a page on the fly by accessing the Page object’s Title property.

  1 protected void Page_Load(System.Object sender,System.EventArgs e)

  2 {

  3    Page.Title = "My Custom Page Title";

  4 }

But from within your DotNetNuke module code you do it in a slightly different way. You first type-cast the Page object into a DotNetNuke.Framework.CDefault variable. Then you read and write the Title member on the CDefault object:

  1 protected void Page_Load(System.Object sender,System.EventArgs e)

  2 {

  3    DotNetNuke.Framework.CDefault cd

  4         = (DotNetNuke.Framework.CDefault)Page;

  5    cd.Title = "My Custom Page Title";

  6 }

If you compare Page.Title to CDefault.Title you will notice that Page.Title is a public property and CDefault.Title is a public member. What’s going on here?

image

image

Let’s take a look under the hood of the framework. Inside the CDefault source you will find this code:

   40 Public Class CDefault

   41    Inherits DotNetNuke.Framework.PageBase

   42 

   43    Public Comment As String = ""

   44    Public Description As String = ""

   45    Public KeyWords As String = ""

   46    Public Copyright As String = ""

   47    Public Generator As String = ""

   48    Public Author As String = ""

   49    Public Shadows Title As String = ""

You will notice that CDefault inherits from DotNetNuke.Framework.PageBase. Let’s take one step further and look at what the PageBase code looks like:

   50 Public MustInherit Class PageBase

   51 

   52    Inherits System.Web.UI.Page

You can see that PageBase inherits from the System.Web.UI.Page class. What is going on is that CDefault is a descendant of PageBase, and inherently a descendant of the Page class as well. Thus it has all the members and method of those two classes.

However, CDefault defines its own public string called Title which “shadows” the Page.Title property. This essentially hides the Page.Title from Visual Studio’s IntelliSense when you’re viewing the properties and methods of a CDefault object.

   49 Public Shadows Title As String = ""

So when you set CDefault.Title you are actually setting a different variable than Page.Title.

The nice thing about having the CDefault object around is that it exposes several other parts of the page for you to work with besides the title.

   44 Public Description As String = ""

   45 Public KeyWords As String = ""

   46 Public Copyright As String = ""

   47 Public Generator As String = ""

   48 Public Author As String = ""

These members allow you to set the values of meta-data in your page header.

    1 cd.Description = "My Custom Description";

    2 cd.KeyWords = "Coffee, Mojo, Hat";

    3 cd.Copyright = "My Company";

    4 cd.Generator = "Foo Coder";

    5 cd.Author = "Custom Author Name";

Will render as:

image

Note that in the code above, cd is a CDefault object.

Knowing how to set these values can be important for those of you concerned with search engine optimization.

Working With The DotNetNuke Page URL

As you probably already understand, the typical DotNetNuke installation really only has one page, Default.aspx. The Default.aspx page receives the tab id (the id of the page it needs to display) via the query string using URL Rewrite. Inside the SiteURLs.config file in the root folder of your installation there exists the following rule which tells the URL Rewritting Http Module to convert the search engine friendly URL into a URL that passes the tab id to the default.aspx page via the query string:

   28 <RewriterRule>

   29    <LookFor>[^?]*/TabId/(\d+)(.*)</LookFor>

   30    <SendTo>~/Default.aspx?TabId=$1</SendTo>

   31 </RewriterRule>

This is a powerful tool that you can customize in order to make your module more functional.

Just as the DotNetNuke site uses the URL rewriter to reduce the page files down to just one, you can use the URL rewriter to reduce the module instance quantity down to just one. Let me explain.

Let’s say that you have a database table containing 10,000 records, each of which you want to provide individual pages for. Rather than generating 10,000 tabs / pages inside your DotNetNuke installation, you can create a URL rewrite rule like this:

   12 <RewriterRule>

   13   <LookFor>.*/Products/(.+)/(.+)\.aspx</LookFor>

   14   <SendTo>~/Default.aspx?TabId=54&amp;brand=$1&amp;item=$2&amp;mode=view</SendTo>

   15 </RewriterRule>

In this rule you tell the URL rewriter to look for a regular expression that matches a request that looks like http://www.yourdomain.com/Products/SomeBrand/ProductName.aspx, where SomeBrand can be anything and ProductName can be anything. Those two “anythings” will be the key to one of the records you wish to display from your database table. The rule rewrites the URL to point to a specific tab (tab 54) on which there exists an instance of your module. This allows you to have a unique URL for each of the 10,000 products in your database, but only one tab within DotNetNuke for displaying them.

Now your module can display whatever it pleases based on the friendly URL that was originally requested! Have your module fetch the brand and item parameters through the query string:

    1 if (Request.QueryString["brand"] != null

    2    && Request.QueryString["item"] != null)

    3 {

    4    string path = Request.QueryString["brand"]

    5         + "/" + Request.QueryString["item"];

    6 

    7    // now use the path string as a

    8    // key to a record in your database

    9 }

Of course you need to take care not to pass on any old query string data on to your DAL. I usually run the values I get from the query string through some code like this which removes spaces and special characters:

    1 // remove non [A-Za-z0-9] with spaces

    2 myString = Regex.Replace(myString, "[^A-Za-z0-9]", " ");

    3 // remove spaces

    4 myString = myString.Replace("  ", " ").Trim();

For the sake of simplicity you might consider passing the numeric id / key of the item in your database rather than the brand and product name text like the example above. By doing so you can keep your data redundancy low inside your database, and eliminate the chance of two items having the same path in the URL. On the other hand the URL containing only text might be considered more optimized for search engines. This is a trade-off you will have to consider on your own.

Final, here is one note regarding URLs for the Asp.Net beginners reading this. You will probably at some point want to advance the browser to one of the product URLs manually. This can be done using the Response.Redirect() method.

    1 Response.Redirect("/Products/"

    2    + path + ".aspx");

 

Storing And Retrieving Settings For Your DotNetNuke Module

I am aware that this topic has already been covered by many fine tutorials out there. However, I want to mention it because there appears to be a major typo in the official Module Development Guide that is a show-stopper. So here is a brief explanation that will allow your show to go on!

You should first understand that you will usually want to store module settings per each instance of your module. This allows for individually configured instances of your module to live within the same portal.

To do this you must key off of your module instance’s id. You can access this id by referencing your module’s ModuleId property that is inherited from the PortalModuleBase class. You will be passing this value into methods that store the settings for your module’s instance.

To access a stored setting for your module from within your main view control code is easy. Just reference the Settings property that is inherited from PortalModuleBase. The Settings property is an associative array that keys on the name of the setting you used to store it in the first place.

    1 protected void LoadMySettings()

    2 {

    3    if (Settings["Mode"] != null)

    4    {

    5         _mode = Settings["Mode"].ToString();

    6    }

    7    if (Settings["ShowPicture"] != null)

    8    {

    9         _showpicture = bool.Parse(Settings["ShowPicture"].ToString());

   10    }

   11    if (Settings["ListTitle"] != null)

   12    {

   13         _title = Settings["ListTitle"].ToString();

   14    }

   15 }

Now on to storing you modules settings.

Storing your settings is more complex because it must be done from within a control that subclasses from the ModuleSettingsBase class. If you’ve read through the Module Development guide then you should know what I am talking about.

Your subclass is required to override the LoadSettings() method and the UpdateSettings() method. Inside your LoadSettings() method you read the settings using the ModuleSettings property that is inherited from the ModuleSettingsBase class. The Module Settings property is an associative array just like the Settings property of the PortalModuleBase class.

    1 public override void LoadSettings()

    2 {

    3    if (ModuleSettings["Mode"] == null)

    4    {

    5         ModuleSettings["Mode"] = "Small";

    6    }

    7    ModeDropDownList.SelectedValue =

    8         ModuleSettings["Mode"].ToString();

    9 

   10    if (ModuleSettings["ShowPicture"] == null)

   11    {

   12         ModuleSettings["ShowPicture"] = false;

   13    }

   14    ShowPictureCheckBox.Checked =

   15         bool.Parse(ModuleSettings["ShowPicture"].ToString());

   16 

   17    if (ModuleSettings["ListTitle"] == null)

   18    {

   19         ModuleSettings["ListTitle"] = "Title";

   20    }

   21    TitleTextBox.Text =

   22         ModuleSettings["ListTitle"].ToString();

   23 }

To store settings for your module’s instance, you must write code inside the UpdateSettings() method. You store values by creating a ModuleController object and calling its UpdateModuleSetting() method.

    1 public override void UpdateSettings()

    2 {

    3    ModuleController modController = new ModuleController();

    4    modController.UpdateModuleSetting(ModuleId,

    5         "Mode",ModeDropDownList.SelectedValue);

    6    modController.UpdateModuleSetting(ModuleId,

    7         "ShowPicture", ShowPictureCheckBox.Checked.ToString());

    8    modController.UpdateModuleSetting(ModuleId,

    9         "ListTitle", TitleTextBox.Text.Trim());

   10 }

 

To Summarize

By using these essentials, you can start making your modules do some amazing things.

  1. Changing a page's title and <head> meta-data is as easy as casting your Page object to a DotNetNuke.CDefault object.
  2. By creating a custom URL Rewrite you can have one instance of your module display different information for different URLs. Place your rule inside the SiteURLs.config file and use the Request.QueryString associative array to access the key to the record in your database that you wish to display.
  3. Inside any of your code that subclasses the PortalModuleBase class you can retrieve modules settings through the Settings property. Inside code that subclasses the ModuleSettings class you can retrieve module settings through the ModuleSettings property. To store settings for a module you must create an instance of the ModuleController class.

Part III of this series will be here soon! Bookmark this page or subscribe to the blog feed to be notified when it arrives.

 

Thanks for reading!

 

Comments Leave Yours...
baldwin
6/5/2008 10:39 PM
# re: Common DotNetNuke Module Page Tasks

Thanks for your sharing! The page title and setting had been understood excluding the "Working With The DotNetNuke Page URL", maybe I need to learn the friendly url in dnn. if there is any question, can you help me solve it?

Rafe
6/6/2008 6:23 AM
# re: Common DotNetNuke Module Page Tasks

Sure thing baldwin. Shoot me an email or post a comment here.

niels
8/21/2008 1:46 AM
# re: Common DotNetNuke Module Page Tasks

Hi,

I was just browsing the net for DNN modules that can help me solving my url problem. My website has an online shop (sysdatanet store) and a typical product details page looks a bit like this:

Default.aspx?TabID=703&TabIDOrig=1439&productID=1221&categoryid=98&langID=0&CurrPage=1&Search=&SearchCurrPage=1&cs=0&tmpModID=-1

so not very sexy! And not good for SEO!

I have tried DNN master SEO pack but that only rewrites the url up to page level and I need product level as many of my customers google on product names.
I was reading through your blog, and although I do not quite understand it all (unfortunately I do not have a bachelor in computer science!), it seems you have a solution for this in half a dozen lines of code which I find amazing.

Are you able to help me out here by explaining things a bit more?

It would be much appreciated.

Regards,

Niels

David
4/12/2009 8:51 AM
# re: Common DotNetNuke Module Page Tasks

for example, if my original URL is "http://www.Test.com/Community/tabid/67/categoryid/17/Default.aspx", I want it more SEO and change it similiar with that URL "http://www.Test.com/Community/17.aspx" or "http://www.Test.com/Community/CategoryName.aspx".How can I achieve it? Thanks a lot

chalama
5/14/2009 8:07 AM
# re: Common DotNetNuke Module Page Tasks

Kemmis,

you do a great job in posting all these tidbits of info that are really useful to work in dotnetnuke.

keep rocking!!
~chalama

Post Your Comment

Title
Required
Name
Required
Email
Optional
Url
Optional
Comment  
Please add 1 and 7 and type the answer here:

Who Is Rafe

rafe

Rafe Kemmis

I am an audacious web developer with a double bachelor of science in Computer Science and Mathematics. I specialize in Microsoft ASP.Net, Silverlight, and Adobe ActionScript.

Questions?

Always a thoughtful response. You may post your question on an article, or contact me directly.

Hire Me.

I provide custom solutions to complex problems. I can help your business no matter how large or small.

Contact me now.

Subscribe


Join me at CodeStock June 26-27, Knoxville, TN