﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Crafty Code</title>
    <description>The craft of writing code.  The outcomes from being crafty with code.  Crafty Code is tales from the coding bench.</description>
    <link>http://www.ifinity.com.au/Blog/BlogId/2</link>
    <language>en-US</language>
    <managingEditor>bchapman@ifinity.com.au</managingEditor>
    <webMaster>bchapman@ifinity.com.au</webMaster>
    <pubDate>Fri, 03 Sep 2010 07:30:39 GMT</pubDate>
    <lastBuildDate>Fri, 03 Sep 2010 07:30:39 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 3.5.0.19041</generator>
    <item>
      <title>How to 301 Redirect .asp Urls to DotNetNuke .aspx pages</title>
      <description>&lt;p&gt;One of the most visited entries on this blog is &lt;a title="http://www.ifinity.com.auhttp://www.ifinity.com.au/Blog/EntryId/66/How-To-301-Redirect-htm-or-html-pages-to-DotNetNuke-aspx-pages" href="http://www.ifinity.com.au/Blog/EntryId/66/How-To-301-Redirect-htm-or-html-pages-to-DotNetNuke-aspx-pages"&gt;How to 301 redirect .htm or .html Urls to DotNetNuke pages&lt;/a&gt;.  From that post, I get a lot of enquiries how to do this with .asp Urls.  I have usually just told people to substitute the .htm in the post with .asp, but I’ve decided to dedicate another post just to the task of converting/redirecting ‘Classic’ ASP urls over to a DotNetNuke website.  It would seem a lot of people are replacing old ASP websites with a DotNetNuke based system (a good choice!) so this should be the final word in keeping them pointed in the right direction.&lt;/p&gt;  &lt;p&gt;So without further discussion, let’s get straight into the steps.&lt;/p&gt;  &lt;h3&gt;Step 0 : Backup&lt;/h3&gt;  &lt;p&gt;You’ll be (probably) be making changes to your web.config file, and it’s possible to mess up your entire site with a misplaced punctuation mark.  Take a copy of that file now and thank yourself later.  You can always delete a backup but you can’t conjure one back from the dead.&lt;/p&gt;  &lt;h3&gt;Step 1 : Install Ur l Master Module&lt;/h3&gt;  &lt;p&gt;You’ll need the Url Master module.   Any other way of doing it will be difficult and involve lots of dealing with IIS redirects and messing about.  Download the software from the &lt;a title="Url Master Product Page" href="http://www.ifinity.com.au/Products/Url_Master_DNN_SEO_Urls"&gt;Url Master Product Page&lt;/a&gt;.  If you’re new to this software, then you can &lt;a href="http://www.ifinity.com.au/Licensing"&gt;get a free trial here&lt;/a&gt;.  It costs nothing to install and trial, and if it works (which it will!) then you can purchase later after you’ve solved your problem.  Just obtain the install package, load it into DotNetNuke via the module installer, and move onto step 2.&lt;/p&gt;  &lt;h3&gt;Step 2 : List out all your redirects&lt;/h3&gt;  &lt;p&gt;Chances are you’ve come to this situation either having already converted over your site, and wondered where your traffic went, or you’re in the planning stages of moving over your site, and can’t figure out the best way to transition your search engine rankings.  What you want to do is find out all of the Urls indexed for your existing site and put them into something like a text file or spreadsheet.&lt;/p&gt;  &lt;p&gt;It’s unlikely you’ll be able to guess all of the various Urls so I suggest that you go to search engines and ask them for a list of all the Urls they’ve found on the site.  Nowadays with webmaster consoles you can often download a list of indexed Urls – this is a good way to go.  You can also use the &lt;em&gt;site:www.example.com&lt;/em&gt; search syntax on Google and other search engines like Yahoo and Bing.    This list, when complete, is a list of all the Urls your old site has used.  This is the list of Urls you want to redirect &lt;em&gt;from&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;Next up is the list of Urls you want to redirect to.  This is the list of pages in your DotNetNuke site.   I don’t recommend just sending everything to the home page – you’ll get a much better long term result if you send all the product Urls to your product page, or all your ‘about’ type Urls to your ‘about’ page, and so on.  It doesn’t matter if you have 15 redirects all going to one page, just as long as you have a new home for each of your existing Urls.&lt;/p&gt;  &lt;h3&gt;Step 3 : Map the .asp extension to ASP.NET&lt;/h3&gt;  &lt;p&gt;This is the most important part of the process, and can’t be skipped or worked around.  You have to do it or the whole thing will not work.  In my experience helping people with .html redirects from the original blog post, the number 1,2 and 3 reason why they couldn’t get it to work is because they didn’t setup the correct mapping on their web server.  &lt;/p&gt;  &lt;p&gt;If you’re a little unsure about what this is, let me give you a little background on what Url extensions are all about.  The Url extension works in the same way as a normal file extension, which associates a particular file with a particular program.  This is why when you click on a .xls file, it knows how to load Excel.  &lt;/p&gt;  &lt;p&gt;Similarly, with a web server, using extensions on the Urls allows many different types of program to be installed on the one web server, and the server knows which program to run with which Url by looking at the extension.  Originally web servers were just like file servers that you could access from another place, but they have since grown to run programs (like DotNetNuke) requested from somewhere else.&lt;/p&gt;  &lt;p&gt;By default, DotNetNuke runs with an extension of .aspx.  Thus, any default installation, the .aspx extension will run the ASP.NET application, which will then run DotNetNuke.  The .asp extension was used with 'Classic' ASP (Active Server Pages).  In fact .aspx was used to allow 'old' ASP applications to run alongside 'new' ASP.NET applications.  The .aspx extension was used to denote 'ASP+', which is what ASP.NET was going to be called before someone in marketing had a change of mind.  You couldn't use a + in an extension, so it got rotated to become 'x', hence we have .aspx instead of .asp+.  Incidentally this is where we get C# - it was to be C+++ - until some genius decided to add another + and turn it into a #.  The end result is that .asp is designed to run an entirely different program than .aspx.&lt;/p&gt;  &lt;p&gt;In order to get the .asp Urls to work with ASP.NET, we have to tell IIS (the webserver) to no longer send .asp requests to Classic ASP, but to instead send them to ASP.NET, which is what DotNetNuke runs on.&lt;/p&gt;  &lt;h5&gt;&lt;u&gt;Associating .asp Urls with the ASP.NET runtime&lt;/u&gt;&lt;/h5&gt;  &lt;p&gt;By default, any IIS webserver will be setup to associate .asp with the 'classic' ASP runtime.  In order to get a particular site (or application, depending on your IIS version) to work with .asp, the default configuration will need to be changed.  The instructions vary for IIS version.&lt;/p&gt;  &lt;p&gt;&lt;i&gt;NOTE : Before doing any of these instructions, be sure to take a full backup of at least your web.config file, if not the entire site.&lt;/i&gt;&lt;/p&gt;  &lt;p&gt;IIS6&lt;/p&gt;  &lt;h4&gt;IIS 6.0 - Windows 2003 Server&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;open property page for website / virtual directory. &lt;/li&gt;    &lt;li&gt;click the 'home directory' tab &lt;/li&gt;    &lt;li&gt;click the 'configuration' button, select the 'mappings' tab &lt;/li&gt;    &lt;li&gt;locate the .asp Extension entry &lt;/li&gt;    &lt;li&gt;Click on 'Edit' &lt;/li&gt;    &lt;li&gt;Change the executable value by browsing to the aspnet_isapi.dll (normally at c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll) &lt;/li&gt;    &lt;li&gt;Ensure that 'check that file exists' is &lt;i&gt;unchecked&lt;/i&gt;&lt;/li&gt;    &lt;li&gt;Click OK, OK, OK to close and apply changes &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;IIS7 – Windows Server 2008 (and later)&lt;/h4&gt;  &lt;p&gt;IIS7 is different from IIS6 in that you can make changes to the handler mappings through either the user interface, or through the web.config directly.  In this case the example will be given to make changes to the web.config file, as this is faster and many people on shared hosting don't have access to the administration console.&lt;/p&gt;  &lt;p&gt;You will also need to know whether your site is running on a 64 bit server, or a 32 bit server, though you can just enter both settings and let the server work out which one is correct for it.  Note that for these changes, it's not important if you're using IIS7 Classic or Integrated Pipeline mode.&lt;/p&gt;  &lt;p&gt;To associate the .asp extension, you have to create a new handler entry for *.asp.  This is done by opening up the web.config file and adding this entry at the &lt;b&gt;bottom&lt;/b&gt; of the existing list of entries in the &lt;system.webserver&gt;&lt;handlers&gt; section.&lt;/p&gt;  &lt;p&gt;For a 32 bit server:&lt;/p&gt;  &lt;p&gt;&lt;add name="classic asp" path="*.asp" verb="GET" type="" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" allowPathInfo="false" preCondition="classicMode,runtimeVersionv2.0,bitness32" responseBufferLimit="4194304" /&gt;&lt;/p&gt;  &lt;p&gt;For a 64 bit server:&lt;/p&gt;  &lt;p&gt;&lt;add name="classic asp 64" path="*.asp" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" preCondition="classicMode,runtimeVersionv2.0,bitness64" /&gt;&lt;/p&gt;  &lt;p&gt;Note that if you don't know if you're on 32 bit or 64 bit, you can add both entries – the correct one will be used and the incorrect one will be ignored.&lt;/p&gt;  &lt;h3&gt;Step 4 : Add the redirects into the Url Master module&lt;/h3&gt;  &lt;p&gt;Now that the .asp extension has been mapped to DotNetNuke, any of the redirects requested will be processed by the ASP.NET runtime.&lt;/p&gt;  &lt;p&gt;The final step is to add in the redirects to the Url Master module.  This is done via the Admin-&gt;Portal Urls page.&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/Howto301Redirect.aspUrlstoDotN.aspxpages_C22F/urlmasterasp301redirect.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="url-master-asp-301-redirect" border="0" alt="url-master-asp-301-redirect" src="/Portals/0/images/Howto301Redirect.aspUrlstoDotN.aspxpages_C22F/urlmasterasp301redirect_thumb.jpg" width="935" height="431" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;The above image shows the detail of the page list.  Select the page you want to redirect &lt;em&gt;&lt;strong&gt;to&lt;/strong&gt;&lt;/em&gt;, and click on the ‘Add New Url’ button.  Enter the Url (without domain) into the field, and select the ‘http action’ to ‘301 Perm Redirect’.  Note you need to include the .asp extension.  The Culture is unimportant even if you have a multi-language site because the redirect will go to the default language of the page.  &lt;/p&gt;  &lt;p&gt;Click ‘Apply Changes’ when you are finished.&lt;/p&gt;  &lt;h3&gt;Step 5 : Testing Changes&lt;/h3&gt;  &lt;p&gt;The first place to test is within the ‘Test Url Changes’ section of the Portal Urls page.  Just click on this section, and enter the Url you wish to redirect into this area:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/Howto301Redirect.aspUrlstoDotN.aspxpages_C22F/urlmastercreate301redirectasp.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="url-master-create-301-redirect-asp" border="0" alt="url-master-create-301-redirect-asp" src="/Portals/0/images/Howto301Redirect.aspUrlstoDotN.aspxpages_C22F/urlmastercreate301redirectasp_thumb.jpg" width="717" height="316" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Click on the ‘Show Rewriting result with current settings’ button, and you’ll see results similar to above.&lt;/p&gt;  &lt;p&gt;This shows that the Url will be redirected to the /forum.aspx Url.&lt;/p&gt;  &lt;p&gt;Once this shows the correct result, then try the actual Url with your browser.  You should see the Url change and end up on the expected page.&lt;/p&gt;  &lt;h3&gt;Bonus section : Using an .asp extension page for your site&lt;/h3&gt;  &lt;p&gt;301 Redirects are the published way in which to transition a Url from one form to another, and are recommended for use by the major search engines.   I use them all the time to massage and fiddle with Urls, looking for the best Url for a particular page.&lt;/p&gt;  &lt;p&gt;With that said, plenty of SEO experts maintain that you should avoid changing the Url at all costs, and I’ve no reason to disbelieve this advice.  If you have a high ranking Url for a high value competitive keyword and your business depends on that (or those) Urls, it’s probably a good idea not to rock the boat.  Unless you’re in that category (and by definition, 99% of us won’t be) then I would suggest you change your DotNetNuke site to work with the old Url, rather than forwarding the Url to your DotNetNuke page.&lt;/p&gt;  &lt;p&gt;The process for doing this is exactly the same as the redirect, except you select ‘200 – OK’ as the Http Status of your new Url.  However, if you have a site using .aspx as it’s default extension (see Portal Settings section in the Portal Urls page) then you’ll end up with /forum.asp.aspx.  That’s because the extension is put onto the end of all Urls in the portal.  The solution is to move your site to no-extension Urls.  This will preserve your .asp extension, and will drop the .aspx for all other Urls in the site (301 redirects will handle this change for the other Urls).  You can, of course, choose to switch off the Url extension for the portal, and then go back in and add the extension back for all the Urls.  Or, you can change the portal Url extension to be .asp for all Urls.  &lt;/p&gt;  &lt;h3&gt;Final Thoughts&lt;/h3&gt;  &lt;p&gt;The ability to move from one web platform to another with your site is crucial, yet it gets overlooked by many platforms, or given token tools that only experts can work out, such as a bunch of redirect patterns using Regex patterns.  I’m an expert in Regex and &lt;em&gt;I&lt;/em&gt; find it tedious and difficult to work with them, because it’s so easy to make a mistake.  It’s simply unthinkable that someone without a deep knowledge in this arcane field could even begin to do anything more than copy/paste and hope for the best.   &lt;/p&gt;  &lt;p&gt;The steps posted here should be easily followed by anyone with a website, particularly if they are on IIS7, because they don’t even need the help of whomever looks after their hosting.&lt;/p&gt;  &lt;p&gt;If you’re reading this post but not using DotNetNuke (and therefore Url Master) don’t despair, at least 50% of the steps apply to you.  You’ll just have to write a Http Module which will identify the .asp requests and have some type of process to identify how to send them off to their correct destination.   The simplest case is a large ‘case’ statement, the more complicated involves database tables and lookup values.&lt;/p&gt;  &lt;p&gt;This blog post was written with regards to Url Master 2.01.  Earlier versions of the module work in the same way, and later versions will work in the same way, but some of the screenshots/terminology might be slightly different.  It won’t be hard to work out the difference.&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/96/How-to-301-Redirect-asp-Urls-to-DotNetNuke-aspx-pages</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/96/How-to-301-Redirect-asp-Urls-to-DotNetNuke-aspx-pages#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/96/How-to-301-Redirect-asp-Urls-to-DotNetNuke-aspx-pages</guid>
      <pubDate>Tue, 24 Aug 2010 03:48:55 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=96</trackback:ping>
    </item>
    <item>
      <title>Performance Testing DotNetNuke 5.5 and Url Master</title>
      <description>&lt;p&gt;Recently, Keivan Beigi posted an article on the DNN Blog about how &lt;a href="http://www.dotnetnuke.com/Community/Blogs/tabid/825/EntryId/2703/DotNetNuke-5-5-Takes-The-Performance-Crown.aspx"&gt;DotNetNuke 5.5 was faster than DotNetNuke 4.9.5&lt;/a&gt;.  This post generated a flurry of emails to my inbox wondering whether the new version of Url Master compared to this.   I have already posted about the &lt;a href="http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/88/Comparing-Url-Rewriting-performance-with-DotNetNuke-and-Url-Master-with-no-aspx-extensions"&gt;relative performance of Url Master and the standard DotNetNuke Url Rewriter&lt;/a&gt; which showed that the Url Master module was faster than the standard DotNetNuke Url Rewriter/Friendly Url Provider by a small margin.  In that post, my aim was to determine the difference in speed with no-extensions vs .aspx extensions (conclusion : not significant) – finding out that the standard Friendly Url Provider was slower was an unexpected result.&lt;/p&gt;  &lt;p&gt;So with the release of the faster DNN 5.5 version, at the request of many people, I’ve done some comparison testing on both DNN 5.4, 5.5 with both the standard Url Rewriter/Friendly Url Provider and the latest release of the Url Master module, which is 2.0.1.&lt;/p&gt;  &lt;p&gt;Before we get started, just a quick note to clear up one question that has arisen.  The Url Master module is designed as a complete and total replacement for the standard Url Rewriter / Friendly Url Provider (it’s one piece of code that does both things).  Therefore, when you install the Url Master module and activate it, your site no longer uses the standard provider in any way.   If you are currently using 5.4 (or earlier) with the Url Master module, installing 5.5 won’t yield the performance increase attributed to the upgraded 5.5 provider.  &lt;em&gt;That’s because your site was already running faster anyway&lt;/em&gt;.&lt;/p&gt;  &lt;h2&gt;Performance Testing setup&lt;/h2&gt;  &lt;p&gt;Like my previous testing, I installed a standard DotNetNuke 5.5 installation, and installed the Blog and Forum modules.  The site has about 5 non-admin tabs, plus a blog post and forum thread.  It’s a very lightweight DNN installation, but that’s OK because we are testing relative performance of two modules.  Because it was a 5.5 install, I installed and configured the site to run two separate language packs, and used the new multi-language features of DotNetNuke 5.5.  This actually means that most of the Urls on the standard installation don’t use ‘human friendly’ urls, and instead drop back to the ‘search friendly’ Urls.&lt;/p&gt;  &lt;p&gt;The tests were a collection of 17 normal page requests, and were submitted using the WCAT for Fiddler testing tool, using 10 virtual clients over 30 seconds.  The tests were all done on a single development machine, so there is no network latency involved.  This represents a short burst of high traffic.&lt;/p&gt;  &lt;p&gt;Unlike my prior testing, however, the requests were restricted only to the actual DNN pages – and don’t include any of the css,js, jpg or other files.  In this respect, only the DNN Url Rewriting and page generation (which includes Friendly Url generation) is being tested.&lt;/p&gt;  &lt;p&gt;Four scenarios were tested : one each for DNN 5.4 and 5.5 with the standard provider, while Url Master 1.15 was tested against 5.4 and Url Master 2.01 was tested against DNN 5.5.   The reason for this is to show the improvements in 1.15 –&gt; 2.01.  You can assume that 2.01 with 5.4 would perform nearly identical, because the big improvement in 5.4-&gt;5.5 is from the Friendly Url generation.&lt;/p&gt;  &lt;p&gt;The tests were repeated 6 times for each scenario, which showed remarkably little variance in results.  These include two cases where the IIS server is restarted, and one where the IIS Worker Process is killed forcing a restart (and reload) of the application.&lt;/p&gt;  &lt;h2&gt;Performance Testing Results&lt;/h2&gt;  &lt;h3&gt;Response Time&lt;/h3&gt;  &lt;p&gt;The first category to be examined is the &lt;em&gt;Response time to First Byte.&lt;/em&gt; This tests how fast the Url is rewritten, the page is generated and is streamed back to the server.  The measurement is in milliseconds (1000 milliseconds to a second), and there are two data points – one for average response time, and another for median response time.    The median response time is that time where 50% of the responses are faster, and 50% of the responses are slower.  This eliminates skewing by an abnormally large or small response time, which can have an effect on the average.  The graph is shown below – smaller is better:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/PerformanceTestingDotNetNu.5andUrlMaster_C6FE/performance_testing_respons.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="performance_testing_respons" border="0" alt="performance_testing_respons" src="/Portals/0/images/PerformanceTestingDotNetNu.5andUrlMaster_C6FE/performance_testing_respons_thumb.jpg" width="487" height="295" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;As you can see, there are 4 separate scenarios with the average and median results.&lt;/p&gt;  &lt;h3&gt;Results Analysis – Response Time&lt;/h3&gt;  &lt;p&gt;The first thing to notice is that Keivan’s claims to have doubled the speed from 5.4 to 5.5 certainly agreed with my results.  The response-to-first-byte times have more than halved with this change.    &lt;/p&gt;  &lt;p&gt;The second thing to notice is that Url Master is no longer faster than the standard provider, which is a shame but not entirely unexpected as it does about 3x as much processing in the same function.  In any case, the difference is about 60 milliseconds – 1/5th of the time it takes you to blink an eye.   Most people won’t be able to notice the difference.  The problem is that all the low-hanging optimization fruit in the Url Master code has been picked clean, so incremental performance is harder and harder to extract.&lt;/p&gt;  &lt;p&gt;The last thing I’d like to point out is the improvement between the 1.15 and 2.01 versions of Url Master – while the average speed shows only a 15% increase, the median speed is nearly half.  This is because the 2.x codebase of Url Master uses a much more optimised way of building the internal page index which keeps track of all the Urls in a portal.  With this new optimization, a request where the page index is rebuilt (because of application recycling or a change in the Urls of the portal) completes much faster.  The result is you have fewer slower loads (with 1.15, the occasional request would take 500 ms or more as the page index was rebuilt) which brings the median down lower than the average.  In other words, you’re much less likely to strike the occasional slower-loading page.&lt;/p&gt;  &lt;h3&gt;Requests per Second &lt;/h3&gt;  &lt;p&gt;The next category to be checked is Requests per second.  This is a measure of how fast the web server was able to process the requests.  The absolute values are again unimportant here, it’s the relative differences that we’re interested in.  In this case, a higher value is better because it shows the servers ability to process requests faster.  It’s related to average response times – because the faster the response, the more that can be done per second.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/PerformanceTestingDotNetNu.5andUrlMaster_C6FE/performance_testing_avg_req.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="performance_testing_avg_req" border="0" alt="performance_testing_avg_req" src="/Portals/0/images/PerformanceTestingDotNetNu.5andUrlMaster_C6FE/performance_testing_avg_req_thumb.jpg" width="474" height="295" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Again you can see the results for the 4 separate tests, which shows the 4 different scenarios.&lt;/p&gt;  &lt;h3&gt;Results Analysis – Requests per second&lt;/h3&gt;  &lt;p&gt;DNN 5.5 with the Standard Url Rewriter also shows up as being the fastest solution here.  Again we can see that 5.4 with the Standard Url Rewriter is the slowest, and that Url Master 1.15 –&gt; 2.01 has seen a 15% improvement in performance.   Finally, it’s apparent that the performance optimizations done on the 5.5 Friendly Url Provider / Url Rewriter have yielded a more than 2x improvement over the 5.4 codebase, so the DNN team should feel happy about that.  Hopefully there are more fixes to be found in the general codebase as well.&lt;/p&gt;  &lt;h2&gt;Conclusion&lt;/h2&gt;  &lt;p&gt;So what does this all mean?  Well, it means that if you use the standard Url Rewriter for any 5.x version up to 5.4, you will yield a performance improvement by moving to the 5.5 codebase.  I’d advise caution for critical, live, sites, however, as there are a lot of changes in 5.5 and I’d wait a little while and be prudent to see how it shakes out as a release.&lt;/p&gt;  &lt;p&gt;If you’re using Url Master 1.x, you’ll also see a small improvement going to the 2.01 version, regardless of what version DNN you have.  &lt;a href="http://www.ifinity.com.au/Products/Url_Master_Version_Upgrade"&gt;You can purchase an upgrade here&lt;/a&gt; if you’re still on a 1.x version of Url Master.&lt;/p&gt;  &lt;p&gt;Note that Url Master 2.01 or better is required for DotNetNuke 5.5.   There are significant changes to DNN 5.5, and previous versions of Url Master won’t work.  &lt;em&gt;You should upgrade your Url Master module to 2.01 (or 1.16 if you haven’t upgraded) &lt;strong&gt;before&lt;/strong&gt; upgrading to DNN 5.5&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;With regards to the lead now yielded to the standard provider, it’s going to be difficult to whittle that down with further code optimizations, as it’s already been run through the profiler many, many times.  It’s important to keep it in context though – it’s only a very small margin, and it’s because the Url Master module has so many more features in it.   With DNN 5.5 now including the ability to run a Multi-Language site out-of-the-box, it’s important to remember that the standard Friendly Url Provider now drops back to the old /tabid/xx/default.aspx style Urls, and can’t use Human Friendly Urls at all with the multi-language features.  With Url Master 2.01, you can have not only human-friendly Urls for your Multi-Lingual site, but you can also customise those Urls to suit the specific language.    And I think that’s worth a 60 millisecond penalty.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/92/Multi-Language-Url-Features-of-Url-Master-2-0"&gt;See more on Url Master 2.x Multi-Language features in the original blog post.&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Products/Url_Master/Downloads"&gt;Download the latest version of Url Master, compatible with DotNetNuke 5.5&lt;/a&gt;&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/95/Performance-Testing-DotNetNuke-5-5-and-Url-Master</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/95/Performance-Testing-DotNetNuke-5-5-and-Url-Master#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/95/Performance-Testing-DotNetNuke-5-5-and-Url-Master</guid>
      <pubDate>Fri, 20 Aug 2010 06:49:03 GMT</pubDate>
      <slash:comments>8</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=95</trackback:ping>
    </item>
    <item>
      <title>Url Master 2.0 Released – The next big step forwards for DotNetNuke Urls</title>
      <description>&lt;p&gt;Today is the announcement of a release about 18 months in the making.  I started out with a quick sketch of functionality for a major upgrade of the Url Master module and added some of these points into my issues tracking system back in June 2008, only months after the first release.  A roadmap and prototyping was started in January 2009 and the Version 1.x code was branched in April 2009, the first workable Alpha version was going by January.  But as any developer knows, the 90% complete mark means that 90% of the work is yet to be done.  Finally that is the case and the module is ready for the wider DotNetNuke community, and I think it will make a big impact on what DotNetNuke site owners can expect from the platform with regards to Urls.&lt;/p&gt;  &lt;h2&gt;What’s new in Url Master 2.0&lt;/h2&gt;  &lt;p&gt;The main areas where the 1.x versions could be improved was in these key areas:&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;Portal specific settings&lt;/strong&gt; : most of the settings were specific to an entire DotNetNuke installation and all settings were applied to all portals.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;Multi-Language Urls&lt;/strong&gt; : On a Multi-Language (ML) site, the Urls for the secondary languages all used the same domain name, and all used the same page names.  They also carried the /language/en-US style path parameters as the way of specifying which language to use both in core features (like logon/logoff links) and in content modules (using the myriad of third-party content localization modules).&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;404 Error Handling&lt;/strong&gt; : A large shortcoming of the ASP.NET platform is the use of a 302 redirect to handle the 404 Error page.  I understand the reasons for doing it this way, but in the modern web, working with search engines is very important, and search engines want to know which links are dead and which to index.&lt;/p&gt;  &lt;p&gt;- &lt;strong&gt;User Interface&lt;/strong&gt; : There was no hiding the fact the old interface was more focused on getting as many options into a page as possible and less focused on making those options understandable by the majority of DNN site owners and administrators.  The old interface made little effort to separate out the basic, understandable settings from the complicated (and frightening to the uninitiated) advanced settings.&lt;/p&gt;  &lt;p&gt;-&lt;strong&gt; Performance and Memory Management&lt;/strong&gt; : The Url Master module runs a cached index of DotNetNuke pages.  This new version has improvements to reduce the size of the cache and to reduce the number of lookups used.   Other code refactoring has resulted in detecting much earlier in the logic when to redirect, preventing rewriting from occurring on Urls which are to be redirected anyway.&lt;/p&gt;  &lt;h3&gt;Portal Specific Settings&lt;/h3&gt;  &lt;p&gt;In version 1.x of Url Master, all major settings were shared across all portals in an installation.  This applied to items like the replacing of spaces with hyphens, the choice of page extensions and the choice of using lower case Urls.  For many people this wasn’t an issue because they only ran one portal per installation, while for others, particularly those who host a variety of customer sites in one installation, this meant that there was a loss of flexibility.&lt;/p&gt;  &lt;p&gt;Version 2.0 improves on this situation by allowing for per-portal settings.  It works by specifying a ‘base’ set of settings which apply to all portals.  Any portal in the installation can have a different setting, which will override the base setting, or can be left to use the ‘default’ base settings.  This keeps the flexibility of changing the settings at a base level and working for all portals, but allows individual fine-tuning of portals where necessary.&lt;/p&gt;  &lt;h3&gt;Multi-Language Urls&lt;/h3&gt;  &lt;p&gt;This has already been covered in my blog post &lt;a href="http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/92/Multi-Language-Url-Features-of-Url-Master-2-0"&gt;Multi Language Features of Url Master 2.0&lt;/a&gt;.  To recap, there are now two ways in which you can define language specific Urls in the Url Master module – by domain and by page (or both).&lt;/p&gt;  &lt;h4&gt;By Domain&lt;/h4&gt;  &lt;p&gt;Essentially this means that you can associate a domain [in this case, equivalent to a portal alias] with a specific language.  This might be a subdomain (fr.example.com) or it might be a different top-level domain (example.fr).  It can even be a top-level path imitating a child portal(example.com/fr).  When this is done, every single Url generated by DotNetNuke with language/fr-FR in it will have the /language/fr-FR path removed and the domain name returned as the chosen domain name.   &lt;/p&gt;  &lt;p&gt;In addition to this, any old Urls for the site (example.com/pagename/tabid/xx/language/fr-FR/default.aspx) will be automatically redirected to the new Url (example.fr/page-name). &lt;/p&gt;  &lt;p&gt;This means you can transform the language-specific Urls for your site and run a well-separated multi-language strategy.  Google Webmaster guidelines recommend using a specific domain name or top-level path with localized content, as it assists with Google recognising language-specific sites and ranking them well for the associated language.&lt;/p&gt;  &lt;h4&gt;By Url&lt;/h4&gt;  &lt;p&gt;Setting a language by Url means creating a custom Url for each language on a page.  By default, all page languages use the same page name as created in (presumably) the default language.  This is then used with the language/xx-YY modifier to deliver different language content for the page – both in core skin objects (login, terms, etc) and with content-localization modules which present different content based on different culture codes.&lt;/p&gt;  &lt;p&gt;This means, for a hypothetical French language page, you’d see example.com/products/tabid/xx/language/fr-FR/default.aspx.  Without a customised Url for the page, Url Master will automatically reduce this to example.com/language/fr-FR/products.aspx.   With a custom language-specific Url, you’ll get example.com/produits.aspx.  This Url will automatically rewrite the Url to include the &amp;language=fr-FR behind the scenes, so all content localization will still work in the same way.  You can also combine the custom page urls with the language-specific domain names, so you can end up with fr.example.com/produits.aspx.   This is the best-case ML SEO solution, because it (1) signals to search engines that the content is localized to the fr-FR culture, and is more likely to match the Url to a keyword a French-speaking person would search for (produits).&lt;/p&gt;  &lt;h3&gt;404 Error Handling&lt;/h3&gt;  &lt;p&gt;For the uninitiated, a 404 error relates to the Http status code returned by a website when a requested Url doesn’t match any content on the server.  The term ‘404’ has entered common usage as a shortcut for referring to a ‘page not found’ situation.&lt;/p&gt;  &lt;p&gt;By default, standard DotNetNuke doesn’t really handle 404 Errors at all.  You’ll either get the default 404 error page (which is optimised to answer the most common installation issues) or you’ll get an ASP.NET 404 Error when you request an invalid page.   If you set up a ASP.NET 404 error handler, you end up with the strange situation where a page not found is redirected to a found page, which says ‘page not found’.   As far as visitors are concerned, this is OK.  As far as search engines are concerned, it’s not good because they rely on the http status codes, and can’t tell the difference between a valid redirect and one that is the result of an invalid Url being followed.  People make mistakes linking to your site all the time, and these generate a lot of 404 errors for an established site.  &lt;/p&gt;  &lt;p&gt;Google has recently started handling this ‘not-really-a-404-error’ problem itself, and now has the concept of ‘soft’ 404 errors in Google Webmaster console.  This means you can get a page on your site incorrectly identified by some type of Google code as a ‘soft 404’ – which means that Google thinks it’s an error page and takes it out of the index.  This recently happened to one of my more important old blog posts, which was happily bringing in a lot of visitors for long-tail searches, but Google decided it was actually an error page (nothing of the sort) and removed it from the index.&lt;/p&gt;  &lt;p&gt;The result of all of this is that you need a ‘real’ 404 error handler.  And that’s what is in Url Master 2.0 : you can choose to use your current setup, or you can specify a Url on your site [example: a 404.htm page you have written] or you can create a DNN page and specify that as your 404 page.  By doing this, any 404 error on your site will result in the specified page/Url being shown, but crucially, &lt;em&gt;it will return a 404 http status code &lt;/em&gt;and thus search engines (a) know it is an error and (b) stop making guesses as to which pages on your site might be error pages.&lt;/p&gt;  &lt;p&gt;In addition to 404 Error Handling, the new version also includes a 404 error log.  This log shows a list of all the Urls which have resulted in a 404 error page being shown.  By reviewing this list you can detect commonly requested Urls and either create a redirect to somewhere correct, or find out where the visitors are coming from and get the link fixed.&lt;/p&gt;  &lt;p&gt;You can read more about the 404 Error Handling in the blog post : &lt;a href="http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/90/Real-404-Error-Handling-in-DotNetNuke"&gt;Real 404 Error Handling for SEO in DotNetNuke&lt;/a&gt;&lt;/p&gt;  &lt;h3&gt;User Interface&lt;/h3&gt;  &lt;p&gt;It’s an awfully clinical phrase : ‘User Interface’.  No doubt coined by computer scientists a long time ago, and I’ve been using it by training and habit for the last 20 years or so – and so unlikely to stop anytime soon.  In reality it’s the visible parts of the program, the way that real people interact and control the functions.    The first iteration of the module was done with the emphasis on getting the ‘oily bits’ of the program to work correctly – very little time was devoted to making it pretty to look at or intuitive to use.   This next iteration has resulted in a large amount of time spent on making the interface usable.  There’s a fresher design, AJAX functionality in tasks like lookups and the test functions, client-side script for other items.  The interface is faster to use, and is logically grouped into areas allowing first-time users to get to grips with the basics and not be overwhelmed, but allowing experienced hands the ability to endlessly tune configuration to get the best results.&lt;/p&gt;  &lt;p&gt;I thought about posting some examples of the interface here – but instead decided to let people’s curiosity drive them to the download button!&lt;/p&gt;  &lt;h3&gt;Performance and Memory Management&lt;/h3&gt;  &lt;p&gt;The Url Rewriting and Friendly Url generating solution for any site is one of the most heavily used parts of the code, as it literally runs all the time and is used many times in each request.  The original version always performed as well as the standard DotNetNuke Url Rewriting, and this was down to the care taken when building the core of the module to work within the constraints of the platform and to consider throughput as the first priority.  This new version takes up where that left off, and introduces important new changes, including per-portal memory caching.  In version 1.x, when the first request came in for one portal, all portals Urls were then loaded into the memory cache.  This left the site ready to handle requests for any and all of the portals, but in larger installations slightly penalised that first request.  This new version optimises this further by only loading the page index on a portal-by-portal basis.  It’s actually quite common to have one portal dominating all the traffic for a DNN installation, so with this change, a dominant portal will not get slowed down by its less-used installation siblings.    &lt;/p&gt;  &lt;p&gt;Another improvement in this front is the loading of Urls for portal alias entries that are used.  One of the key improvements in this version is the much stronger ability to detect and redirect away from Urls which use a portal alias not designated as the ‘chosen’ portal alias for the portal.  It’s very common to have example.com and www.example.com for a portal – the old version would cache all the urls for each, meaning the cache size was [num of portal alias entries x number of tabs] for each portal.  Now this is [num of chosen portal alias entries x number of tabs] – in the most common case, the administrator chooses www or non-www – this immediately reduces by half the amount of memory taken up by the page index.  It’s not a huge difference but all these small enhancements add up to a better and faster product.&lt;/p&gt;  &lt;h3&gt;Other Fixes and Enhancements&lt;/h3&gt;  &lt;p&gt;There are plenty of other fixes and enhancements in the module – a small example is the dropping of the requirement to enter both the www and non-www version of the portal alias.  The module will now work with one or the other, and will automatically redirect to the one that is entered in the portal alias table.   The Test Url Rewriting and Test Friendly Url Generation pages are now located on the same page, so you can quickly test generation of Friendly Urls and immediately check the Url Rewriting results without scrolling around and copy/pasting bits of Url everywhere.  In the middle of all this is the usual fixing of small bugs found by the active and vocal community of people who use this module for their live websites.&lt;/p&gt;  &lt;p&gt;And remember – all the other existing features are still there : better friendly urls, automatic redirects, user profile Urls, custom redirects and much, much more.&lt;/p&gt;  &lt;h2&gt;It’s ready – go and get it!&lt;/h2&gt;  &lt;p&gt;After that long build up – the module is ready and released to the wider community.  You can download it for a free trial from the &lt;a title="Url Master Product Page" href="http://www.ifinity.com.au/Products/Url_Master_DNN_SEO_Urls"&gt;Url Master Product Page&lt;/a&gt; – even that has had a makeover as part of the release.  It’s compatible with all DotNetNuke versions after 4.6, including all the 5.x versions.&lt;/p&gt;  &lt;h3&gt;Upgrading from Url Master 1.x&lt;/h3&gt;  &lt;p&gt;As 1.x versions have been out for over two years, there are a lot of people around with this module installed in their site and relying on it from a day-to-day basis.   The upgrade path is very simple : you just install the new version and it completely upgrades the old version, carrying across all the old settings and configuration.  About the only thing you need to do is to remember to press Ctl+F5 to refresh the stylesheets so you get all the new interface details.&lt;/p&gt;  &lt;p&gt;However, it is a paid upgrade from any 1.x version to 2.0.  Unless you purchased your copy since June 22, 2010, you will need to &lt;a href="http://www.ifinity.com.au/Products/Url_Master_Version_Upgrade"&gt;purchase a module upgrade&lt;/a&gt; and &lt;a href="http://www.ifinity.com.au/Licensing"&gt;request a new licence Keyfile&lt;/a&gt;.  The cost of upgrading your existing Url Master 1.x version to Url Master 2.0 is $30.  &lt;/p&gt;  &lt;p&gt;I don’t recommend upgrading your installation until you have purchased an upgrade and received your updated licence keyfile (which has a product version of 2.0 in it).  If you upgrade your install first, you’ll have an unlicensed copy until you receive your keyfile.  It’s all automated delivery now, but things can get delayed and I would hate to have customers disappointed.&lt;/p&gt;  &lt;p&gt;If you purchased a copy since June 22, 2010, you should have already received a Url Master 2.0 licence keyfile.  You can easily check this by looking in the licence keyfile, it should have a licence version of 1.4 and a product version of 2.0.  If so, you can just upgrade your install by downloading the new version and uploading via the DNN Module installer.&lt;/p&gt;  &lt;h2&gt;Comments, Questions, Feature requests for Version 3.0?&lt;/h2&gt;  &lt;p&gt;This new version of the module is the result of a lot of feedback, discussions and requests from committed customers who help to make this product great.  I’m hoping that the module will prove to be a real step forwards in the arena of DotNetNuke Url generation and rewriting.  If you’ve got any comments, questions, feedback, or just want to get started on the feature requests for the next version, please pile in via the comments.&lt;/p&gt;  &lt;p&gt;For bug reports and specific problems, please post in the &lt;a href="http://www.ifinity.com.au/Products/Support_Forums/forumid/8/scope/threads"&gt;support forum&lt;/a&gt;.  You’ll get a specific answer in the forum.&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/94/Url-Master-2-0-Released-ndash-The-next-big-step-forwards-for-DotNetNuke-Urls</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/94/Url-Master-2-0-Released-ndash-The-next-big-step-forwards-for-DotNetNuke-Urls#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/94/Url-Master-2-0-Released-ndash-The-next-big-step-forwards-for-DotNetNuke-Urls</guid>
      <pubDate>Wed, 07 Jul 2010 10:48:00 GMT</pubDate>
      <slash:comments>12</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=94</trackback:ping>
    </item>
    <item>
      <title>Updated Google Analytics Provider for DotNetNuke</title>
      <description>&lt;p&gt;My last update of the iFinity Google Analytics provider was back in December 2007 – and a lot has changed since then.  Probably the biggest change is the inclusion of a standard Analytics provider in the DotNetNuke core.  That doesn’t seem to have dented enthusiasm for the iFinity Google Analytics provider, with nearly 6,000 downloads since it’s original release and still running at a healthy rate of about 7 downloads per day.&lt;/p&gt;  &lt;p&gt;With my work on &lt;a href="http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/92/Multi-Language-Url-Features-of-Url-Master-2-0"&gt;Multi-Language Urls for DotNetNuke with the Url Master module&lt;/a&gt;, I have setup the &lt;a href="http://url-master.com/"&gt;Url Master demonstration site&lt;/a&gt; which shows how to setup language-specific sub-domains to tidy up and optimise the Urls on a DotNetNuke site.  Here’s the sub-domains created for the site:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;fr.url-master.com – French language version&lt;/li&gt;    &lt;li&gt;nl.url-master.com – Dutch language version&lt;/li&gt;    &lt;li&gt;de.url-master.com – German language version&lt;/li&gt;    &lt;li&gt;es.url-master.com – Spanish language version&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;What has this got to do with Analytics?  Very simple, actually.  With a range of subdomains in the one DotNetNuke portal, the trusty old 1.01 version of the iFinity Google Analytics provider was no longer performing as needed, because it regards the subdomains as separate domains, and will not track the traffic as a ‘whole’.  For some people, this will be the option they prefer, however, for me, I wished to view the data for the entire site, and to have all the sub-domain traffic merged into one set of reports.&lt;/p&gt;  &lt;h2&gt;Tracking across Sub-domains&lt;/h2&gt;  &lt;p&gt;Google Analytics covers this scenario (wishing to track all sub-domains in one profile), all I had to do was to include the ‘trackDomain’ call into the Analytics script.  This was pretty easy to add : a new option called ‘Track Domain’ which feeds through to the generated script.&lt;/p&gt;  &lt;p&gt;But once I had the project open and was building a new release, I decided to go through and bring the entire module up to date, and work through the long list of requests that had come in since the last release.&lt;/p&gt;  &lt;h2&gt;Asynchronous Tracking&lt;/h2&gt;  &lt;p&gt;One of the big changes in Google Analytics has been the introduction of Asynchronous Tracking.  Without drilling down to the depths of explanation, in the ‘old’ [ga.js] tracking script, the Page View was recorded once all the page had loaded, and the Analytics script had run.&lt;/p&gt;  &lt;p&gt;Asynchronous in this respect is a bit similar to the ‘A’ in AJAX (which is Asynchronous Javascript and XML) – the script loads, and then records a page view &lt;em&gt;asynchronously&lt;/em&gt;, which basically means it does it without slowing down all the other script on your page.&lt;/p&gt;  &lt;p&gt;Google have made it pretty clear this is the direction they are headed with Analytics, so, with the new version of the iFinity Google Analytics module, you have the option of ticking a box and choosing Asynchronous tracking, which will generate the correct script for you behind the scenes.  You don’t have to do anything else other than checking the box.&lt;/p&gt;  &lt;h2&gt;Removing Deprecated Code&lt;/h2&gt;  &lt;p&gt;Google is continually upgrading the Analytics script to keep up with it’s customers requirements.  To this end, they sometimes deprecate (remove support for) some of the functions, and replace them with newer, better versions. The new version of the Analytics module has removed all of the old deprecated functions and replaced them with new versions.&lt;/p&gt;  &lt;h2&gt;Automatic Container Hiding&lt;/h2&gt;  &lt;p&gt;One of the lessons I learnt while building the &lt;a href="http://www.ifinity.com.au/Products/Canonical_Linker_for_DNN"&gt;Canonical Linker module&lt;/a&gt; was how to hide a module container unless an administrator needed to see it.  This technique has now been applied to the iFinity Google Analytics module, so you no longer have to go into the module settings and check the ‘hide container’ option.  The module detects when the site is in ‘edit’ mode, and will show itself on the page, so that settings can be modified.  When in ‘view’ mode, the module does not appear on the page.  &lt;/p&gt;  &lt;p&gt;Note : the placement of the module in the skin does not affect where the script is inserted.  The script is inserted into the output DNN page in the correct location independently of where in the page skin the module is loaded.  This was a common misconception with the previous version – you don’t need to move the module to the bottom of the page in order to get the script further down.&lt;/p&gt;  &lt;h2&gt;No more CSS files&lt;/h2&gt;  &lt;p&gt;One of the faults of the prior version was that it had a module.css file – the DNN framework automatically detects this file and sends it to the browser, even if it is not needed.  The module.css file just contained a few classes to define how the module settings should be displayed and was not required.  Yet, every page that had the Google Analytics module installed ended up sending a /desktopmodules/ifinity.googleanalytics/module.css file down to the browser, taking up precious connections, downloads and speed.  This often shows up in YSlow reports, and it’s something that has been requested a few times.&lt;/p&gt;  &lt;p&gt;With the new version, the module.css file is no longer used, and using the module will not create a reference to this file.  &lt;/p&gt;  &lt;p&gt;Note : If you are on DNN 4.x and upgrade to the Google Analytics 2.0 module, you will have to manually delete the module.css file after upgrading.  This is because of the lack of support for a cleanup routine.  If you are on DotNetNuke 5.x, the old module.css file should be deleted for you once the module is upgraded.  If you have upgraded to the new version of the module, and you are still seeing the Analytics module.css file being downloaded for your site, just go in and delete the module.css file.  It will do no harm at all.&lt;/p&gt;  &lt;h2&gt;Same Great Features&lt;/h2&gt;  &lt;p&gt;While this new functionality was being added, all the old functionality has been kept.  This includes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Ability to exclude traffic for specified user group, for example: Administrators &lt;/li&gt;    &lt;li&gt;Ability to track Registered users as a custom segment &lt;/li&gt;    &lt;li&gt;Ability to track external link clicks in Analytics reports&lt;/li&gt;    &lt;li&gt;Exclude calls to Analytics when running in development/test environments.  This helps when you wish to view how the script behaves without actually calling the Google servers&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;And, despite the temptation to convert thousands of downloads into dollars, it remains the same great price : free!&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Products/Google_Analytics_Script_Module"&gt;Download your copy from the iFinity Google Analytics Product page&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If you have any comments, please leave in the comments field below.  For product support and questions, please use the &lt;a href="http://www.ifinity.com.au/Products/Support_Forums/forumid/4/scope/threads"&gt;iFinity Google Analytics product support forum&lt;/a&gt;.    &lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/93/Updated-Google-Analytics-Provider-for-DotNetNuke</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/93/Updated-Google-Analytics-Provider-for-DotNetNuke#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/93/Updated-Google-Analytics-Provider-for-DotNetNuke</guid>
      <pubDate>Tue, 29 Jun 2010 00:27:50 GMT</pubDate>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=93</trackback:ping>
    </item>
    <item>
      <title>Multi Language Url Features of Url Master 2.0</title>
      <description>&lt;p&gt;This is the second post in my series illustrating functionality which will be available with the release of the Url Master, version 2.0.&lt;/p&gt;  &lt;p&gt;The previous post covered the new &lt;a href="http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/90/Real-404-Error-Handling-in-DotNetNuke" target="_blank"&gt;404 Error Handling&lt;/a&gt; features, this post will discuss the new Multi-Language (ML) features that the module incorporates.&lt;/p&gt;  &lt;p&gt;Like better 404 error handling, people using the Url Master module soon started to request support of multi-language Urls.  While Url Master 1.x versions did work perfectly well with ML sites, and shuffled the /language/xx-YY Url forwards in the path, so that it at least appeared to have a path structure related to the language, this was about all that could be achieved.&lt;/p&gt;  &lt;p&gt;The first thing that was needed was the ability to localize Urls for a specific language, and to get the Urls to work without the /language/xx-YY stuck in the middle of the Url.&lt;/p&gt;  &lt;p&gt;The next thing was to work out the best SEO strategy for handling different language versions of the same content.&lt;/p&gt;  &lt;p&gt;After a lot of research about ML sites and SEO in particular, I came to the conclusion that there are three main streams of thought:&lt;/p&gt;  &lt;p&gt;1)  Register separate domains names for each country / language.  i.e. example.com, example.fr, example.de.  Note this doesn’t help with multi-language countries like Switzerland or Canada.&lt;/p&gt;  &lt;p&gt;2) Use subdomains to differentiate language versions of the same site. i.e. example.com, fr.example.com, de.example.com.  This only needs a single domain name and clearly separates out the sites as separate entities within search engines.&lt;/p&gt;  &lt;p&gt;3) Use path separators to differentiate language versions : i.e. example.com, example.com/fr,  example.com/de.  This has the benefit of keeping the same domain name, and passing on link value to all the various language-sections of the site.&lt;/p&gt;  &lt;p&gt;[Note : &lt;a href="http://www.ifinity.com.au/Products/Url_Master_2.0_Beta"&gt;Url Master 2.0 is currently in Beta Testing&lt;/a&gt;, and is not yet available for public release. This information is posted to alert readers of upcoming functionality which will be available soon.]&lt;/p&gt;  &lt;p&gt;Update : This &lt;a href="http://www.google.com/support/webmasters/bin/answer.py?&amp;answer=182192#3"&gt;Google Webmaster Central article covers Multi-Language sites&lt;/a&gt;.  As part of their advice, they recommend:&lt;/p&gt;  &lt;blockquote&gt;   &lt;h5&gt;&lt;strong&gt;Make sure the page language is obvious&lt;/strong&gt;&lt;/h5&gt;    &lt;p&gt;Google uses only the visible content of your page to determine its language. We don’t use any code-level language information such as &lt;code&gt;lang&lt;/code&gt; attributes.&lt;/p&gt;    &lt;h5&gt;&lt;strong&gt;Carefully consider your choice of URL&lt;/strong&gt;&lt;/h5&gt;    &lt;p&gt;Google uses the content of the page to determine its language, but the URL itself provides human users with useful clues about the page’s content. For example, the following .ca URLs use &lt;code&gt;fr&lt;/code&gt; as a subdomain or subdirectory to clearly indicate French content: http://example.ca/fr/vélo-de-montagne.html http://fr.example.ca/vélo-de-montagne.html &lt;/p&gt;    &lt;p&gt;Signaling the language in the URL may also help you to discover issues with multilingual content on your site.&lt;/p&gt;    &lt;p&gt;It’s fine to translate words in the URL, or to use an &lt;a href="http://en.wikipedia.org/wiki/Internationalized_domain_name"&gt;Internationalized Domain Name (IDN)&lt;/a&gt;. Make sure to use UTF-8 encoding in the URL (in fact, we recommend using UTF-8 wherever possible) and remember to escape the URLs properly when linking to them.&lt;/p&gt; &lt;/blockquote&gt;  &lt;h3&gt;The DotNetNuke Multi-Language Domain Problem&lt;/h3&gt;  &lt;p&gt;All of these solutions require multiple &lt;em&gt;portal alias &lt;/em&gt;entries for a DotNetNuke site.  The portal alias is roughly equivalent to a domain name, but can also include subdomains, and domains with paths in them, as in child portals.  So example.com, fr.example.com and www.example.com/fr are all examples of portal aliases.  &lt;/p&gt;  &lt;p&gt;The problem with standard DotNetNuke is that, everytime you add a portal alias, you effectively create a duplicate of that site under that domain name.  When you add the variable of a language to that, you can quickly end up with many different versions of a site.  Just two domains with two languages will give you 4 different versions of a site, because there is no mechanism to tie a language to a portal alias.&lt;/p&gt;  &lt;h3&gt;The Url Master Domain-Language Solution&lt;/h3&gt;  &lt;p&gt;Rather than try and pick a strategy to support, the Url Master module now supports all three strategies for handling domain names with ML sites.   Once you have chosen the style of portal alias to identify your different language versions of the site, you can then associate specific portal alias entries [or domain names if you prefer] to specific languages.  This is done through the following point-and-click interface within the Url Master module:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/MultiLanguageUrlFeaturesofUrlMaster2.0_12831/portalaliasbylanguage.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="portal-alias-by-language" border="0" alt="portal-alias-by-language" src="/Portals/0/images/MultiLanguageUrlFeaturesofUrlMaster2.0_12831/portalaliasbylanguage_thumb.jpg" width="702" height="429" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;[Note : this example comes from the new &lt;a href="http://url-master.com/" target="_blank"&gt;Url Master demo site&lt;/a&gt;, which will be discussed further in this post]&lt;/p&gt;  &lt;p&gt;As you can see, once you add the list of portal alias entries to your portal, you can then just select which language belongs to which portal alias.  The rest is taken care of for you, including these factors:    &lt;br /&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;If you enter a mismatch between language modifier and domain name, it will be redirected to the correct domain name. For example, url-master.com/language/de-DE/home.aspx will redirect to de.url-master.com &lt;/li&gt;    &lt;li&gt;Any generated Urls with the /language/xx-YY in them (in reality, all ML urls generated by DNN) will automatically have the /language/xx-YY removed from them, and the associated portal alias replaced instead.  There are no modifications needed to modules in order to use this feature &lt;/li&gt;    &lt;li&gt;When you have two entries for one language (url-master.com and www.url-master.com for en-US) then the second entry will be 301 redirected to the first. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This applies to any list of unique portal alias entries, whether they are separate domains, different subdomains, or just paths created under a single domain (ie url-master.com/nl)&lt;/p&gt;  &lt;p&gt;The page urls for each page in the ML sites just follows whatever the page name is.  So, a page called ‘Products’ within the site will be the same for each portal alias, because the portal alias path makes the Url unique, and the Url Master module can work out which language is meant by which portal alias.&lt;/p&gt;  &lt;h3&gt;The Url Master Page Url-Language Solution&lt;/h3&gt;  &lt;p&gt;While providing a clean way to separate ML sites in a single portal was one half of the problem solved, the other half is localizing the actual Url of the page.   Having an incorrect language term for the Url makes the translation look incomplete, and doesn’t help when optimising the Url for the page in the local language.&lt;/p&gt;  &lt;p&gt;For example, we might have /products as the Url for a hypothetical products page on an English-language site.  In a French language site, you would expect this to be /produits.  This is both to be pleasing for the French-language readers of the site, and also to help optimise the page for French-language search engines.&lt;/p&gt;  &lt;p&gt;The solution to this problem is to allow a particular Page Url to be associated with a specific language, in a similar way to how the portal alias is associated.  This screen grab shows how this works on the Url Master module demo site:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/MultiLanguageUrlFeaturesofUrlMaster2.0_12831/pageurlbylanguage.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="page-url-by-language" border="0" alt="page-url-by-language" src="/Portals/0/images/MultiLanguageUrlFeaturesofUrlMaster2.0_12831/pageurlbylanguage_thumb.jpg" width="912" height="578" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Anyone familiar with the 1.x versions of the Url Master module will recognise the general format of the page, but note the addition of the ‘Culture’ field.  Culture is used to specify a country/language pair, because some languages are spoken and spelled differently in different parts of the world.&lt;/p&gt;  &lt;p&gt;In the above image, you’ll note there has been three custom Urls added for the page, and each has been set to ‘200 – OK’ [in this example, the ‘automatic 301 redirect’ option is switched on].   This allows the entry of language-specific versions of Urls, one unique language for each configured culture in the DotNetNuke install.  Note that here, the German [Deutsch] Url has not been modified – the ‘200 – OK’ option is greyed out because it is not a custom Url.  However, it still does not show the /language/de-DE path because of the unique de.url-master.com domain name.&lt;/p&gt;  &lt;p&gt;Please note I can only speak one language and have relied on machine translation to get these Urls, so let me know if they’re wrong.&lt;/p&gt;  &lt;p&gt;At this point, it’s important to mention that the language/culture specific Urls for pages is not dependent on having language-specific domain names.  You can just use the language-specific page Urls, or just the language-specific domains, or both combined as shown in this image.&lt;/p&gt;  &lt;h2&gt;The Url Master Module Demonstration Site&lt;/h2&gt;  &lt;p&gt;Actions speak louder than words, so I have used the Url Master 2.0 module, DotNetNuke 5.4.2 and the EALO Codeplex module to build a multi-language site to demonstrate the module.  &lt;/p&gt;  &lt;p&gt;Here are the links:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://url-master.com" target="_blank"&gt;English Version&lt;/a&gt; – &lt;a href="http://fr.url-master.com" target="_blank"&gt;French Version&lt;/a&gt; – &lt;a href="http://es.url-master.com" target="_blank"&gt;Spanish Version&lt;/a&gt; – &lt;a href="http://de.url-master.com" target="_blank"&gt;German Version&lt;/a&gt; – &lt;a href="http://nl.url-master.com/" target="_blank"&gt;Netherlands Version&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Apologies to native speakers of those languages, because all the translations are machine based.  However, the site is meant to display how the Urls for a ML DotNetNuke site will appear.  You can switch between the different languages with a single click, and note that they will always show the correct localized content versions.   You can also see how each page has been localized via the Url, to give better keyword matching in native-language country-specific versions of search engines.&lt;/p&gt;  &lt;p&gt;The site uses the options of removing the page extensions and replacing the spaces in the Urls with hyphens.&lt;/p&gt;  &lt;p&gt;You can also see the 404 handling discussed in the previous post by following an incorrect link like this one : &lt;a href="http://url-master.com/deadlink.aspx"&gt;http://url-master.com/deadlink.aspx&lt;/a&gt; – even the 404 page is localized, as you can see from this link : &lt;a href="http://de.url-master.com/deadlink.aspx"&gt;http://de.url-master.com/deadlink.aspx&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Feel free to navigate around the Url Master demo site and get a feel for how a ML DotNetNuke site can be put together.&lt;/p&gt;  &lt;h3&gt;Can’t Wait?  Then don’t!&lt;/h3&gt;  &lt;p&gt;The Url Master version 2.0 will come as a paid upgrade to people with a version 1.x licence, and there will be a price increase over the 1.x version.  The pricing is not yet finalised and will be announced with the module release.  However, any purchase made after 21st June 2010 for Url Master 1.15 will receive a free upgrade to Version 2.0 when it is released in the next couple of weeks.  This represents an &lt;a href="http://www.ifinity.com.au/Products/Purchase/Url_Master"&gt;opportunity to purchase&lt;/a&gt; the next version at today’s prices.  This offer will only last until the release, so if you’re thinking of buying, now is the time to do so.&lt;/p&gt;  &lt;h3&gt;Other tidbits….&lt;/h3&gt;  &lt;p&gt;The version 2.0 module will be compatible with DNN versions from 4.6 upwards.  It’s even been tested against DNN 5.4.4 which isn’t quite out yet.  You will, however, need to supply your own content localization solutions – this is just a Url Rewriting solution to provide friendly Urls and redirections.  You’ll need Html modules, ML menu systems and other items.&lt;/p&gt;  &lt;h2&gt;Wrapping Up&lt;/h2&gt;  &lt;p&gt;These language features have been a &lt;em&gt;very&lt;/em&gt; long time in the works but with the maturation of DotNetNuke 5 with more Multi-Language features the time is right for people running Multi-Language DotNetNuke installations to have a full Url solution.  I have collected a lot of feedback on the needs of ML site administrators, and hopefully this solution will cover all of their needs.&lt;/p&gt;  &lt;p&gt;If you have  questions or feedback about these changes I’m very happy to hear via the comments below.  But stick to English please!&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/92/Multi-Language-Url-Features-of-Url-Master-2-0</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/92/Multi-Language-Url-Features-of-Url-Master-2-0#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/92/Multi-Language-Url-Features-of-Url-Master-2-0</guid>
      <pubDate>Fri, 25 Jun 2010 11:04:03 GMT</pubDate>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=92</trackback:ping>
    </item>
    <item>
      <title>Using Friendly Urls in internal site links instead of LinkClick</title>
      <description>&lt;p&gt;One of the features of early DotNetNuke was the ability to track clicks of particular links within the site.  You could work out how many people clicked on a link on a certain page.&lt;/p&gt;  &lt;p&gt;This is one of those features which is actually of limited use these days – a good web analytics package will give you that detail, and a whole lot more.  There wasn’t even a link click report you could look at to see the result – &lt;a href="http://www.ifinity.com.au/Blog/EntryId/31/Free-extra-reports-for-DotNetNuke-Get-Link-Clicks-statistics-Detailed-User-visits-and-more" target="_blank"&gt;though I have written one of these you can use&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;However, the ‘LinkClick’ approach still litters the DotNetNuke framework and can get ordinary people into difficulty with their SEO efforts.&lt;/p&gt;  &lt;h2&gt;The problems with the LinkClick handler&lt;/h2&gt;  &lt;p&gt;The LinkClick handler is a generic Url which looks like http://example.com/linkclick.aspx?tabid=234&amp;moduleid=355.  It can be thought of as a generic redirector, like Microsoft used to use for everything a few years back (it was go.microsoft.com or something like that).  There’s several issues with this:&lt;/p&gt;  &lt;p&gt;1) it uses a 302 redirect to get you to your content, instead of just a direct link&lt;/p&gt;  &lt;p&gt;2) it’s doubtful whether any link value is passed onto the destination page&lt;/p&gt;  &lt;p&gt;3) these days with human friendly Urls not containing any ‘tabid’ information, the links are actually quite brittle and easily broken when people move and rename pages.&lt;/p&gt;  &lt;p&gt;The LinkClick handler is actually a multi-faceted tool : it is also used to serve up downloadable files (like zip packages and pdf documents) as well as being used to serve up secure files.  To be clear I am discussing the use of the LinkClick handler to redirect users to specific DNN pages, not downloadable files.&lt;/p&gt;  &lt;p&gt;The SEO drawbacks for using the linkclick handler are both the lack of contextual keywords in the Url, and the use of a 302 redirect, which is not always followed correctly by search engines, as opposed to a straight hyperlink which search engines know exactly what to do with.&lt;/p&gt;  &lt;h3&gt;Using the LinkClick Handler without realising&lt;/h3&gt;  &lt;p&gt;Most people don’t even know they are creating ‘LinkClick’ Urls.  It usually happens when they use the DotNetNuke ‘Link’ control somewhere in a module.  For an example, I’m going to show the announcements module.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/UsingFriendlyUrlsininternalsitelinksinst_EE1A/announcementdemo1.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="announcement-demo-1" border="0" alt="announcement-demo-1" src="/Portals/0/images/UsingFriendlyUrlsininternalsitelinksinst_EE1A/announcementdemo1_thumb.jpg" width="557" height="112" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;An announcement in the announcements module consists of a title, description and link.  The title is a plain-text field (although you can be sneaky and enter your own html).  The link for the announcement appears as the ‘read more…’ hyperlink.&lt;/p&gt;  &lt;p&gt;The ‘read more’ link comes from the ‘link’ field in the Announcement, which looks like this:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/UsingFriendlyUrlsininternalsitelinksinst_EE1A/announcementdemo2.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="announcement-demo-2" border="0" alt="announcement-demo-2" src="/Portals/0/images/UsingFriendlyUrlsininternalsitelinksinst_EE1A/announcementdemo2_thumb.jpg" width="573" height="276" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;This is the generic DNN Link control – and it appears in many different locations.  The selection of the ‘Link Type’ option drives what the actual link will look like.&lt;/p&gt;  &lt;p&gt;Here’s the list:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;None – no link (obviously!)&lt;/li&gt;    &lt;li&gt;Url – you enter a Url in the full format, ie &lt;a href="http://example.com/somewhere.aspx"&gt;http://example.com/somewhere.aspx&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;Page – you select a page from the current site in the drop down box&lt;/li&gt;    &lt;li&gt;File – you select a file from the current site in the drop down box&lt;/li&gt;    &lt;li&gt;User – you enter the username for a user in your site&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you choose ‘File’ it will create a linkclick based Url – but that’s not what this blog post is about.&lt;/p&gt;  &lt;p&gt;If you choose ‘Page’, it will create a normal Url based on your current Friendly Url Settings.  In this example, ‘Blog’ is selected, so the returned Url will be http://example.com/blog.aspx&lt;/p&gt;  &lt;p&gt;However, if you then check ‘Track number of times this link is clicked’ then the simple hyperlink will be replaced with a linkclick Url, which will track the tabid the destination is for, and the module Id the link is situated on, giving you a hyperlink which will look like http://example.com/linkclick.aspx?link=aa&amp;tabid=xx&amp;mid=yy.  When you click on this link, the click is recorded, and then the request is 302 redirected to the eventual page.&lt;/p&gt;  &lt;p&gt;So my recommendation is this : &lt;strong&gt;Do not tick the ‘Track number of times this link is clicked’ unless you have a very clear and valid reason to do so.&lt;/strong&gt;  &lt;/p&gt;  &lt;p&gt;By sticking to this advice, you’ll avoid having ‘LinkClick.aspx’ Urls all through your site content.&lt;/p&gt;  &lt;h3&gt;Avoid the Link Box and get better contextual Links&lt;/h3&gt;  &lt;p&gt;While I’m discussing the ‘Announcements’ module, I’ll just add that I don’t recommend using the ‘link’ text at all.&lt;/p&gt;  &lt;p&gt;Instead of having a text which reads something like:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;‘My very important announcement on the sale of widgets &lt;u&gt;read more&lt;em&gt;…&lt;/em&gt;&lt;/u&gt;’&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I recommend ignoring the ‘link’ field and just baking the link into the Html description, like this:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;‘My very important announcement on the &lt;u&gt;sale of widgets&lt;/u&gt;’&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;You can link in the Html either by creating the Html yourself, directly, or by using the FCK Editor/Telerik RadEditor link toolbar button to do it for you.&lt;/p&gt;  &lt;p&gt;Link this way does two things:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;It gives exact control over the link anchor text your link has.  This helps notify search engines of what the relevant keywords for the linked page are.&lt;/li&gt;    &lt;li&gt;It gives exact control over the format of the link itself, and ensures the format and destination is exactly as you wish.  For example, instead of just linking to a blog page, you can link to a particular blog entry.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;This is how the announcements on the home page of this site are handled.&lt;/p&gt;  &lt;h2&gt;Conclusion&lt;/h2&gt;  &lt;p&gt;My advice is to avoid the linkclick handler all together.  Further to this, I advise learning on how to create correct html anchor links (the &lt;a href=http://www.ifinity.com.au’’&gt;link text&lt;/a&gt; tag) and craft them yourself, so you know exactly where and how you are linking.&lt;/p&gt;  &lt;p&gt;Got any more pointers, disagree or agree?  Leave a comment and let me know.&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/91/Using-Friendly-Urls-in-internal-site-links-instead-of-LinkClick</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/91/Using-Friendly-Urls-in-internal-site-links-instead-of-LinkClick#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/91/Using-Friendly-Urls-in-internal-site-links-instead-of-LinkClick</guid>
      <pubDate>Thu, 24 Jun 2010 06:56:05 GMT</pubDate>
      <slash:comments>6</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=91</trackback:ping>
    </item>
    <item>
      <title>Real 404 Error Handling in DotNetNuke</title>
      <description>&lt;p&gt;404 Handling is the process of managing what happens when a visitor comes to your site and enters a Url/follows a link which isn't valid.  The correct handling of 404 errors can really mean the different between a professional looking site, and one that still looks like it is in development.  The name ‘404 Error’ is used because the web server returns a &lt;a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes" target="_blank"&gt;response code&lt;/a&gt; of ‘404’, meaning it couldn’t find a matching file/resource for the Url.&lt;/p&gt;  &lt;p&gt;A well developed 404 strategy will retain users, keep search engines up to date and in general make your site look like a polished and finished effort.&lt;/p&gt;  &lt;p&gt;This post takes a look at what happens when a 404 occurs, how DotNetNuke handles it, and how the new version of Url Master (2.0) can handle 404 errors.&lt;/p&gt;  &lt;h3&gt;Background on DotNetNuke 404 Error Handling.&lt;/h3&gt;  &lt;p&gt;In order to discuss issues behind DotNetNuke 404 handling, it’s worthwhile to just take a background look at how DotNetNuke handles all Urls that are requested.  As I’m sure you are aware, DotNetNuke sits on the ‘Active Server Pages .NET’ (ASP.NET) platform, which runs in ‘Internet Information Services’ (IIS), which in turn runs on Microsoft Windows.&lt;/p&gt;  &lt;h4&gt;DotNetNuke Url Handling&lt;/h4&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/Real404HandlinginDotNetNuke_1252F/404_Error_Handling.gif"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="404_Error_Handling" border="0" alt="404_Error_Handling" src="/Portals/0/images/Real404HandlinginDotNetNuke_1252F/404_Error_Handling_thumb.gif" width="621" height="568" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This diagram demonstrates what happens when a Url is requested to a DotNetNuke installation.  The steps are:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Request from browser arrives at website &lt;/li&gt;    &lt;li&gt;IIS inspects the Url extension, and sends the request according to the current configuration.  Static files (.jpg, .gif, .css etc) are read directly from the file system, and streamed back as the response.   ASP.NET files (.aspx, .axd, .asmx, etc) are passed onto the ASP.NET runtime. &lt;/li&gt;    &lt;li&gt;For ASP.NET requests, they are given to the configured Url Rewriter for DotNetNuke.      &lt;br /&gt;a) If a match is found with a page in DotNetNuke, then the Url is rewritten so that it looks like /default.aspx?tabid=xx etc.  ‘Default.aspx’ is the one of the only &lt;em&gt;physical&lt;/em&gt; files that you can see if you look in the website directory for a DotNetNuke installation.  b) If no match is found with a page (or rule) in DotNetNuke, the Url is not rewritten and passed back to ASP.NET without modification.  &lt;br /&gt;c) ASP.NET will then attempt to locate the file (or handler, if defined in the web.config file) and execute the contents.  This is the same for both rewritten requests and requests not touched by the Url Rewriter. &lt;/li&gt;    &lt;li&gt;If ASP.NET cannot find a matching file or handler for the Url, it will drop into it’s defined 404 error configuration.  If a 404 Error handler is specified, then ASP.NET will do a 302 redirect to that Url, and the 404 page/handler will stream the contents back along with a ‘200 OK’ status. &lt;/li&gt;    &lt;li&gt;If ASP.NET did find a matching file or handler, that code is executed, the contents are streamed back and a ‘200 OK’ Http status is returned. &lt;/li&gt;    &lt;li&gt;For IIS static files, if IIS cannot find a matching file, it will lookup the configuration of the IIS website.  If it finds a custom 404 error handler, that page will be shown.  Otherwise, it will show a standard ‘IIS’ 404 error page, which is different depending on the version and other settings.  In both cases, IIS will return a ‘404 Not Found’ Http status.  If the missing file is an image, you’ll see a broken image in the web page. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The reason I have detailed this process is to highlight problems with it.  I’ll do that by showing what you want to happen when someone requests a file that doesn’t exist.&lt;/p&gt;  &lt;h2&gt;Ideal 404 Handling for a Website &lt;/h2&gt;  &lt;p&gt;This what I think should happen when you get a 404 error on your site, regardless of underlying technology.&lt;/p&gt;  &lt;p&gt;1. The 404 Error Page should immediately identify itself as associated with your site.  &lt;/p&gt;  &lt;p&gt;You can choose the wording, whether it’s a formal ‘404 Error on Url xyx’ or the informal ‘Whoopsie! Lost that document’.  But it’s important that the page shown at least looks like it belongs to the target website, by some level of branding such as colours, fonts, logos. &lt;/p&gt;  &lt;p&gt;2. The 404 Error Page should show a set of links where a person can get back on track.  The gold standard is where it runs a search on the server and returns some results, but a simple set of links back into the main part of the site is probably good enough for most people.   Just suggesting someone go back and try again isn’t much help, particularly if they clicked on a link in an email or on some social media site.&lt;/p&gt;  &lt;p&gt;3. You should be aware of any 404 Errors happening.&lt;/p&gt;  &lt;p&gt;A curious artefact of everyone migrating towards web-analytics programs like Google Analytics is that they don’t track 404’s.  I admit I only look in my actual web logs when there is a problem or something to investigate, and I rely on Analytics to tell me what the trends are.  This skips a big part of traffic analysis – finding people who thought they were coming to your site and missed because of a bad link.  Analytics packages don’t track 404 errors because they run a piece of javascript on a loaded page to track the traffic – no page load, no traffic logged.&lt;/p&gt;  &lt;p&gt;4. Your 404 page must return a 404 status to search engine indexes.&lt;/p&gt;  &lt;p&gt;The Http status codes are there for browsers and search engine indexing robots to understand and act upon.  If you don’t return a 404 status code when a Url does not return anything, search engines don’t know that the page doesn’t exist.  It’s very important to return a 404 status code so that dead links and pages can be removed from the page index.&lt;/p&gt;  &lt;h3&gt;How a standard DotNetNuke Installation Fails the 404 Criteria&lt;/h3&gt;  &lt;p&gt;Using the above criteria, here’s where a standard DotNetNuke installation fails:    &lt;br /&gt;1.  There is no standard 404 page for DotNetNuke.  Depending on ‘where’ the error lies, DNN will either show the ASP.NET 404 page (no branding, no links) or the IIS 404 Page (no branding, no links).&lt;/p&gt;  &lt;p&gt;You can overcome this by creating your own 404 page, and putting it in the root of your website, so that any 404 errors are routed to that page.  This is how dotnetnuke.com does it.  The problem with this approach is when you have a multi-portal DotNetNuke installation – you are forced to have a generic page, because all portals will use the same 404 handler.  There’s no way for ASP.NET to display a per-portal error page because ASP.NET just sees a DotNetNuke install as one website.  The portal segmentation is achieved within DotNetNuke itself.&lt;/p&gt;  &lt;p&gt;2.  Again, having no standard error page means not having links for the site, and, again, if you have a multi-portal install, you can’t easily determine which links to show for which site.&lt;/p&gt;  &lt;p&gt;3.  DotNetNuke will not log any 404 errors in it’s site log, or through an analytics package (unless you include the analytics script on a custom 404 page – but again for multi-portal installs this can’t work properly).  You have to look at the IIS website logs to discover what 404’s are occuring.&lt;/p&gt;  &lt;p&gt;4.  Crucially, any ASP.NET application doesn’t actually return a correct 404 Http status back to a search engine if it follows a dead link.  In fact, you get a 302 redirect, and then a 200 OK return status.   The search engines assume that the original Url has now changed, and they index the 404 error page for that Url instead.  If you don’t believe me, try searching Google for ‘the resource cannot be found’.  Once you get past the first 5 pages of programmers asking questions on how to fix the problem, you’ll see thousands, if not millions, of ASP.NET sites that have the generic ASP.NET error page indexed for previously-valid Urls.  While this probably doesn’t present too much of a problem, SEO wise, it would be better if search engines can automatically remove dead links for your site instead of leaving them lying around.  Some links really are just dead and should be removed.   Sometimes search engine ‘bots’ take guesses at Urls while indexing your site, and you definitely don’t want to have them endlessly indexing your site errors because every guessed-at link returns a valid 200 page.  &lt;/p&gt;  &lt;p&gt;For SEO purposes, though, the most important part is step 3 : logging your 404 errors so that you can setup redirects to capture the valuable traffic if a popular link is wrong.&lt;/p&gt;  &lt;h2&gt;404 Handling with Url Master 2.0&lt;/h2&gt;  &lt;p&gt;[Note : &lt;a href="http://www.ifinity.com.au/Products/Url_Master_2.0_Beta" target="_blank"&gt;Url Master 2.0 is currently in Beta Testing&lt;/a&gt;, and is not yet available for public release. This information is posted to alert readers of upcoming functionality which will be available soon.]&lt;/p&gt;  &lt;p&gt;When Url Master version 1.0 came out, it didn’t take long before people started asking about how to handle 404 errors better in their DotNetNuke installs.  The emails and forum posts have continued at a steady rate the whole time the module has been released.  Thanks to many conversations with many different people, Url Master version 2.0 contains probably the most robust 404 handling you can put into an ASP.NET application.  Here’s the details:&lt;/p&gt;  &lt;h3&gt;Per-portal specification of 404 Pages&lt;/h3&gt;  &lt;p&gt;This is selected within the module settings for each portal in the installation.  Within each portal on a site, this is the choices you have on how to handle 404 errors:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Default ASP.NET 404 Handling (use existing methods)     &lt;br /&gt;This is for when you have implemented your own 404 handling scheme, and are happy with it, or you don’t particularly care about 404 errors.&lt;/li&gt;    &lt;li&gt;Show a selected DotNetNuke page for 404 Errors.     &lt;br /&gt;This method allows you to select a page in your DotNetNuke site to show when a 404 occurs. You can tailor the content of this page to exactly what you want users to see, without having any more skill than it takes to create any other DotNetNuke page.  When a 404 error happens, this page will be shown.  Because it is a full DNN page, it will show the correct menus, links, skin, logos, etc.  You can place anything on the page; script, sitemap modules, html, flash, images – anything you can do with a DotNetNuke page&lt;/li&gt;    &lt;li&gt;Show a specified Url in the site.  &lt;br /&gt;This method allows you to show another page/handler in your site for 404 errors.  You might have a simple html page setup, or you might just want to use the standard DotNetNuke ErrorPage.aspx.  Or, you might have written a customised handler for 404 errors which then redirects to a specific page depending on the Url.  This option allows to to tailor your needs endlessly.&lt;/li&gt;    &lt;li&gt;Show specific DotNetNuke for some 404 Errors, and show a specified Url for others.     &lt;br /&gt;This method uses a Regex expression to show a specified DotNetNuke page (as per the second option) for most errors, but for those matching a Regex expression, to use a Url that you specify.  This allows you to have a generic 404 for most errors, but a specific page for other types.  For example, you can match on Urls that have ‘ProductId’ and show a product search page.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;If you specify either showing a DotNetNuke page or Url within the site, the module will return a true 404 Http status when the page is shown.  This method &lt;em&gt;&lt;strong&gt;doesn’t&lt;/strong&gt; &lt;/em&gt;use a 302 redirect to a specified page like the standard ASP.NET handling does.  The original, incorrect Url will still be in the browser bar for a visitor, not a generic Url like ‘ErrorPage.aspx’.  &lt;/p&gt;  &lt;p&gt;Note that all of the above options are all strictly point-and-click.  There’s no need to modify web.config files, edit custom html files or use FTP to move things around.&lt;/p&gt;  &lt;h3&gt;404 Error Logging&lt;/h3&gt;  &lt;p&gt;The Url Master module now has the ability to log 404 Errors per portal in your installation.  What this means is that you have a convenient place to check on 404 errors and look for patterns of recurring Urls being requested.  This allows you to identify any problem Urls, and, if found, you can setup a 301 redirect for that Url to somewhere valid in your site, using the Custom Redirect functionality built into the Url Master module.&lt;/p&gt;  &lt;p&gt;The 404 Log will provide the following information:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Date/ Time of request&lt;/li&gt;    &lt;li&gt;Url requested that resulted in a 404.&lt;/li&gt;    &lt;li&gt;IP Address request originated from&lt;/li&gt;    &lt;li&gt;User Agent (browser type, or search engine bot type)&lt;/li&gt;    &lt;li&gt;The originally requested Url, if the Url was rewritten before returning the 404 (helps identify Url rewriting errors)&lt;/li&gt;    &lt;li&gt;An identified page or portal alias/ if matched correctly&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The 404 Log is self-managing and keeps its size to a maximum amount of rows, to prevent filling up of database tables and disk space.&lt;/p&gt;  &lt;h3&gt;Other 404 Errors in IIS&lt;/h3&gt;  &lt;p&gt;Keen readers will note that this discussion hasn’t covered off errors for non-DotNetNuke related Urls, such as static files like images and CSS files.   These are not as important, because they show up as broken/missing pieces of information within the site, rather than entire pages showing errors.  If custom errors are required for these items, I suggest using the standard IIS configuration to point the 404 handling to the pages you create, or create a new custom page to show 404 errors for static files.&lt;/p&gt;  &lt;h3&gt;500 Errors&lt;/h3&gt;  &lt;p&gt;In addition to 404 error handling, Url Master version 2.0 also contains similar handling for ‘500 Application Errors’.  A 500 error is shown when something goes seriously wrong with the site and it is not working properly.  You can use the same settings to show customised 500 error pages for your site, when it encounters unhandled errors.  Unhandled errors are ones that DotNetNuke itself doesn’t detect (when you get an error in a module, you’ll still see the familiar ‘an error has occured’ message).  This gives administrators greater control about how the application behaves when things seriously go wrong.   You can use a DotNetNuke page, or an external file in the site, like a html file.  Or, you can just elect to use the ‘ErrorPage.aspx’.  It’s important to note, though, that not all errors can be caught like this : some are so serious that the site never quite gets started in the first place.  But you’ll know when that happens, because the server will return nothing at all.&lt;/p&gt;  &lt;h2&gt;Summary&lt;/h2&gt;  &lt;p&gt;I’m hoping that this is a comprehensive step forwards in 404 handling in DotNetNuke websites.  I’m also hoping that this post doesn’t flush out any more suggestions and that I have covered all angles.    I can’t wait to release the finished product and finally close the work item on my release management system.  The one that says ‘Handle 404 Errors properly’, and that has been open and waiting since June 2008.&lt;/p&gt;  &lt;p&gt;Thanks to all the customers, well-wishers and altruistic types who have contributed their suggestions to how 404 errors should be handled.  You know who you are, and I can’t say enough how much this module improves through community feedback.&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/90/Real-404-Error-Handling-in-DotNetNuke</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/90/Real-404-Error-Handling-in-DotNetNuke#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/90/Real-404-Error-Handling-in-DotNetNuke</guid>
      <pubDate>Fri, 11 Jun 2010 06:50:55 GMT</pubDate>
      <slash:comments>6</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=90</trackback:ping>
    </item>
    <item>
      <title>Top 5 DotNetNuke Manifest file Module Packaging Tips</title>
      <description>&lt;h3&gt;1. Use Html in the File for better layout in the install pages&lt;/h3&gt;  &lt;p&gt;This one comes from the &lt;a href="http://www.erikvanballegoij.com/tabId/36/itemId/24/DotNetNuke-5-Extension-packaging.aspx" target="_blank"&gt;blog of Erik VB&lt;/a&gt; : use html in the manifest file by including &lt;![CDATA[ sections.  &lt;/p&gt;  &lt;p&gt;A CDATA section is a way of including xml/html within an xml file.  As a manifest file is just a big xml file, you can use this to your advantage and include cdata sections for various pieces of information.  For example, instead of providing an email address, here’s what’s in my manifiest file:&lt;/p&gt;  &lt;p&gt;&lt;email&gt;&lt;![CDATA[Contact iFinity via the &lt;a href="&lt;a href="http://www.ifinity.com.au/Talk_to_us""&gt;http://www.ifinity.com.auhttp://www.ifinity.com.au/Talk_to_us"&lt;/a&gt; target="_new"&gt;Contact Page&lt;/a&gt;]]&gt;&lt;/email&gt;&lt;/p&gt;  &lt;p&gt;When the module installs, instead of getting a plain listing of an email address, this gives a link to the page on the iFinity website for contact.    You can also see in the below screenshot that the Url is an actual link to the site.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="dnn_manifest_licence_details" border="0" alt="dnn_manifest_licence_details" src="/Portals/0/images/DotNetNuke5ManifestfileModulePackagingTi_EF0E/dnn_manifest_licence_details.jpg" width="644" height="291" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;This also comes in handy with the ‘Release Notes’ section, and allows html elements like headers, lists and hyperlinks.&lt;/p&gt;  &lt;h3&gt;2. Use a resources.zip file for all your files&lt;/h3&gt;  &lt;p&gt;I actually stumbled across this one accidentally while reading something else on Scott McCulloch’s website.  If you’ve been including each and every static file in your package by listing each one individually, then you’ve been both wasting your time and opening yourself up to packaging mistakes.  Just include a resource &lt;component&gt; section, and list your resources.zip file:&lt;/p&gt;  &lt;p&gt;  &lt;component type="ResourceFile"&gt;    &lt;br /&gt;    &lt;resourceFiles&gt;     &lt;br /&gt;      &lt;basePath&gt;DesktopModules\iFinity.UrlMaster&lt;/basePath&gt;     &lt;br /&gt;      &lt;resourceFile&gt;     &lt;br /&gt;        &lt;name&gt;iFinity.UrlMaster_Resources.zip&lt;/name&gt;     &lt;br /&gt;      &lt;/resourceFile&gt;     &lt;br /&gt;    &lt;/resourceFiles&gt;     &lt;br /&gt;  &lt;/component&gt;     &lt;br /&gt;&lt;/components&gt;&lt;/p&gt;  &lt;p&gt;You should have some sort of automated packaging process : I use a command line script with a built-in PKZIP command.  This dumps all the files from the development directory into a directory, and then zips them up as the resources file.&lt;/p&gt;  &lt;h3&gt;3. Use a html file for your Licence Agreement&lt;/h3&gt;  &lt;p&gt;My EULA came at great cost to me via a lawyer.  I say great cost because I actually had to pay for it, being unable to barter services (they still have &lt;em&gt;fax&lt;/em&gt; machines everywhere?!) or get them to participate in the beer economy.  Because a lawyer had anything to do with it, it’s a mile and a half long, and full of paragraphs and headings.   I’ve wanted to include in the DNN 5 ‘Accept Licence’ page, but there’s been two problems – the first being that including a .txt file in the ‘&lt;license&gt;’ element of the manifest file just dumps a pile of text in one big blob, and the second being that it pushes the bottom of the page, with the ‘accept’ and ‘next’ controls on it, to far away, leaving the prospective installer what to do next.&lt;/p&gt;  &lt;p&gt;After a bit of experimentation, I figured out that you could include a html file using &lt;license src=”eula.htm”&gt; and this would blend the licence html in with the overall DNN module installer page.  I then took this further and added a bit of CSS to restrict the size of the container, and add a scroll bar (overflow:scroll).  The result is a &lt;em&gt;very&lt;/em&gt; Microsoft looking EULA box with the ‘Accept Licence’ just underneath.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="dnn_manifest_licence_page" border="0" alt="dnn_manifest_licence_page" src="/Portals/0/images/DotNetNuke5ManifestfileModulePackagingTi_EF0E/dnn_manifest_licence_page.jpg" width="644" height="381" /&gt; &lt;/p&gt;  &lt;p&gt;This is done by using the correct format in the manifest file, namely:&lt;/p&gt;  &lt;p&gt;&lt;license src="EULA.html" /&gt;&lt;/p&gt;  &lt;p&gt;The EULA.html file is included in the zip file of the package, and the important part at the top looks like this:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="dnn_manifest_licence_html" border="0" alt="dnn_manifest_licence_html" src="/Portals/0/images/DotNetNuke5ManifestfileModulePackagingTi_EF0E/dnn_manifest_licence_html.jpg" width="644" height="478" /&gt;&lt;/p&gt;  &lt;p&gt;Note the use of two div elements : one to contain the licence, and the other to provide a restricting top layer that creates a scrollbar.&lt;/p&gt;  &lt;p&gt;Of course you could do this just by entering all the license information into the manifest file, but that would make it large and unwieldy.  Having the EULA in a separate file makes it easy to track it in source control and to share between different projects, and makes it easy for people to read if they are poking around in your install file.&lt;/p&gt;  &lt;h3&gt;4. Make your module DNN 4.x and DNN5.x compatible by using two separate manifest files.&lt;/h3&gt;  &lt;p&gt;I’ve actually been banging on about this ever since the new manifest file design was announced for DNN 5.  The first problem I could see was having to have two separate install packages, and people getting confused which one they needed.  It’s OK to use &lt;em&gt;install_dnn5.zip&lt;/em&gt; and &lt;em&gt;install_dnn4.zip&lt;/em&gt; but you’d be surprised the number of people with DNN installs who have no idea what version they are running.  I always advocated the use of a .dnn5 extension for DNN 5 manifest files – the perfect solution because DNN 4 installs would just ignore the file, and DNN5 installs would pick it up and use it.&lt;/p&gt;  &lt;p&gt;Well, knock me down with a feather, but I found out by accident that DNN (well, 5.4 at least) works exactly like that.  I found out accidentally because I renamed a file .dnn5 in my package while messing about with it, and found that DNN 5 picked up and read that file.&lt;/p&gt;  &lt;p&gt;So, you can include two different manifest files in the one package, and DotNetNuke will work out which one is the right one to use.  The files should be like this:&lt;/p&gt;  &lt;p&gt;module name.dnn&lt;/p&gt;  &lt;p&gt;module name.dnn5&lt;/p&gt;  &lt;p&gt;That’s all you need to do!  I’m sure this was announced somewhere, but I didn’t find out &lt;em&gt;until I did it by accident&lt;/em&gt;.  That’s the sort of surprise that makes your day.&lt;/p&gt;  &lt;h3&gt;5. Use the ‘sourceFileName’ attribute for your assembly files.&lt;/h3&gt;  &lt;p&gt;I’ve seen quite a few forum posts from people wondering how to get their assemblies loading right.  The confusion usually comes about because they locate the assembly files in the ‘root’ of the zip folder, but then they don’t get copied to the /bin folder correctly.&lt;/p&gt;  &lt;p&gt;Here’s how to do it:&lt;/p&gt;  &lt;p&gt;&lt;component type="Assembly"&gt;   &lt;br /&gt;  &lt;assemblies&gt;    &lt;br /&gt;    &lt;assembly&gt;    &lt;br /&gt;      &lt;path&gt;bin&lt;/path&gt;    &lt;br /&gt;      &lt;name&gt;iFinity.UrlMaster.dll&lt;/name&gt;    &lt;br /&gt;      &lt;sourceFileName&gt;iFinity.UrlMaster.dll&lt;/sourceFileName&gt;    &lt;br /&gt;    &lt;/assembly&gt; &lt;/p&gt;  &lt;p&gt;Note the sourceFileName element : this tells the package installer where in the zip file the file can be found, while the &lt;path&gt;&lt;name&gt; elements tell it where to put the file for the install.&lt;/p&gt;  &lt;p&gt;That’s it – my top 5 tips for working with DNN 5 Packaging.  Do you have more?  Let me know via the comments.&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/89/Top-5-DotNetNuke-Manifest-file-Module-Packaging-Tips</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/89/Top-5-DotNetNuke-Manifest-file-Module-Packaging-Tips#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/89/Top-5-DotNetNuke-Manifest-file-Module-Packaging-Tips</guid>
      <pubDate>Tue, 25 May 2010 07:00:43 GMT</pubDate>
      <slash:comments>16</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=89</trackback:ping>
    </item>
    <item>
      <title>Comparing Url Rewriting performance with DotNetNuke and Url Master with no .aspx extensions</title>
      <description>&lt;p&gt;A question that I field on a regular basis is ‘what performance implications are there for switching off page extensions on my DotNetNuke site?’.   If you peek around various posts and blogs, you’ll see dire warnings from people predicting the end of your server as you know it.   The main problem people have is that, when you switch off page extensions, all of the processing for all requests on the server are routed through the ASP.NET runtime, which has to serve up not only the dynamic ASP.NET pages, but all of the static content (js files, jpg files, css files et al) as well.  &lt;/p&gt;  &lt;p&gt;My response to people has always been : switch it on and see what happens,  if your site becomes too slow then turn it back off again.  My advice tends to be of a practical nature in this respect.  My own site has been running without extensions for years, and while it is known to have the occasional hiccup, that’s never been to do with the missing .aspx on the Urls.&lt;/p&gt;  &lt;p&gt;However, I decided to do a little bit of comparison with a standard DNN site and one with the Url Master module installed, so I could point to some empirical data when asked this question, plus give others a jumping off point to doing their own research.  As a side benefit it would give me a baseline performance comparison between the latest Url Master and standard DNN Friendly Url Provider.&lt;/p&gt;  &lt;h3&gt;Performance Criteria &lt;/h3&gt;  &lt;p&gt;Before starting, I decided the criteria I would measure across to compare.  These would be tracked over the test run and compared with each scenario.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Memory Usage – looking for average and peak memory usage &lt;/li&gt;    &lt;li&gt;Open threads – looking for peaks in open threads &lt;/li&gt;    &lt;li&gt;Time to first byte – measures how quickly the application can send back the request &lt;/li&gt;    &lt;li&gt;Time to last byte – measures how quickly the application finishes the request &lt;/li&gt;    &lt;li&gt;Requests per second – measures the rate at which the web server is handling requests &lt;/li&gt; &lt;/ul&gt;  &lt;h3&gt;Scenarios &lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Plain DNN 5.4 Installation &lt;/li&gt;    &lt;li&gt;Plain DNN 5.4 Installation with Url Master &lt;/li&gt;    &lt;li&gt;Plain DNN 5.4 Installation with Url Master and no page extensions &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Testing Platform&lt;/h2&gt;  &lt;p&gt;The testing was done on a DotNetNuke 5.4.2 installation, with the standard skin.  The installation contains 3 portals and 98 tabs across the 3 portals.   The Installation was standard apart from the Blog and Forum modules installed, and the Url Master module where tested.&lt;/p&gt;  &lt;p&gt;The requests were collected using &lt;a href="http://www.fiddlertool.com/" target="_blank"&gt;Microsoft Fiddler&lt;/a&gt;, and was equivalent to a click on each page of the first portal, which results in approximately 162 requests to the server, across all style sheets, images, css files and actual DotNetNuke pages.&lt;/p&gt;  &lt;p&gt;The tests were submitted to the &lt;a title="Microsoft WCAT Tool download" href="http://www.iis.net/community/default.aspx?tabid=34&amp;g=6&amp;i=1466" target="_blank"&gt;Microsoft WCAT tool&lt;/a&gt; (Web Capacity Analysis Tool) using the &lt;a href="http://blogs.iis.net/thomad/archive/2010/05/11/using-the-wcat-fiddler-extension-for-web-server-performance-tests.aspx" target="_blank"&gt;WCAT Fiddler Extension&lt;/a&gt;.  These were done on a Windows 7 development machine running IIS7 in integrated pipeline mode.    WCAT was configured to act as 10 concurrent clients submitting the stored requests continually for 30 seconds.&lt;/p&gt;  &lt;p&gt;The testing configuration was designed to test a short burst of concurrent requests on the server, not to test the absolute limits of the application or the hardware.  Probably 95% of all the DotNetNuke sites I have seen fall into the type of performance envelope I’m using.  The main principle here was testing relative changes – when swapping out the standard DNN Friendly Url Provider/ Url Rewriter, what is the change in performance?&lt;/p&gt;  &lt;p&gt;Each scenario was tested with 6 test runs, including one where the IIS service was restarted before starting, and one where the Application Pool was recycled before starting.  This gave coverage of different scenarios and was designed to show the difference between cold starts and hot running situations.&lt;/p&gt;  &lt;p&gt;The data were obtained using a combination of both the WCAT metrics, and using the Windows Performance Monitor, which provided information on memory usage and open threads.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Performance Monitor" border="0" alt="Performance Monitor Screenshot" src="/portals/0/blog/files/2/88/performance_54_um_no_ext.jpg" width="500" /&gt;&lt;/p&gt;  &lt;p&gt;The above picture shows the performance counters during a test run.&lt;/p&gt;  &lt;h2&gt;Testing Results&lt;/h2&gt;  &lt;p&gt;If I were putting a ‘media talking point’ out for this article, it would be : ‘Url Master outperforms standard DotNetNuke Rewriter’.  However, in reality the testing was probably too limited in scope to come up with such a headline.  The tests did show that the Url Master module had both better response times and throughput than the standard DotNetNuke Url Rewriter, and was comparable in memory usage.&lt;/p&gt;  &lt;p&gt;The main purpose of the testing, however, was to test whether or not the switch to ‘wildcard mapping’ or, in other words, removing the .aspx from the Urls has any measurable performance effect.  Remember, the main issue that most people have with the routing of all requests through the ASP.NET runtime is that it will result in slower performance than serving those files through the ‘Native’ IIS static file handler.&lt;/p&gt;  &lt;p&gt;The surprising result for me was that the ‘no page extension’ scenario actually processed requests &lt;em&gt;faster&lt;/em&gt; than when the .aspx extension was mapped to the asp.net runtime.  This is probably due to the fact that IIS7 in integrated pipeline manages this situation very well, and the extra speed can just be put down to random differences in the samples.  A more safe statement would be that no discernible effect could be found.&lt;/p&gt;  &lt;h3&gt;&lt;/h3&gt;  &lt;h3&gt;Requests per Second&lt;/h3&gt;  &lt;p&gt;Requests per second measures the amount of requests the web server is handling, and is a measure of throughput of the server.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Requests Per Second" border="0" alt="Requests per second graph" src="/portals/0/blog/files/2/88/performance_54_rps.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;As you can see from the data, the Url Master module changes the amount of requests per second that the installation can handle.  In this graph, a larger value is better. This is likely due to the level of caching used in the design.  The Url Master module caches both the index of pages for Url Rewriting purposes, and it also caches the list of Urls used when generating Urls for the output Html of a DNN page.  Thus most of the usage of the module works from in-memory caches, and restricts the amount of calls to the database.&lt;/p&gt;  &lt;h3&gt;Average time to first byte&lt;/h3&gt;  &lt;p&gt;The Average time to first byte metric shows the responsiveness of the web application to requests.  It measures the time taken before the request is submitted to the server, to when the request is received.   Note that this testing took place on the same server as the web application, so there is no network latency involved.  What we are measuring is the time taken to process the page and respond to the request.&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Average Time to First Byte" border="0" alt="Average Time to first byte graph" src="/portals/0/blog/files/2/88/performance_54_attfb.jpg" /&gt;&lt;/p&gt;  &lt;p&gt;This metric shows that the Url Master improves the response time of the DotNetNuke application in the tests run.  Again, my guess is that the way the module rewrites the rules is faster than the standard DotNetNuke Friendly Url Provider, again probably because of the caching.&lt;/p&gt;  &lt;h3&gt;Full Data Set&lt;/h3&gt;  &lt;p&gt;Below is the full dataset of the results of the tests run.   You can peruse the information and see where the differences show up.  &lt;/p&gt;  &lt;table style="border-bottom: #efefef 1px solid; border-left: #efefef 1px solid; border-top: #efefef 1px solid; border-right: #efefef 1px solid" cellspacing="0" cellpadding="0"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td width="64"&gt;         &lt;p&gt;Test Setup&lt;/p&gt;       &lt;/td&gt;        &lt;td width="83"&gt;Memory Usage (bytes)&lt;/td&gt;        &lt;td width="83"&gt; &lt;/td&gt;        &lt;td width="92"&gt; &lt;/td&gt;        &lt;td width="64"&gt;Avg Open Threads&lt;/td&gt;        &lt;td width="94"&gt;Requests / second&lt;/td&gt;        &lt;td width="64"&gt;Time to first byte&lt;/td&gt;        &lt;td width="64"&gt;milliseconds&lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt;avg&lt;/td&gt;        &lt;td width="83"&gt;min&lt;/td&gt;        &lt;td width="92"&gt;max&lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="94"&gt; &lt;/td&gt;        &lt;td width="64"&gt;avg&lt;/td&gt;        &lt;td width="64"&gt;max&lt;/td&gt;        &lt;td width="64"&gt;50%&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;Standard DNN&lt;/td&gt;        &lt;td width="83"&gt;28,288,562&lt;/td&gt;        &lt;td width="83"&gt;17,888,920&lt;/td&gt;        &lt;td width="92"&gt;42,168,896&lt;/td&gt;        &lt;td width="64"&gt;59&lt;/td&gt;        &lt;td width="94"&gt;217.07&lt;/td&gt;        &lt;td width="64"&gt;479&lt;/td&gt;        &lt;td width="64"&gt;4524&lt;/td&gt;        &lt;td width="64"&gt;31&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt;32,381,297&lt;/td&gt;        &lt;td width="83"&gt;19,449,704&lt;/td&gt;        &lt;td width="92"&gt;54,097,768&lt;/td&gt;        &lt;td width="64"&gt;60&lt;/td&gt;        &lt;td width="94"&gt;218&lt;/td&gt;        &lt;td width="64"&gt;473&lt;/td&gt;        &lt;td width="64"&gt;4540&lt;/td&gt;        &lt;td width="64"&gt;16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt;31,793,653&lt;/td&gt;        &lt;td width="83"&gt;20,735,960&lt;/td&gt;        &lt;td width="92"&gt;62,305,244&lt;/td&gt;        &lt;td width="64"&gt;61&lt;/td&gt;        &lt;td width="94"&gt;427.33&lt;/td&gt;        &lt;td width="64"&gt;245&lt;/td&gt;        &lt;td width="64"&gt;4586&lt;/td&gt;        &lt;td width="64"&gt;0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt;32,134,567&lt;/td&gt;        &lt;td width="83"&gt;19,666,056&lt;/td&gt;        &lt;td width="92"&gt;47,637,008&lt;/td&gt;        &lt;td width="64"&gt;62&lt;/td&gt;        &lt;td width="94"&gt;217.63&lt;/td&gt;        &lt;td width="64"&gt;475&lt;/td&gt;        &lt;td width="64"&gt;4665&lt;/td&gt;        &lt;td width="64"&gt;16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;iisreset&lt;/td&gt;        &lt;td width="83"&gt;18,380,881&lt;/td&gt;        &lt;td width="83"&gt;6,780,652&lt;/td&gt;        &lt;td width="92"&gt;37,184,816&lt;/td&gt;        &lt;td width="64"&gt;40&lt;/td&gt;        &lt;td width="94"&gt;446.5&lt;/td&gt;        &lt;td width="64"&gt;237&lt;/td&gt;        &lt;td width="64"&gt;4602&lt;/td&gt;        &lt;td width="64"&gt;15&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;new wp&lt;/td&gt;        &lt;td width="83"&gt;29,902,197&lt;/td&gt;        &lt;td width="83"&gt;7,066,944&lt;/td&gt;        &lt;td width="92"&gt;105,284,592&lt;/td&gt;        &lt;td width="64"&gt;36.8&lt;/td&gt;        &lt;td width="94"&gt;490.87&lt;/td&gt;        &lt;td width="64"&gt;188&lt;/td&gt;        &lt;td width="64"&gt;5288&lt;/td&gt;        &lt;td width="64"&gt;15&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt;28,813,526&lt;/td&gt;        &lt;td width="83"&gt;15,264,706&lt;/td&gt;        &lt;td width="92"&gt;58,113,054&lt;/td&gt;        &lt;td width="64"&gt;53&lt;/td&gt;        &lt;td width="94"&gt;336.23&lt;/td&gt;        &lt;td width="64"&gt;349.50&lt;/td&gt;        &lt;td width="64"&gt;4700.83&lt;/td&gt;        &lt;td width="64"&gt;15.50&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;kilobytes&lt;/td&gt;        &lt;td width="83"&gt;28,138&lt;/td&gt;        &lt;td width="83"&gt;14,907&lt;/td&gt;        &lt;td width="92"&gt;56,751&lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="94"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt; &lt;/td&gt;        &lt;td width="83"&gt; &lt;/td&gt;        &lt;td width="92"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="94"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;Url Master&lt;/td&gt;        &lt;td width="83"&gt;26,611,569&lt;/td&gt;        &lt;td width="83"&gt;9,997,464&lt;/td&gt;        &lt;td width="92"&gt;49,498,544&lt;/td&gt;        &lt;td width="64"&gt;56.14&lt;/td&gt;        &lt;td width="94"&gt;542.23&lt;/td&gt;        &lt;td width="64"&gt;183&lt;/td&gt;        &lt;td width="64"&gt;3588&lt;/td&gt;        &lt;td width="64"&gt;0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt;21,787,730&lt;/td&gt;        &lt;td width="83"&gt;8,263,072&lt;/td&gt;        &lt;td width="92"&gt;69,673,616&lt;/td&gt;        &lt;td width="64"&gt;39&lt;/td&gt;        &lt;td width="94"&gt;314.97&lt;/td&gt;        &lt;td width="64"&gt;331&lt;/td&gt;        &lt;td width="64"&gt;3557&lt;/td&gt;        &lt;td width="64"&gt;16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt;23,112,331&lt;/td&gt;        &lt;td width="83"&gt;13,014,831&lt;/td&gt;        &lt;td width="92"&gt;59,858,528&lt;/td&gt;        &lt;td width="64"&gt;39&lt;/td&gt;        &lt;td width="94"&gt;474.47&lt;/td&gt;        &lt;td width="64"&gt;218&lt;/td&gt;        &lt;td width="64"&gt;2965&lt;/td&gt;        &lt;td width="64"&gt;0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt;24,019,964&lt;/td&gt;        &lt;td width="83"&gt;12,914,032&lt;/td&gt;        &lt;td width="92"&gt;60,035,168&lt;/td&gt;        &lt;td width="64"&gt;40&lt;/td&gt;        &lt;td width="94"&gt;400.7&lt;/td&gt;        &lt;td width="64"&gt;259&lt;/td&gt;        &lt;td width="64"&gt;3464&lt;/td&gt;        &lt;td width="64"&gt;0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;iisreset&lt;/td&gt;        &lt;td width="83"&gt;43,609,843&lt;/td&gt;        &lt;td width="83"&gt;7,542,158&lt;/td&gt;        &lt;td width="92"&gt;133,115,904&lt;/td&gt;        &lt;td width="64"&gt;37.492&lt;/td&gt;        &lt;td width="94"&gt;422.67&lt;/td&gt;        &lt;td width="64"&gt;222&lt;/td&gt;        &lt;td width="64"&gt;4290&lt;/td&gt;        &lt;td width="64"&gt;15&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;new wp&lt;/td&gt;        &lt;td width="83"&gt;37,905,787&lt;/td&gt;        &lt;td width="83"&gt;13,054,040&lt;/td&gt;        &lt;td width="92"&gt;96,584,112&lt;/td&gt;        &lt;td width="64"&gt;34.98&lt;/td&gt;        &lt;td width="94"&gt;553.33&lt;/td&gt;        &lt;td width="64"&gt;168&lt;/td&gt;        &lt;td width="64"&gt;4056&lt;/td&gt;        &lt;td width="64"&gt;0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt;29,507,871&lt;/td&gt;        &lt;td width="83"&gt;10,797,600&lt;/td&gt;        &lt;td width="92"&gt;78,127,645&lt;/td&gt;        &lt;td width="64"&gt;41&lt;/td&gt;        &lt;td width="94"&gt;451.40&lt;/td&gt;        &lt;td width="64"&gt;230.17&lt;/td&gt;        &lt;td width="64"&gt;3653.33&lt;/td&gt;        &lt;td width="64"&gt;5.17&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;kilobytes&lt;/td&gt;        &lt;td width="83"&gt;28,816&lt;/td&gt;        &lt;td width="83"&gt;10,545&lt;/td&gt;        &lt;td width="92"&gt;76,297&lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="94"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="83"&gt; &lt;/td&gt;        &lt;td width="83"&gt; &lt;/td&gt;        &lt;td width="92"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="94"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;        &lt;td width="64"&gt; &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;Url Master / no .aspx&lt;/td&gt;        &lt;td width="83"&gt;24,679,225&lt;/td&gt;        &lt;td width="83"&gt;18,365,184&lt;/td&gt;        &lt;td width="92"&gt;38,196,888&lt;/td&gt;        &lt;td&gt;51&lt;/td&gt;        &lt;td width="94"&gt;380.13&lt;/td&gt;        &lt;td width="64"&gt;271&lt;/td&gt;        &lt;td width="64"&gt;2028&lt;/td&gt;        &lt;td width="64"&gt;16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt; &lt;/td&gt;        &lt;td&gt;31,766,699&lt;/td&gt;        &lt;td&gt;17,076,128&lt;/td&gt;        &lt;td&gt;99,749,916&lt;/td&gt;        &lt;td&gt;43&lt;/td&gt;        &lt;td&gt;449&lt;/td&gt;        &lt;td width="64"&gt;224&lt;/td&gt;        &lt;td width="64"&gt;4868&lt;/td&gt;        &lt;td width="64"&gt;16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt; &lt;/td&gt;        &lt;td&gt;31,366,464&lt;/td&gt;        &lt;td&gt;21,458,184&lt;/td&gt;        &lt;td&gt;53,405,976&lt;/td&gt;        &lt;td&gt;44&lt;/td&gt;        &lt;td&gt;450.13&lt;/td&gt;        &lt;td width="64"&gt;229&lt;/td&gt;        &lt;td width="64"&gt;2605&lt;/td&gt;        &lt;td width="64"&gt;0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt; &lt;/td&gt;        &lt;td&gt;3,202,372&lt;/td&gt;        &lt;td&gt;18,625,760&lt;/td&gt;        &lt;td&gt;69,994,176&lt;/td&gt;        &lt;td&gt;44&lt;/td&gt;        &lt;td&gt;482&lt;/td&gt;        &lt;td width="64"&gt;215&lt;/td&gt;        &lt;td width="64"&gt;3432&lt;/td&gt;        &lt;td width="64"&gt;16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;iisreset&lt;/td&gt;        &lt;td&gt;26,119,487&lt;/td&gt;        &lt;td&gt;5,265,854&lt;/td&gt;        &lt;td&gt;69,994,176&lt;/td&gt;        &lt;td&gt;40&lt;/td&gt;        &lt;td&gt;486.97&lt;/td&gt;        &lt;td width="64"&gt;180&lt;/td&gt;        &lt;td width="64"&gt;4118&lt;/td&gt;        &lt;td width="64"&gt;16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;new wp&lt;/td&gt;        &lt;td&gt;34,893,992&lt;/td&gt;        &lt;td&gt;13,985,840&lt;/td&gt;        &lt;td&gt;95,012,592&lt;/td&gt;        &lt;td&gt;36&lt;/td&gt;        &lt;td&gt;488&lt;/td&gt;        &lt;td width="64"&gt;180&lt;/td&gt;        &lt;td width="64"&gt;4212&lt;/td&gt;        &lt;td width="64"&gt;16&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt; &lt;/td&gt;        &lt;td width="83"&gt;25,338,040&lt;/td&gt;        &lt;td width="83"&gt;15,796,158&lt;/td&gt;        &lt;td width="92"&gt;71,058,954&lt;/td&gt;        &lt;td width="64"&gt;41&lt;/td&gt;        &lt;td width="94"&gt;471.07&lt;/td&gt;        &lt;td width="64"&gt;216.50&lt;/td&gt;        &lt;td width="64"&gt;3543.83&lt;/td&gt;        &lt;td width="64"&gt;13.33&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td width="64"&gt;kilobytes&lt;/td&gt;        &lt;td width="83"&gt;24,744&lt;/td&gt;        &lt;td width="83"&gt;15,426&lt;/td&gt;        &lt;td width="92"&gt;69,394&lt;/td&gt;        &lt;td&gt; &lt;/td&gt;        &lt;td&gt; &lt;/td&gt;        &lt;td&gt; &lt;/td&gt;        &lt;td&gt; &lt;/td&gt;        &lt;td&gt; &lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;h2&gt;Conclusions&lt;/h2&gt;  &lt;p&gt;There are two main conclusions I found from this testing:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;In IIS7 integrated pipeline, running with no page extensions makes showed no measurable difference in performance &lt;/li&gt;    &lt;li&gt;The Url Master module showed better performance than the standard DotNetNuke Url Rewriter/Friendly Url Provider &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;These are interesting results for me, and I may expand this testing to cover different scenarios such as an IIS6 server, or to greatly increase the sample size of the requests (I’m sure a statistician would scoff at my sample size of 7).  However, they are pleasing for me as I do spend a lot of time performance optimising code and figuring out ways to make it run faster, given that the Url Master code runs every single time a page is requested in DotNetNuke.&lt;/p&gt;  &lt;p&gt;If you see an obvious error, or repeat this testing and find a different result, please let me know via the comments.&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/88/Comparing-Url-Rewriting-performance-with-DotNetNuke-and-Url-Master-with-no-aspx-extensions</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/88/Comparing-Url-Rewriting-performance-with-DotNetNuke-and-Url-Master-with-no-aspx-extensions#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/88/Comparing-Url-Rewriting-performance-with-DotNetNuke-and-Url-Master-with-no-aspx-extensions</guid>
      <pubDate>Fri, 21 May 2010 07:13:07 GMT</pubDate>
      <slash:comments>13</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=88</trackback:ping>
    </item>
    <item>
      <title>Simple fix for Radio Button controls in an ASP.NET Repeater using jQuery</title>
      <description>&lt;p&gt;I’ve come across this problem a few times, and have usually just worked my way around it.&lt;/p&gt;  &lt;p&gt;The problem is when you want to create a list of Radio Buttons to display on a page, and you need to show these with other data, using an ASP.NET repeater (or DataList, or DataGrid).&lt;/p&gt;  &lt;p&gt;Here’s what your code might look like:&lt;/p&gt;  &lt;p&gt;&lt;asp:Repeater id=”rptValues” runat=”server”&gt;&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;ItemTemplate&gt;&lt;/p&gt;    &lt;p&gt;&lt;div&gt;&lt;/p&gt;    &lt;p&gt;&lt;asp:Label id=”lblValue” runat=”server” Text=”Value” /&gt;&lt;/p&gt;    &lt;p&gt;&lt;asp:RadioButton id=”optValue” runat=”server” Name=”options” /&gt;&lt;/p&gt;    &lt;p&gt;&lt;asp:TextBox id=”txtValue” runat=”server” /&gt;&lt;/p&gt;    &lt;p&gt;&lt;/div&gt;&lt;/p&gt;    &lt;p&gt;&lt;/ItemTemplate&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;&lt;/asp:Repeater&gt;&lt;/p&gt;  &lt;p&gt;If you run a DataBind to show values for this repeater, the Html will end up something like this:&lt;/p&gt;  &lt;pre&gt;&lt;div&gt; &lt;br /&gt;    &lt;span id="rptValues_ctl01_lblValue"&gt;One&lt;/span&gt; &lt;br /&gt;    &lt;input id="rptValues_ctl01_optValue" type="radio" value="optValue" &lt;br /&gt;          name="rptValues$ctl01$options" /&gt; &lt;br /&gt;    &lt;input id="rptValues_ctl01_txtValue" type="text" value="One" &lt;br /&gt;          name="rptValues$ctl01$txtValue" /&gt; &lt;br /&gt;&lt;/div&gt; &lt;br /&gt;&lt;div&gt; &lt;br /&gt;    &lt;span id="rptValues_ctl02_lblValue"&gt;Two&lt;/span&gt; &lt;br /&gt;    &lt;input id="rptValues_ctl02_optValue" type="radio" value="optValue" &lt;br /&gt;          name="rptValues$ctl02$options" /&gt; &lt;br /&gt;    &lt;input id="rptValeus_ctl02_txtValue" type="text" value="Two" &lt;br /&gt;          name="rptValues$ctl02$txtValue" /&gt; &lt;br /&gt;&lt;/div&gt;&lt;/pre&gt;

&lt;p style="font-size: smaller"&gt;(Note I haven’t shown the ‘code behind’ here, just take it that I have bound to a string list which consists of ‘one’ and ‘two’)&lt;/p&gt;

&lt;p&gt;Because the two ‘radio’ inputs have a different ‘name’ attribute, then they will act independently of each other, and you’ll be able to select all of them in the page.  The ASP.NET databinding code does this as a standard manner of treating the ‘name’ attribute.  Here’s what the above Html will display:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.ifinity.com.au/Portals/0/images/SimplefixforRadio.NETRepeaterusingjQuery_82B6/aspnet_radio_buttons_repeater.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="aspnet_radio_buttons_repeater" border="0" alt="aspnet_radio_buttons_repeater" src="/Portals/0/images/SimplefixforRadio.NETRepeaterusingjQuery_82B6/aspnet_radio_buttons_repeater_thumb.jpg" width="244" height="183" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Note that both of the options are selected : most users would be completely flummoxed by that one and be frantically clicking back, undo, searching for the ‘help’ button or probably even restarting their computer thinking it was their fault.  None of these actions are what you want to encourage.&lt;/p&gt;

&lt;p&gt;You can’t fix this by changing the name value in the code-behind, it’s a bug/feature of ASP.NET.  Trust me, I’ve done the research and legwork on this one for you.  You’ll find some nasty fixes floating around on MSDN sites, but they often don’t work or are very fiddly, inefficient and fragile.&lt;/p&gt;

&lt;p&gt;In the past I have laboured around this by using different input structures and types, but it occurred to me that jQuery offers the simplest, most elegant solution in a couple of lines:&lt;/p&gt;

&lt;p&gt;jQuery("[name$='$optValue']").attr("name",jQuery("[name$='$optValue']").attr("name"));&lt;/p&gt;

&lt;p&gt;jQuery("[name$='$optValue]").click(function (){
  &lt;br /&gt;                //set name for all to name of clicked

  &lt;br /&gt;                jQuery("[name$='$optValue]").attr("name", this.attr("name"));

  &lt;br /&gt;            });&lt;/p&gt;

&lt;p&gt;Of course, this assumes that you have the jQuery library already reference for the page.  I’ve used the long-form notation of jQuery instead of $() – it makes no difference.  What the first line does is select all of the inputs on the page which end with ‘optValue’ – which is all the ‘optValue’ items in the ASP.NET repeater.  It then changes the ‘name’ attribute to first value found for all the ‘optValue’ elements.  The attr(“name”) function (used here in ‘get’ format) always returns the first in the list.  So all the option buttons get the same ‘name’ attribute in the Html, which allows the select to work correctly.&lt;/p&gt;

&lt;p&gt;If you just need this to work like a radio button, that’s all you need to do.  However, if you need to read the selection value in some postback-linked code, the optValue.Checked value will always equal ‘true’ for the first value, and ‘false’ for the others, regardless of which item in the list is actually selected.  This is related to the way that ASP.NET does the viewstate calculations to preserve the values of the page controls.  Whichever item in the option control group has a name which matches the id value will be selected as true.  This is a problem, but it’s possible to use this strange feature to work for you instead of against you.&lt;/p&gt;

&lt;p&gt;The second line (or block if you like) attaches a jQuery click event handler to the option button.  What this does is set the &lt;em&gt;name&lt;/em&gt; attribute of all of the selected option buttons, the same as the initial line of code does.  However, in this case, it sets the &lt;em&gt;name&lt;/em&gt; attribute to the value of the clicked item.  Because ASP.NET uses the match between the &lt;em&gt;ID&lt;/em&gt; value and the &lt;em&gt;name&lt;/em&gt; attribute to determine if an item is checked, this means you can check the value of optValue.Checked, and it will be true for the correct item.&lt;/p&gt;

&lt;p&gt;To use this script, just include it either in a javascript include, or just insert it directly into the page between &lt;script&gt; elements.&lt;/p&gt;

&lt;p&gt;Once that is done, all the option input controls belong to the same group, and you’ll only be able to select one at a time, just the way it should be.&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/EntryId/87/Simple-fix-for-Radio-Button-controls-in-an-ASP-NET-Repeater-using-jQuery</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/EntryId/87/Simple-fix-for-Radio-Button-controls-in-an-ASP-NET-Repeater-using-jQuery#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/EntryId/87/Simple-fix-for-Radio-Button-controls-in-an-ASP-NET-Repeater-using-jQuery</guid>
      <pubDate>Mon, 12 Apr 2010 23:26:59 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=87</trackback:ping>
    </item>
  </channel>
</rss>