Rewriting the DotNetNuke Url Rewriter Module - Again
NOTE: Due to popular demand, there is now a Support Forum for support requests on this module, or if you just want the thing to work ASAP, I can provide one-on-one support or install it for you. What I did previously was improve upon Scott McCulloch's work by working out a way to handle parameters. All well and good, and it worked OK. But it just still didn't look quite right. What's more, I wanted to use the rel="tag" microformat on my tagging module, and I was stuck with the .aspx extension on everything, which the microformat doesn't recognise. So after some back and forwards on the Ventrian forum where I posted my update, I went away and had a good think about it. There were two things nagging at me: Doing number 1 was easy : just do a dictionary based lookup on the page path, if it's found, great. If not, 404 coming right up. It works like this (if you're not intimately familiar with DNN, you might want to skip to the next part). On the first request, a dictionary of path information is built up. This contains the path (example: mysite/mypage) and the actual DNN request Url (example: default.aspx?tabid=37). The dictionary is stashed away in the Cache. There is obviously a great deal more complexity in it than that, but that's the basic algorithm. So onto number 2. Some will look at you with fear in their eyes when you mention removing the .aspx extension from asp.net pages and declare that 'you cannot change the laws of physics'. But in reality there is nothing difficult about removing the .aspx extension from asp.net pages. There's really two (easy) ways. Given I was already rewriting Urls, the second of those options was the path of least resistance for me. Now I realise that people using DotNetNuke on a shared host aren't going to be able to do this, but if you've got your own server, it's not difficult. By mapping all requests to go through asp.net, all requests for items on the website (or virtual directory) end up going through the DNN Url Rewriter. Eek - better make sure they work then. To fix this, I implemented a couple of regex filters to be placed in the web.config. These restrict what items will be passed along to IIS unfettered and what will be rewritten by the UrlRewrite code. And that was about it - because the way the dictionary lookup works, the .aspx is redundant anyway. Because all entries in the dictionary are without .aspx, it's not needed to find them again - only the relative path. Once the messy .aspx extensions are eradicated, getting nicer Url's is easy-peasy. Instead of doing by front-to-back flipping of parameters around, now I just put them out in-line, as they should. So, from the example given in the first posting on this topic, the results now are: Of course, there are still times when the first-parm-last scenario might work well, so I've left it in as a configurable option. This is particularly the case if you can't remove the .aspx extensions (shared hosting, for example) Here's the original examples from the first post redone: The 301 redirect code in the original version was an important step forwards for my SEO DotNetNuke efforts. DNN has a habit of outputting a variety of Url's for the same bit of content, so it's important to stay on top of this by both generating a single Url per bit of content, but also to let Google know you've been on the case of hunting down every last default.aspx?tabid=37 and home/tabid/37/default.aspx reference. So the new code maintains the previous features, and adds a couple more - when a request comes in that doesn't end in a '/', it puts one on. If a request comes in for a page with .aspx, and you've turned .aspx off, then it returns a 301 status and gives the new, cleaner url. As well as this, if you've got a page you've deleted from your website, or it was only visible for a period of time, then requests for the no-longer-valid page will redirect to the home page of your portal with a 301. Here's a list of all the things that this version can do: Step 1: Download the code from the Free Downloads page. Step 2: Backup your existing DotNetNuke.HttpModules.UrlRewrite.dll from your website/bin directory, and copy the new version in to the /bin directory. Step 3: Backup your existing web.config, and then replace the existing 'DNNFriendlyUrl' provider section with this one: Step 4: Change any options to suit how you'd like your DNN installation to work. The full list is below. Step 5: Try it out! If you haven't already done so, you might want to take a look at the DotNetNuke Google Sitemap Generator available in the free downloads section pageExtensionUsage="never"* pageExtensionUsage="always" /Enquiries/ /Enquiries.aspx pageExtensionUsage="never" * parameterHandling="ordered" pageExtensionUsage="always" parameterHandling="ordered" /TagList/Tag/Valuers/ /TagList/Tag/Valuers.aspx pageExtensionUsage="never" * parameterHandling="firstparmlast" pageExtensionUsage="always" parameterHandling="firstparmlast" /TagList/Valuers/Tag/ /TagList/Valuers/Tag.aspx pageExtensionUsage="pageonly" * pageExtensionUsage="always" pageExtension=".page" ** /Enquiries.aspx /Enquiries.page pageExtensionUsage="pageonly" parameterHandling="ordered" pageExtensionUsage="always" pageExtension=".page" ** parameterHandling="ordered" /TagList/Tag/Valuers/ /TagList/Tag/Valuers.page pageExtensionUsage="pageonly" * parameterHandling="firstparmlast" pageExtensionUsage="always" pageExtension=".page" ** parameterHandling="firstparmlast" /TagList/Valuers/Tag/ /TagList/Valuers/Tag.page Warning: This may destabilise your website. Always check this on a test version first, and understand what you are doing! These instructions will vary between IIS 5.0, IIS 6.0 and the Workstation and Server versions of 2000/XP/2003/Vista Then thoroughly test all website functions. And you're done! Due to the problems with the 4.7 release and namespace collision with the config part of the module, I've released a new version which uses it's own namespace and should solve the problems. However, this requires new web.config entries. The changes are available in the free downloads section. This new version requires different modifications to the web.config from those shown in this blog post. The options are the same, but the namespace has changed. Please see the example.web.config file included in the downloads to see what changes are required for the web.config There are also three new features in this new version, which are set using the following configuration attributes: Again, see the example.web.config on the different options for these features Any problems please report them using the comments section below (I might have to stretch to forums one day!) In response to the many requests to include a way of substituting spaces with a '-' or '_', I have included a 'replaceSpaceWith' option. This will replace any spaces in a tab path with the supplied character. It will also issue a 301 redirect for any request to the 'space removed' version. This means that existing pages found in search engines will redirect to the new version. I've also fixed (finally) the problems with getting an exception on the Host Settings page. Basically, in versions of DotNetNuke prior to 4.5, the Friendly Url Provider shared a namespace with internal classes. I've explictly implemented a cast so that my provider will be able to interact with the host settings page. However, for DNN versions 4.6 and above, the FriendlyUrl provider was moved into the single DotNetNuke.HttpModules assembly. This solved the problem, so the later version of my Friendly Url provider just doesn't include the section for reading the FriendlyUrl rules. The new files can be found on the Free Downloads page. You must install the correct version for your DNN install. If you are running 4.0 - 4.5, then you want the 4.5 version. If you are running 4.6 or later, then you want the 4.6 version. Trying to run the later version with the earlier DNN installs will just cause errors - there is no benefit in running the 4.6 code - it's just a compatibility change, both version are built from the same base source.Redoing the DotNetNuke Friendly Url Provider for Human Reading and Search Engines Indexing
So far so good. The incoming url is deconstructed into segments. Working backwards from the full url (mysite/mypage/mypath/myvalue) the url is tried against the dictionary for a 'hit'. If a page entry in the dictionary is found, great, the url is rewritten and processing continues.
If the dictionary didn't contain the page, then the next segment is removed, thus mysite/mypage/mypath/myvalue is trimmed to mysite/mypage/mypath. This trimming process is repeated until there are not segments left. If nothing was found after all that, the page dictionary is rebuilt one more time, just in case it's a new page, then the process is repeated. If still nothing, then no url rewriting will be done and a 404 will probably occur.What about the 301 Redirects?
Full feature list of this Url Rewriter / Friendly Url Provider
How to install the DNN Friendly Url Provider
Changing Config Entries for Different Options
Complete list of web.config options
Changing IIS Settings for either a custom page extension, or no page extension
Changing IIS Settings to map all requests through the aspnet isapi dll
Update (22 Nov 2007)
Update (10 Jan 2008)
Copyright Bruce Chapman 2007
Comments