iFinity Blogs 

Building Friendly Urls into DotNetNuke Modules Part 2 – Improving Module Urls

by Bruce Chapman on Monday, November 15, 2010 2:34 PM

This is part 2 in a series covering friendly Urls in DotNetNuke modules.  It is adapted from the presentation I made at the DotNetNuke Connections Conference 2010.   Part 1 covers some background on friendly urls and how that relates to DNN modules, you may wish to read that first if you have arrived at this post from somewhere else.

In the previous post in the series, I expanded on which part of a Url is related to a DotNetNuke module.  This was the example given:


This Url gets rewritten to this one on the server:


In the rewritten Url, the ‘tabid=795’ is used by DNN to load the correct page (the one with the Forum module) and the rest of the Url (forumid=77&threadid=381676&scope=posts) is used by the forum module to find and display the correct forum thread.

This entry in the series will cover how to make improvements to Urls such as the one shown above.

3 Levels of Improvements to DNN Module Urls

I’ll present three different levels of improvements you can make to DNN Module Urls, in ascending order of improvement (and difficulty to implement). 

First, though, we’ll look at level zero – what’s wrong with many DNN module Urls.

Using the Forum Url above (and I don’t mean to single out the Forum module as anything else than an example of what many modules do) you cannot, from the Url, identify what is on the page.  The Url is also very long, and will be difficult to transcribe, post and email.  In fact, it’s likely that emailing a long Url like the one above will ‘break’ it across lines in some email clients, making it finicky to copy/paste and click on.

Just to show that I’m not here to just gripe about the Forum module (which is very good in many respects) I’ll use a hypothetical module Url to explain the improvements that can be made.  It will be on a page called ‘species’ on a hypothetical DNN install.

Level Zero : No contextual Keywords, just meaningless Database Id’s in the Url.


Anyone care to guess what this hypothetical Url links to?  You can’t.  It’s impossible to know.  It’s as obscure as the frustrating Url-shortener craze that Twitter has enabled (and needs to put to the sword, if you ask me)

This is an example of a common DotNetNuke module Url.  It’s a hypothetical module that shows information in a series of articles.

This is the starting point for many DotNetNuke modules, both core and third-party, paid and free.  It continues the practice of locating the content in a database table (good) and then showing through that table structure in the Url by exposing the primary key value, a numeric integer (bad).  This is a shortcut on the part of the programmer – a simple and easy way to get the module finished and working.

Unfortunately for the end-consumer of the module, be it administrators, visitors or search engines, it doesn’t make any sense at all.  For the uninitiated, you’d be forgiven for asking where on earth you entered ‘56’ in your entry.  Well, you didn’t.  The system came up with that value and forced it upon you, as though the Url was something you’re not allowed to design or touch.

It’s my position that this is lazy programming – and I can hold my hand up to being a lazy programmer on many occasions.  Sometimes in the drive to deliver, some things aren’t considered important, and so are glossed over.  But I now see exposed database ids like I see exposed screwheads in a car interior or piece of furniture – ugly, unfinished and very much with an air of ‘home made’ about it.  It’s time to start moving away from this model.

Level 1 - ‘Good Urls’ : Incorporate Contextual Keywords into the Url.

This is a dead-simple improvement to the Url that can be done with a minimum of programming, and yields a useful improvement for the amount of time required.  The cost/benefit scale is very favourable.

This procedure is just to take a piece of contextual text, and drop it into the Url without changing the core structure of the Url.


Now you know what this Url is about.  Something about birds flying North for the Winter, I guess? (you didn’t really think I would say South, did you?).

How was this done?  It’s simple.  And, in case you think this is a new thing I’ve come up with, let me introduce you to a blog post of mine from over 2 years ago :  An open letter to the DotNetNuke developers of the world - please start using the Friendly Url Provider API for custom page names 

Well, I thought it was a snappy title at the time.

The core of this post is something I’ll reproduce here to save you going back in time and talking to the 2008 version of me.

Level 2  - ‘Better Urls’ : Reformat the Url for length and increase the keyword ratio

In our Level 1 example, some descriptive text was put on the end of the Url, which resulted in adding some context so that visitors and search engines could work out what might be on the page.

Level 2 is taking that further and increasing the keyword ratio of the Url.  The Keyword ratio is a concept I use, and it’s basically the ratio of meaningful words to meaningless words (or numbers) in the Url.   If you’re mathematically inclined, this would be:

Url words / meaningful Url words*

*By words, what I mean is parse-able blocks of characters, whether they are separated by /, – or even spaces, and whether they are words or numbers.  Some numbers are keywords, some numbers are just random junk (as far as the visitor is concerned).  Words that are just key/value pair placeholders are often meaningless to the visitor.  Ask a non-programmer, non IT person what ‘entryId’ means and you’ll get some very strange answers.  Remember, for most people, an ID is something you produce in order to buy beer.  Remember, most people would think a database table is a a piece of dining room furniture with a boxed copy of Microsoft Access on it.

The desirable value for the Keyword ratio is 1 : all words in the Url are meaningful.  It’s not like putting keywords into Html content- there’s no threshold at which search engines think you are spamming – if you only put keywords in your Url, they just think you’re being clear about the content of the page.  And they reward you for that with higher rankings.

The undesirable value is infinity : none of the words are meaningful.  The Url only makes any sense to the programmer and the program they have created. 

With that goal in mind, Level 2 is all about removing meaningless words as much as possible.  Here’s an example we might come up with:


You’ll see that this Url removes several ‘words’ from the Url.  Gone is ‘tabid’, ‘75’ and ‘entryId’.  The first two are achieved by implementing the Url Master module.  Note that the procedures described here don’t require the Url Master module, but as it’s a module which improves all Urls in a DotNetNuke site (whether module-specific or just for DNN pages) it’s worth noting here.  Without the Url Master module, this Url might look like this :


The differences are these:

1) the Url Master module removes the /tabid/75 part of the path from all Urls, not just those for ‘base’ DNN pages.

2) the Url Master module allows for single-part module urls.  The standard DNN Url Rewriter / Friendly Url Provider requires that all module specific Url parts are key/value pairs.  It won’t allow you to have a single-part querystring.  By single-part, what I mean is just having one path level after the page-specific Url information.

3) the Url Master module can remove the .aspx from the Urls

I’ll assume a Url Master module install in the rest of the examples shown, but be aware that it’s not a requirement, but it does help. I’m not trying to get vendor lock-in here.  Your module code should be Url Rewriter agnostic, and the Url Master module will improve when installed, but it must always work with the standard Url Rewriter as well.

Now, getting back to the example Url, a cursory look at the Url will reveal that we’ve joined the entryid and the Url Value together to make up the Url value.

The idea behind this is to just condense down the Url to a single string value.  There’s no extra rewriting in place, it’s up to the programmer to identify this string and parse out the entryid.  This is pretty easily done with a regex pattern, or even just a string.split() function.

So, we receive this as our Url Value in the module code : “56-migratory-birds”.

The code would just run a simple parsing routine to get the ‘56’ off the front, and would discard the rest of the information.  It’s not needed, it’s just there to raise the keyword density.  Once you have the all-important database ID for the content, the rest of the module is the same.

To generate the Url, you would call the NavigateUrl() call with the Url Value of ‘56-migratory-birds’ already created.  There’s nothing in the NavigateUrl() functions to append together this type of data – it needs to be done externally in the module and provided to the DotNetNuke API as a finished product.

Level 3 - ‘Best Urls’ : Creating a totally custom Url Value with only Keywords in it

The ‘Best’ level is achieved when you can completely remove the concept of keeping numeric database identifiers and fixed Url terms in the Url, and allow complete customisation of the Urls that are used to drive module content.

Here’s an example:


or, using a key-value pair instead of a single value

example.com/species/groups/migratory-birds  (where ‘groups’ is the key in the key/value pair)

In this example, the module must take the value ‘migratory-birds’ and find the right piece of content to display on the page.

This is done by implementing database logic that both allows creation of custom, unique Url Values that link to content, and by allowing customisation of items like the ‘key’ in key/value pairs.    This allows administrators to both choose (or customise a pre-set value) the Url Value (migratory birds) as well as the rest of the Url (the ‘key’ part, either with a set value, or missing altogether where the Url Rewriter permits).

Handling ‘Old’ Module Urls

Any developer who is experienced at developing DotNetNuke modules should be nodding sagely in agreement, but saying ‘yes, that’s all very well, but what about all the already-implemented versions of my module, you can’t just change the way the modules work’.

Actually, I’ve seen some modules do just that – change the Url structure between versions.  It’s very upsetting for people who have already implemented your code.  Please don’t do that without providing a migration path for the sites with existing bookmarked, indexed and linked Urls.

This is a problem with a simple solution : 301 redirects.  The 301 ‘permanent’ redirect is a status returned to the visitor and says ‘thanks for requesting that piece of content from our server.  Sorry, but it has moved over here’.  A 301 redirect allows old Urls to still work and for the visitor to be forwarded to the new location.  Search Engines used 301 redirects to keep their indexes current, and to allow webmasters control of the Urls of their code, which allows a site to grow and change over time.

So if you have an existing module that has been implemented anywhere, you’ll need to have a redirect strategy in place along with your new module changes.

Implementing in Code

The next post in the series will show how to actually implement these strategies in code.   You’ll see how to implement ‘Level 1’ Urls with about 10 minutes of coding and testing.  You’ll see how to build Level 2 and Level 3 Urls.  You’ll see different techniques for implementing redirects when an ‘old’ module Url is used.  You’ll see how to make your module much, much better and become very popular with the people who use it, particularly those with an eye for SEO (and that seems like everyone, these days).

Companion Module

This Blog Series (and the associated Conference presentation) has a companion module.  This is called the ‘iFinity MultiContent’ module.  This module is a simple way of displaying different Text/Html content on a page, by varying the Url value.  It’s built with the purpose of displaying the techniques that will be shown throughout this series of blog posts, and comes available with source code.

The MultiContent module shows ‘Level 3’ Urls at work, and the source code shows the techniques used to do this.

You can download it (for free) from this location : iFinity MultiContent Module

First article in this series : Building Friendly Urls into DotNetNuke Modules Part 1

Blogs Parent Separator Crafty Code
Bruce Chapman

The craft of writing code. The outcomes from being crafty with code. Crafty Code is tales from the coding bench.

2 comment(s) so far...

Anonymous 11/16/2010

this is a great seris of blogs cant wait for part 3!. <br><br>instresstingly this was almost badly timed for me, as i just completed a news module for one of the sites I help manage. I can assure you it had dirty urls for a week or so until our SEO guy asked if I could improve the url. Glad to say there now no number in my url and its full of keywords :)

Bruce Chapman 12/12/2011

Part 3 of this series is available here : <a href="http://www.ifinity.com.au/Blog/EntryId/104/Building-Friendly-Urls-into-DotNetNuke-Modules-ndash-Part-3-ndash-Implementing-new-Url-Schemes" rel="nofollow">www.ifinity.com.au/Blog/EntryId/104/Building-Friendly-Urls-into-DotNetNuke-Modules-ndash-Part-3-ndash-Implementing-new-Url-Schemes</a>

Bruce Chapman
Hi, I'm Bruce Chapman, and this is my blog. You'll find lots of information here - my thoughts about business and the internet, technical information, things I'm working on and the odd strange post or two.
Connect with Bruce Chapman on Google+

Share this page
Get more!
Subscribe to the Mailing List
Email Address:
First Name:
Last Name:
You will be sent a confirmation upon subscription

Follow me on Twitter
Stack Exchange
profile for Bruce Chapman at Stack Overflow, Q&A for professional and enthusiast programmers
Klout Profile

Page Tags