Apr 9

Written by: Bruce Chapman
Wednesday, April 09, 2008 11:46 AM 

I spent a whole cache of hours yesterday tracking down a bug reported with the iFinity Friendly Url Provider. This bug was that the RSS feed button which is in-built into DNN modules didn’t work. The problem turned out to be the same old thing that causes the majority of incompatibility between my Friendly Url Provider and other DNN Core functions and DNN Modules – misuse or non-use of the Friendly Url Provider API. So, please, if anyone writes DNN code for anything, please see what I have to say

I spent a whole cache of hours yesterday tracking down a bug reported with the iFinity Friendly Url Provider. This bug was that the RSS feed button which is in-built into DNN modules didn’t work. The problem turned out to be the same old thing that causes the majority of incompatibility between my Friendly Url Provider and other DNN Core functions and DNN Modules – misuse or non-use of the Friendly Url Provider API. So here’s my plea to DNN developers worldwide, both core and third party: please use all the Friendly Url API features to create your Urls, don’t craft them up yourself within your code!

Generating a DNN internal site Url

Anyone who has written any DNN code will sooner or later have to generate a Url to put as the Href behind a generated link. Soon enough they will come across the DotNetNuke®.Common.Globals.NavigateUrl( ) call. This takes in the page you’d like to generate the Url for, plus some other options regarding Portal Alias (the domain name), and any query string values. Great! It works like a charm, and the underlying NavigateUrl() code also figures out whether you are running friendly Urls or not. 

However, developers often want something slightly different to the /default.aspx reference that inevitably shows up at the end of the Url.

Most of the time that I have seen, the developer takes the power into their own hands and starts replacing ‘default.aspx’ with their desired value in their own code.  The code inevitably looks like this:

Dim url as string = DotNetNuke®.Common.Globals.NavigateUrl(tab, path, etc..)
url = url.Replace(‘default.aspx’, ‘my-clever-hack.aspx’)

Because the Url Rewriting actually ignores the .aspx, it doesn’t matter, and the code works.

Everyone is happy, and the code is checked in. Don’t believe me? Try going to this Url and tell me if it works or not : http://www.dotnetnuke.com/tabid/125/But_I_Don't_Want_A_Download.aspx  (it’s the DotNetNuke® downloads page)

You don’t need the default.aspx – you only need the /tabid/125/.aspx - everything else is superfluous.

The .aspx is only there to tell IIS it’s an asp.net request, and the tabid/125/ does all the heavy lifting in finding the right page to display.

The problem comes when the developer replaces the page name with something that needs to be in the Url to make something work.

In the case of the RSS feeds, you’ve got to request the page called ‘rss.aspx’.

In the e-commerce module ASPDOTNETSF for DNN, it contains the product information, like this:  /products/tabid/55/p-1-product-name.aspx

In both of these cases, the developers that wrote the code replaced the ‘default.aspx’ with the custom page value after calling the Friendly Url Provider.   And this stops the Friendly Url Provider knowing that there is a special case to handle.

Only then someone, in the future, replaces their standard Friendly Url Provider with a new one – and all of a sudden things don’t work anymore, because the default.aspx gets removed from the resulting url that gets generated. Anyone interested in getting Friendly Urls to work on DNN considers the /default.aspx appendix on all the pages to be the greatest problem, closely followed by the tabid/nn path. So default.aspx is always the first up against the wall when the Url revolution comes, and any code that assumes it will be there is now broken.

The Correct Way to get a Url when you want to replace default.aspx

Now, the only module I know of that works correctly is Scott McCulloch’s News Articles module, which isn’t surprising given that he wrote the DNN Friendly Url Provider.  He knows how to call the Friendly Url API correctly, which is to forget NavigateUrl, and call the FriendlyUrlProvider, like this:

DotNetNuke®.Services.Url.FriendlyUrl.FriendlyUrlProvider.Instance().FriendlyUrl(tab, "~/Default.aspx?TabId=" & tab.TabID.ToString(), "My_Custom_Page_Name.aspx")

This code calls the Friendly Url Provider, and uses a little-known feature which allows you to specify a custom page name. I’ve posted on DotNetNuke®.com forums before about how the Blog module could instantly make thousands of people happier if they used this call to generate the internal links for the module. All it would have to do is supply the title for the blog post as the custom page name, and the entire module would become more valuable to those who are of a SEO bent. 

In truth, the NavigateUrl( ) call should probably have one more overload added to it, which takes a custom page name and passes that through to the configured Friendly Url Provider. Developers would be much more likely to discover the overload and say ‘hey, neat, I can provide any page name I like’. If the DNN core member responsible reads this, then I’ll give you the code on how to do it.

At least the Blog module doesn’t modify the url after the Friendly Url Provider call, though. The other modules which do modify the Url after calling the Friendly Url Provider leave developers (like me) of customized Friendly Url Providers out in the cold when it comes to interoperability.    Developers take note: you need to tell the Friendly Url Provider that a special case is being used, so that it can handle it.

In the case of RSS feeds, just by modifying the core code to call down to the Friendly Url Provider, it’s easy to intercept the call and say ‘oh, that’s for an RSS feed – well, in that case, here’s your RSS url’. Without it, you are stuck with /default.aspx on every page you want an RSS feed. For websites with friendly Urls, that’s a disaster case.

In the case of ASPDOTNETSF, well, that’s even more difficult. The module won’t work at all with any Friendly Url Provider because the whole thing is built on the assumption that DNN urls look like this : domain.com/pagename/tabid/xx/default.aspx. Change that, and the whole thing doesn’t work.

Well, I shouldn’t say ‘won’t work at all with any Friendly Url Provider’ because I have developed a way to make it work with my Url Master for DotNetNuke module. It’s not just by having ‘unfriendly’ urls on the product pages, either, I’m talking about full, human friendly Urls  for the ASPDOTNETSF product and category pages.  But it would have been a lot easier if they had used the Friendly Url API in the first place!

Update

Since writing this, Chris Hammond from Engage has informed me that the Engage:Publish module does indeed use the right way of generating a custom Url.  I should have known this already from another thread regarding the iFinity Friendly Url Provider - I was able to sort out a problem he was having precisely because the Engage:Publish module behaved in the right way!  So add another one to the list.

Tags:

15 comment(s) so far...

Re: An open letter to the DotNetNuke® developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

Wow, this post is HUGE in IE7, you have to scroll for a mile to the right to read it!

By Chris Hammond on   Wednesday, April 09, 2008 11:33 PM

Re: An open letter to the DotNetNuke® developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

@chris

Malformed Html tag destroyed the layout. But all fixed now, thanks for letting me know. It should be nice in any browser :)

By bchapman on   Wednesday, April 09, 2008 1:04 PM

Re: An open letter to the DotNetNuke® developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

Nice post. Didn't realize that the FriendlyURL provider did that. I'll have to review my code to make sure I'm using it.

By n3bu1a on   Wednesday, April 09, 2008 11:33 PM

Re: An open letter to the DotNetNuke® developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

n3bula1

Hey, join the revolution, and modify your code today! Friendly Urls for all DotNetNuke® code :) Seriously, it's a 5 minute change and makes all the difference with the quality of Urls.

By bchapman on   Wednesday, April 09, 2008 11:34 PM

Re: An open letter to the DotNetNuke® developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

Great article. I suggest that use also highlight also the correct code, not only the bad example.

By Stefan Cullmann on   Friday, April 18, 2008 7:15 AM

Re: An open letter to the DotNetNuke® developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

Bruce,

Great information.

Also, a recommendation, if you have the code for the additional overload for the NavigateUrl object, you should post it to support.DotNetNuke®.com, supposedly that is the best way to "submit" code for inclusion in the core if you are a non core team member...

By Mitchel Sellers on   Friday, April 18, 2008 7:15 AM

Re: An open letter to the DotNetNuke® developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

@stefan
The suggested code was there, it just has a formatting problem :DotNetNuke®.Services.Url.FriendlyUrl.FriendlyUrlProvider.Instance().FriendlyUrl(tab, _ "~/Default.aspx?TabId=" & tab.TabID.ToString(), "My_Custom_Page_Name.aspx")

@mitchel
I'll log in two requests - one for the navigateUrl overload, one for the way the RSS feed aggregator is created.

By bchapman on   Friday, April 18, 2008 8:43 AM

Re: An open letter to the DotNetNuke developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

The gemini request to add in an extra 'navigateUrl' is here : vote for it if you like it :)

http://support.dotnetnuke.com/issue/ViewIssue.aspx?id=7400&PROJID=23

By bchapman on   Friday, April 18, 2008 9:12 AM

Re: An open letter to the DotNetNuke developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

Hi Bruce,

Great article!

I would like to update all my modules to use this method but I am concerned about the affect on SEO. For example, on PokerDIY, I have 400 or so poker leagues (for example - http://www.pokerdiy.com/Leagues/PokerLeague/tabid/514/LID/241/Default.aspx). I would much prefer this to be "http://www.pokerdiy.com/Poker-League-241/Rods-Poker-League" or similar, but as soon as I change my NavigateUrl() methods then every league will cause duplicate content.

Can URL Masters be configured to handle a generic URL rewrite like this or would I need to use PageBlaster to do it?

By rodneyjoyce on   Tuesday, July 01, 2008 9:31 AM

Re: An open letter to the DotNetNuke developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

@rod

If you're going to change the way your module works, you do need to think about the knock-on effect with search engines, as you have rightly pointed out. The best way to go is to implement a 301 redirect for your 'old' Urls.

You can do this inside your module (detect when the 'old' version of the Url was issued by looking at the 'UrlRewrite:OriginalUrl' item in the context.items collection) and issuing a 301 redirect to the 'new' url.

Or, as you have pointed out, you can use an external module like the Url Master module to implement the 301 redirect for you. Not sure if Page Blaster can handle this for you or not.

I'll send you a PM regarding the redirects.

By Bruce on   Tuesday, July 01, 2008 9:39 AM

Re: An open letter to the DotNetNuke developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

Hi Bruce
I am a new bee to Dotnetnuke. I have this problem. Can you please help me to figure out exct place to change this code for FriendlyUrl for RSS feeds

By mittalsoni on   Wednesday, August 13, 2008 1:07 PM

Re: An open letter to the DotNetNuke developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

hi
if i write DotNetNuke.Common.Global. i cann't found NavigateURL ?
plz explan if i need to add any dll to my protal ?

By almny on   Tuesday, May 19, 2009 4:56 PM

Re: An open letter to the DotNetNuke developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

sorry
i should write
DotNetNuke.Common.Globals.
not
DotNetNuke.Common.Global.
:)

By almny on   Tuesday, May 19, 2009 4:59 PM

Re: An open letter to the DotNetNuke developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

I'm having a problem when using Globals.FriendlyUrl on my localhost. When I use it by running my site through IIS on my localmachine it returns a string such as: localhost/eol/MyPortal/TabId/172/Default.aspx
However if I run the site through VWD using the builtin Webserver I get the value:
/eol/MyPortal/TabId/172/Default.aspx

This is kinda annoying. Anyone else having this issue or am I doing something weird?

ps this is using the line: Globals.FriendlyUrl(PortalSettings.ActiveTab, Globals.NavigateURL(202))

By Mark Chambers on   Monday, May 25, 2009 2:10 PM

Re: An open letter to the DotNetNuke developers of the world: Please start using the FriendlyUrlProvider API for custom page names!

@Mark : the behaviour you are seeing is indeed weird, and quite annoying. I'm guessing in your case the reason is the difference between the cassini built in webserver and 'proper' IIS in the way that the Url path information is constructed in the request context. I found this out the hard way while trying to develop a unit testing framework for DNN modules - there's a couple of blog posts about that somewhere.

The end result is that you have to learn to live with it and write your code to accept either result. Or start rewriting portions of the underlying code. I've rewritten the Friendly Url PRovider to always return the full domain name and path, just to eliminate confusion.

By Bruce Chapman on   Monday, May 25, 2009 2:18 PM

Your name:
Your email:
(Optional) Email used only to show Gravatar.
Your website:
Title:
Comment:
Add Comment   Cancel 
Need Help?
 

If you're having trouble with an iFinity Product, use the Support Forums to search for answers, and to post questions.

If you need help faster than that, or can't figure out the answer, try our Premium Support service.