﻿<?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>Wed, 07 Jan 2009 13:28:33 GMT</pubDate>
    <lastBuildDate>Wed, 07 Jan 2009 13:28:33 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 3.5.0.19041</generator>
    <item>
      <title>Setting the Favourite Icon in a DotNetNuke Portal</title>
      <description>&lt;p&gt;I've had this post half-written for a while, but I saw someone asking the question on the DNN forums today, so I thought I should finish it and post it for everyone to read.  &lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;Note : Where I write from, 'Favorite' is spelled with a 'u', so that's the standard I'll stick to in this post.&lt;/font&gt;&lt;/p&gt; &lt;p&gt;Since about DotNetNuke 4.8 or so (correct me where I'm wrong) DNN outputs a Favourite icon for your specified portal.  If there's no FavIcon, it will generate the standard DNN cog/wheel icon thing in it's place.  Thus you have many websites on the internet with the DNN icon instead of their own.&lt;/p&gt; &lt;p&gt;Updating this for your site is dead simple, and will take under 5 minutes.  Here's what you need to do:&lt;/p&gt; &lt;h2&gt;1) Locate your Icon, and get a standard JPEG, GIF or PNG file.&lt;/h2&gt; &lt;p&gt;Sounds simple, but it's not always.  Ideally you should come up with some sort of image that is square in shape.  I use the little stylised 'i' from the iFinity logo for my site : you could do something similar with yours.   &lt;/p&gt; &lt;p&gt;You should end up with a square JPEG, GIF or PNG file with just the image that will become your Favourite icon.&lt;/p&gt; &lt;p&gt;Note that you don't have to worry about squeezing onto a 32x32 pixel canvas, just do it about 100x100 or whatever feels comfortable to you.  Jot down where you saved the file so you can refer back to it in step 2.&lt;/p&gt; &lt;p&gt;Here's mine, after I copy / pasted a square selection from my standard logo image.  I just used a simple graphics editor : you can do this in MS paint if you like.  &lt;/p&gt; &lt;p&gt;&lt;a href="http://www.ifinity.com.au/portals/0/images/SettingtheFavouriteIconinaDotNetNukePort_D502/favicon.gif"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="87" alt="favicon" src="/portals/0/images/SettingtheFavouriteIconinaDotNetNukePort_D502/favicon_thumb.gif" width="87" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;As a tip (and this applies to all icon files) I always try and fill the size of the image close to the border of the canvas. I find that this always makes a more pleasing icon file.  This is because they're pretty small, so you want to maximise the image size.&lt;/p&gt; &lt;h2&gt;2) Create your Favourite Icon, using a web service&lt;/h2&gt; &lt;p&gt;Most people don't have an .ico file editor on their system.  I do, but it's a pain to use and probably a bit like a scalpel, in that when it's used by a professional yields good results : the rest of us tend to make a mess.  A simple graphics program is much easier to use, and it's easier to work on a bigger scale.&lt;/p&gt; &lt;p&gt;I use the favourite icon service at &lt;a title="http://www.html-kit.com/favicon/" href="http://www.html-kit.com/favicon/"&gt;http://www.html-kit.com/favicon/&lt;/a&gt; I just found this through Google; without doubt there will be other services like it.&lt;/p&gt; &lt;p&gt;For the above linked site, you just click the 'browse' button on the page, and select your chosen icon image (that you created in step 1) and then click on 'Generate Favicon.ico'.&lt;/p&gt; &lt;p&gt;You will be redirected to a new page, which will show an example of your favicon in a browser.  You should also see a button which says 'Download FavIcon'.  Click this and download your favicon package to your computer.&lt;/p&gt; &lt;h2&gt;3) Pick the right file&lt;/h2&gt; &lt;p&gt;You will either (depending on your browser settings) download the zip file to your computer, or the zip file will open in your zip program.&lt;/p&gt; &lt;p&gt;Inside this Zip file, you'll see the following files:&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.ifinity.com.au/portals/0/images/SettingtheFavouriteIconinaDotNetNukePort_D502/favicon_zip.jpg"&gt;&lt;img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="265" alt="favicon_zip" src="/portals/0/images/SettingtheFavouriteIconinaDotNetNukePort_D502/favicon_zip_thumb.jpg" width="453" border="0"&gt;&lt;/a&gt; &lt;/p&gt; &lt;p&gt;You're going to extract the favorite icon file out to your computer somewhere.  If you've got funky colours all over the place, go ahead and choose the 'favicon.ico'.  If you're like me and like a simpler, transparent background icon, then choose the 'transparent.ico'.  Use the Zip program extract feature and put the file somewhere where you can find it.&lt;/p&gt; &lt;p&gt;If you chose the 'transparent.ico', rename the file to 'favicon.ico'.&lt;/p&gt; &lt;h2&gt;4) Upload the favicon.ico to your portal&lt;/h2&gt; &lt;p&gt;If you have host access to your portal, then first go into your 'Host-&gt;Host Settings' page.  Scroll down to the 'Other Settings' section, and expand it.  Then, in the 'File Upload Extensions' box, add '.ico' to the list.  Otherwise you can't upload your icon file using DNN.&lt;/p&gt; &lt;p&gt;If you either don't have host access, or don't want to add .ico to the list, then use the FTP program of your choice, and FTP the favicon.ico file to the /portals/_n_/ directory of your site, where _n_ is either the portal ID or the directory name of your portal home directory.&lt;/p&gt; &lt;p&gt;If you have updated your host settings permission to upload .ico files, then go to the 'Admin-&gt;Files' page.  Make sure you have 'Portal Root' selected, then click on 'Upload'.  Browse to your .ico file, then click on 'Upload File'.  This will load the favicon.ico file into your portal root directory.&lt;/p&gt; &lt;h2&gt;5) Admire your Favicon&lt;/h2&gt; &lt;p&gt;That's all you have to do.  DNN will take care of the rest.  You may have to do one of the following to get your Favicon to appear:&lt;/p&gt; &lt;p&gt;1) do a 'hard' refresh of the page (ctl+F5)&lt;/p&gt; &lt;p&gt;2) close your browser and open again&lt;/p&gt; &lt;p&gt;3) clear out your browser cache and open the site again&lt;/p&gt; &lt;p&gt;4) turn off your computer and start it again&lt;/p&gt; &lt;p&gt;5) reinstall your operating system &lt;/p&gt; &lt;p&gt;Of course, I'm just kidding on item (5).  You should only need to apply the latest 10 security patches. No, kidding again!&lt;/p&gt; &lt;p&gt;Seriously though, for reasons beyond my desire to find out, sometimes it can take a bit of messing about to get a favourite icon to appear once your browser has cached a previous version.  The best way is to ask someone else to browse the site and get them to tell you if the icon appeared correctly.&lt;/p&gt; &lt;h2&gt;Did that Help?&lt;/h2&gt; &lt;p&gt;If you've found a problem in my instructions or would like to add more, please use the comments field below.&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/53/Setting-the-Favourite-Icon-in-a-DotNetNuke-Portal/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/53/Setting-the-Favourite-Icon-in-a-DotNetNuke-Portal/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/53/Setting-the-Favourite-Icon-in-a-DotNetNuke-Portal/</guid>
      <pubDate>Fri, 28 Nov 2008 05:10:16 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=53</trackback:ping>
    </item>
    <item>
      <title>Creating PortalSettings Instance running in a DotNetNuke Schedule Item</title>
      <description>&lt;p&gt;A couple of weeks ago I posted &lt;a href="http://www.dotnetnuke.com/Community/Forums/tabid/795/forumid/108/postid/263262/scope/posts/Default.aspx"&gt;some advice on the DotNetNuke forum regarding the use of the 'NavigateURL'&lt;/a&gt; call.  Through my work on Friendly Url Providers I've become a bit of a walking reference for this particular corner of the DNN framework.  So I posted a short description on all the different overloads for the NavigateUrl call.&lt;/p&gt; &lt;p&gt;In it, I posted the cheerful snippet:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;"[Same as the other NavigateUrl overloads] but allows you to pass in your own portalSettings instance.  This allows you to define different portal options, so you can either change the current language, change the portal alias, or even generate urls for a different portal altogether.  All overloads without 'portalSettings' produce Urls for the current portal, with all the current settings like the current language, current portal alias and more.  You would also supply the 'portalSettings' value for use when the portalSettings is not in the current context, such as in DotNetNuke scheduled events - the current portal settings is only created and stored in the context.items when the request is as a result of a 'user' request to the website.  Scheduled Items can be triggered by a timer and as such don't always have the 'portalSettings' instanced.  An example would be generating links for an automated email created in a scheduled task."&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The reason I posted this much information specifically about scheduled tasks, is that I've built a few now, and I know that using the DotNetNuke framework in 'scheduled task' mode can be a bit tricky.  The reason is that when a scheduled task is kicked off, it's done in a different application thread to the main asp.net application, and as such, many of the Http items that the DNN framework takes for granted are missing.  There's just one problem with this detailed advice, as we will find out, it's total hogwash and doesn't work.&lt;/p&gt; &lt;h2&gt;What really happens when you provide your own PortalSettings&lt;/h2&gt; &lt;p&gt;In the last day or so, I've been working on a DNN schedule item that does exactly what I posted in my forum response : generates an email to send to users, and in that email is links to pages within the site.  Of course, as any good DNN developer knows, to get Page Urls, you use the DotNetNuke.Common.Globals.NavigateUrl() call.  And, forgetting my own advice, the first thing I tripped up on was a 'object reference not set' error.  A quick trace, a short slap to the forehead - of course! No Context.Items["PortalSettings"] instance, because there's no HttpContext.Current instance in a DNN schedule item thread.    Incidentally, the check in the HttpContext for the PortalSettings call is this method, in 'PortalController.vb'&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Public Shared Function GetCurrentPortalSettings() As PortalSettings&lt;br&gt;     Return CType(HttpContext.Current.Items("PortalSettings"), PortalSettings)&lt;br&gt;End Function&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Note that this method doesn't first check to see if HttpContext.Current is a valid reference - it's just assumed that it will be.&lt;/p&gt; &lt;p&gt;So, I dutifully took my own advice and came up with a new PortalSettings instance- easy peasy, I thought, I'll just grab the first portal alias in the list, and create a new portal settings object like this:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;PortalSettings ps = new PortalSettings(-1, alias.HttpAlias);&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Whoops! That doesn't work either.  Why?  Because, believe it or not, one of the things in the Portal Settings constructor actually seems to check the Current Portal Settings.  This wouldn't be so bad (as it copes with 'null' as a return value), except that it assumes that the HttpContext.Current will never be null.&lt;/p&gt; &lt;h2&gt;Back to Square One with the Portal Settings Constructor&lt;/h2&gt; &lt;p&gt;So I sat down and wrote a whole procedure which replicated the constructor for the portal settings object, only in C# to match the project I was working on.  This worked OK, after I removed the code that expected the HttpContext.Current to be a valid value.  Armed with my new PortalSettings instance, I then called the NavigateUrl() call overload that allows you to pass in your own PortalSettings instance.  I sat back, ran my code and waited for the output of a set of perfectly formed Urls.&lt;/p&gt; &lt;p&gt;I didn't have to wait long, as I got the long and wordy stream of Exception text back instead.  Seems as though, even if you supply the PortalSettings object into the NavigateUrl overload, one of the first things it does is check the 'GetEnabledLocales' method, and the first line in that call is ... you guessed it 'PortalController.GetCurrentPortalSettings()' - which, as shown above, checks the HttpContext for the current portal settings.  Now this is a bit of a silly situation - providing an overload to supply your own PortalSettings instance, and then checking the current Context for a PortalSettings instance.  I'll probably log this one in Gemini to fix.&lt;/p&gt; &lt;blockquote style="border-right: #efefef 1px solid; padding-right: 4px; border-top: #efefef 1px solid; padding-left: 4px; padding-bottom: 4px; margin: 4px; border-left: #efefef 1px solid; padding-top: 4px; border-bottom: #efefef 1px solid"&gt; &lt;p align="justify"&gt;&lt;font face="Tahoma" size="2"&gt;&lt;u&gt;Interesting Sidebar to this Discussion&lt;/u&gt;&lt;/font&gt;&lt;/p&gt; &lt;p align="justify"&gt;&lt;font face="Tahoma" size="2"&gt;I often get people reporting 'object not set' reference errors when using various DNN modules and the Url Master / iFinity Friendly Url Provider modules.    Normally, this shows up in a stack trace as eminating from the 'GetEnabledLocales' procedure, like this:&lt;/font&gt;&lt;/p&gt; &lt;p align="justify"&gt;&lt;font face="Tahoma" size="2"&gt;System.NullReferenceException: Object reference not set to an instance of an object. at DotNetNuke.Entities.Portals.PortalController.GetCurrentPortalSettings() &lt;/font&gt;&lt;/p&gt; &lt;p align="justify"&gt;&lt;font face="Tahoma" size="2"&gt;The reason for this is that it is the DotNetNuke UrlRewriter that is responsible for adding the current PortalSettings object into the HttpContext.Current.Items collection.  The Url Master / Friendly Url Provider modules have a set of filters designed to stop requests at different points of processing.  The 'ignoreRegex' filter means the UrlRewriter ignores the request completely, while the 'doNotRewriteRegex' ensures that the request is not rewritten, but still allows the PortalSettings to be created and added to the context.  So if you've got this error, what you want to do is craft your 'ignoreRegex' to let the request through, but the 'doNotRewriteRegex' to block it.  In between these two filters is the code to identify the portal and store the PortalSettings object in the HttpContext.&lt;/font&gt;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;So, getting back to my project... what to do now?  I still need to call 'NavigateUrl' without a HttpContext.   I decided to go back to Square Zero and mock up the HttpContext completely, the same as I have done in my series of unit testing DotNetNuke modules.&lt;/p&gt; &lt;h2&gt;Forward to Square Two with the PortalSettings Constructor&lt;/h2&gt; &lt;p&gt;(I've always assumed it's square two that you move on to from square one, not circle one - some sort of integer over shape preference, I presume)&lt;/p&gt; &lt;p&gt;To fix the missing HttpContext problem without butchering up the DNN Core with custom fixes, I simply added a butchered up mock HttpContext constructor, in which I would stash my created portal settings.  This creates a fake HttpContext object, stores the PortalSettings in the items collection, and the rest of the DNN Framework appears none the wiser.  My Schedule Program now generates Emails with the correct Urls embedded, and I've got a bit of custom portal settings code to use next time I head up this pathway.&lt;/p&gt; &lt;p&gt;Here's the code.  Don't use it unless you know what you're using it for, and if you're working on a high load server, probably best to make sure the threads are being disposed of correctly.  Please don't ask me for a VB version either : go and find a C#/VB.NET Converter.  The code is taken from the DNN Core, so all the usual legal messages in the DNN code files applies.&lt;/p&gt; &lt;blockquote style="border-right: #dfdfdf 1px solid; padding-right: 5px; border-top: #dfdfdf 1px solid; padding-left: 5px; padding-bottom: 5px; margin: 5px; border-left: #dfdfdf 1px solid; padding-top: 5px; border-bottom: #dfdfdf 1px solid; background-color: #efefef"&gt; &lt;p&gt;public static DotNetNuke.Entities.Portals.PortalSettings CreateNewPortalSettings(int portalId)&lt;br&gt;{&lt;br&gt;    //new settings object&lt;br&gt;    PortalSettings ps = new PortalSettings();&lt;br&gt;    //controller instances&lt;br&gt;    PortalController pc = new PortalController();&lt;br&gt;    TabController tc = new TabController();&lt;br&gt;    PortalAliasController pac = new PortalAliasController();  &lt;p&gt;    //get the first portal alias found to be used as the current portal alias&lt;br&gt;    PortalAliasInfo portalAlias = null;&lt;br&gt;    PortalAliasCollection aliases = pac.GetPortalAliasByPortalID(portalId);&lt;br&gt;    string aliasKey = "";&lt;br&gt;    if (aliases != null &amp;&amp; aliases.Count &gt; 0)&lt;br&gt;    {&lt;br&gt;        //get the first portal alias in the list and use that&lt;br&gt;        foreach (string key in aliases.Keys)&lt;br&gt;        {&lt;br&gt;            aliasKey = key;&lt;br&gt;            portalAlias = aliases[key];&lt;br&gt;            break;&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;    //get the portal and copy across the settings&lt;br&gt;    PortalInfo portal = pc.GetPortal(portalId);&lt;br&gt;    if (portal != null)&lt;br&gt;    {&lt;br&gt;        ps.PortalAlias = portalAlias;&lt;br&gt;        ps.PortalId = portal.PortalID;&lt;br&gt;        ps.PortalName = portal.PortalName;&lt;br&gt;        ps.LogoFile = portal.LogoFile;&lt;br&gt;        ps.FooterText = portal.FooterText;&lt;br&gt;        ps.ExpiryDate = portal.ExpiryDate;&lt;br&gt;        ps.UserRegistration = portal.UserRegistration;&lt;br&gt;        ps.BannerAdvertising = portal.BannerAdvertising;&lt;br&gt;        ps.Currency = portal.Currency;&lt;br&gt;        ps.AdministratorId = portal.AdministratorId;&lt;br&gt;        ps.Email = portal.Email;&lt;br&gt;        ps.HostFee = portal.HostFee;&lt;br&gt;        ps.HostSpace = portal.HostSpace;&lt;br&gt;        ps.PageQuota = portal.PageQuota;&lt;br&gt;        ps.UserQuota = portal.UserQuota;&lt;br&gt;        ps.AdministratorRoleId = portal.AdministratorRoleId;&lt;br&gt;        ps.AdministratorRoleName = portal.AdministratorRoleName;&lt;br&gt;        ps.RegisteredRoleId = portal.RegisteredRoleId;&lt;br&gt;        ps.RegisteredRoleName = portal.RegisteredRoleName;&lt;br&gt;        ps.Description = portal.Description;&lt;br&gt;        ps.KeyWords = portal.KeyWords;&lt;br&gt;        ps.BackgroundFile = portal.BackgroundFile;&lt;br&gt;        ps.GUID = portal.GUID;&lt;br&gt;        ps.SiteLogHistory = portal.SiteLogHistory;&lt;br&gt;        ps.AdminTabId = portal.AdminTabId;&lt;br&gt;        ps.SuperTabId = portal.SuperTabId;&lt;br&gt;        ps.SplashTabId = portal.SplashTabId;&lt;br&gt;        ps.HomeTabId = portal.HomeTabId;&lt;br&gt;        ps.LoginTabId = portal.LoginTabId;&lt;br&gt;        ps.UserTabId = portal.UserTabId;&lt;br&gt;        ps.DefaultLanguage = portal.DefaultLanguage;&lt;br&gt;        ps.TimeZoneOffset = portal.TimeZoneOffset;&lt;br&gt;        ps.HomeDirectory = portal.HomeDirectory;&lt;br&gt;        ps.Version = portal.Version;&lt;br&gt;        ps.AdminSkin = SkinController.GetSkin(SkinInfo.RootSkin, portalId, SkinType.Admin);&lt;br&gt;        if (ps.AdminSkin == null) &lt;br&gt;        {&lt;br&gt;            ps.AdminSkin = SkinController.GetSkin(SkinInfo.RootSkin, DotNetNuke.Common.Utilities.Null.NullInteger, SkinType.Admin);&lt;br&gt;        }&lt;br&gt;        ps.PortalSkin = SkinController.GetSkin(SkinInfo.RootSkin, portalId, SkinType.Portal);&lt;br&gt;        if (ps.PortalSkin == null) &lt;br&gt;        {&lt;br&gt;            ps.PortalSkin = SkinController.GetSkin(SkinInfo.RootSkin, DotNetNuke.Common.Utilities.Null.NullInteger, SkinType.Portal);&lt;br&gt;        }&lt;br&gt;        ps.AdminContainer = SkinController.GetSkin(SkinInfo.RootContainer, portalId, SkinType.Admin);&lt;br&gt;        if (ps.AdminContainer == null) &lt;br&gt;        {&lt;br&gt;            ps.AdminContainer = SkinController.GetSkin(SkinInfo.RootContainer, DotNetNuke.Common.Utilities.Null.NullInteger, SkinType.Admin);&lt;br&gt;        }&lt;br&gt;        ps.PortalContainer = SkinController.GetSkin(SkinInfo.RootContainer, portalId, SkinType.Portal);&lt;br&gt;        if (ps.PortalContainer == null) &lt;br&gt;        {&lt;br&gt;            ps.PortalContainer = SkinController.GetSkin(SkinInfo.RootContainer, DotNetNuke.Common.Utilities.Null.NullInteger, SkinType.Portal);&lt;br&gt;        }&lt;br&gt;        ps.Pages = portal.Pages;&lt;br&gt;        ps.Users = portal.Users;&lt;br&gt;        // set custom properties&lt;br&gt;        if (DotNetNuke.Common.Utilities.Null.IsNull(ps.HostSpace)) &lt;br&gt;        {&lt;br&gt;            ps.HostSpace = 0;&lt;br&gt;        }&lt;br&gt;        if (DotNetNuke.Common.Utilities.Null.IsNull(ps.DefaultLanguage)) {&lt;br&gt;            ps.DefaultLanguage = DotNetNuke.Services.Localization.Localization.SystemLocale;&lt;br&gt;        }&lt;br&gt;        if (DotNetNuke.Common.Utilities.Null.IsNull(ps.TimeZoneOffset)) {&lt;br&gt;            ps.TimeZoneOffset = DotNetNuke.Services.Localization.Localization.SystemTimeZoneOffset;&lt;br&gt;        }&lt;br&gt;        ps.HomeDirectory = DotNetNuke.Common.Globals.ApplicationPath + "/" + portal.HomeDirectory + "/";&lt;br&gt;        // get application version&lt;br&gt;        string[] arrVersion = DotNetNuke.Common.Assembly.glbAppVersion.Split('.');&lt;br&gt;        int intMajor = 0;&lt;br&gt;        int intMinor = 0;&lt;br&gt;        int intBuild = 0;&lt;br&gt;        Int32.TryParse(arrVersion[0], out intMajor);&lt;br&gt;        Int32.TryParse(arrVersion[1], out intMinor);&lt;br&gt;        Int32.TryParse(arrVersion[2], out intBuild);&lt;br&gt;        ps.Version = intMajor.ToString() + "." + intMinor.ToString() + "." + intBuild.ToString();&lt;br&gt;    }&lt;br&gt;    //Add each portal Tab to DekstopTabs&lt;br&gt;    TabInfo portalTab = default(TabInfo);&lt;br&gt;    ps.DesktopTabs = new ArrayList();&lt;br&gt;    bool first = true;&lt;br&gt;    foreach (KeyValuePair&lt;int, TabInfo&gt; tabPair in tc.GetTabsByPortal(ps.PortalId)) &lt;br&gt;    {&lt;br&gt;        // clone the tab object ( to avoid creating an object reference to the data cache )&lt;br&gt;        portalTab = tabPair.Value.Clone();&lt;br&gt;        // set custom properties&lt;br&gt;        if (portalTab.TabOrder == 0) &lt;br&gt;        {&lt;br&gt;            portalTab.TabOrder = 999;&lt;br&gt;        }&lt;br&gt;        if (DotNetNuke.Common.Utilities.Null.IsNull(portalTab.StartDate)) &lt;br&gt;        {&lt;br&gt;            portalTab.StartDate = System.DateTime.MinValue;&lt;br&gt;        }&lt;br&gt;        if (DotNetNuke.Common.Utilities.Null.IsNull(portalTab.EndDate)) &lt;br&gt;        {&lt;br&gt;            portalTab.EndDate = System.DateTime.MaxValue;&lt;br&gt;        }&lt;br&gt;        ps.DesktopTabs.Add(portalTab);  &lt;p&gt;        //assign the first 'normal' tab as the active tab - could be the home tab, if it &lt;br&gt;        //still exists, or it will be after the admin tab(s)&lt;br&gt;        if (first &amp;&amp; (portalTab.TabID == portal.HomeTabId || portalTab.TabID &gt; portal.AdminTabId))&lt;br&gt;        {&lt;br&gt;            ps.ActiveTab = portalTab;&lt;br&gt;            first = false;&lt;br&gt;        }&lt;br&gt;    }&lt;br&gt;    //last gasp chance in case active tab was not set&lt;br&gt;    if (ps.ActiveTab == null) ps.ActiveTab = portalTab;&lt;br&gt;    //Add each host Tab to DesktopTabs&lt;br&gt;    TabInfo hostTab = default(TabInfo);&lt;br&gt;    foreach (KeyValuePair&lt;int, TabInfo&gt; tabPair in tc.GetTabsByPortal(DotNetNuke.Common.Utilities.Null.NullInteger)) &lt;br&gt;    {&lt;br&gt;        // clone the tab object ( to avoid creating an object reference to the data cache )&lt;br&gt;        hostTab = tabPair.Value.Clone();&lt;br&gt;        hostTab.PortalID = ps.PortalId;&lt;br&gt;        hostTab.StartDate = System.DateTime.MinValue;&lt;br&gt;        hostTab.EndDate = System.DateTime.MaxValue;&lt;br&gt;        ps.DesktopTabs.Add(hostTab);&lt;br&gt;    }  &lt;p&gt;    //now add the portal settings to the httpContext&lt;br&gt;    if (System.Web.HttpContext.Current == null)&lt;br&gt;    {&lt;br&gt;        //if there is no HttpContext, then mock one up by creating a fake WorkerRequest&lt;br&gt;        string appVirtualDir = DotNetNuke.Common.Globals.ApplicationPath;&lt;br&gt;        string appPhysicalDir = AppDomain.CurrentDomain.BaseDirectory;&lt;br&gt;        string page = ps.PortalAlias.HTTPAlias;&lt;br&gt;        string query = string.Empty;&lt;br&gt;        System.IO.TextWriter output = null;&lt;br&gt;        //create a dummy simple worker request&lt;br&gt;        System.Web.Hosting.SimpleWorkerRequest workerRequest = new System.Web.Hosting.SimpleWorkerRequest(page, query, output);&lt;br&gt;        System.Web.HttpContext.Current = new System.Web.HttpContext(workerRequest);&lt;br&gt;    }&lt;br&gt;    //stash the portalSettings in the Context Items, where the rest of the DNN Code expects it to be&lt;br&gt;    System.Web.HttpContext.Current.Items.Add("PortalSettings", ps);&lt;br&gt;    return ps;&lt;br&gt;}&lt;/p&gt;&lt;/blockquote&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/52/Creating-PortalSettings-Instance-running-in-a-DotNetNuke-Schedule-Item/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/52/Creating-PortalSettings-Instance-running-in-a-DotNetNuke-Schedule-Item/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/52/Creating-PortalSettings-Instance-running-in-a-DotNetNuke-Schedule-Item/</guid>
      <pubDate>Thu, 20 Nov 2008 06:01:18 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=52</trackback:ping>
    </item>
    <item>
      <title>Blog Posting with Windows Live Writer and DNN Blog 3.5</title>
      <description>&lt;p&gt;The ease at which you can post to a blog with Windows Live Writer (WLW) would have seemed like science fiction a couple of years ago, yet here I am doing it right now.   Except that, in years gone by, you could easily edit Html in a WYSIWYG editor and quickly FTP Up the results.  The more things change, the more they stay the same.&lt;/p&gt;  &lt;p&gt;I thought I'd post a quick entry in case people are running Blog 3.5, Url Master and would like to use WLW.  I found that in configuring the Post Url for WLW, I had a few problems to sort out.&lt;/p&gt;  &lt;p&gt;If you haven't yet set up your WLW to post to your blog, it's really easy.  Here's the steps:&lt;/p&gt;  &lt;p&gt;1) Start WLW, and progress through the first couple of steps, indicating you already have a blog, and that it's with 'Another Blog Service'.&lt;/p&gt;  &lt;p&gt;2) Enter your blog Url and DNN username and password that you blog under&lt;/p&gt;  &lt;p&gt;3) Select 'MetaWeblog API' as the type of weblog&lt;/p&gt;  &lt;p&gt;4) Enter your Blog Posting Url : this is pretty easy to get.  Its &lt;a href="http://www.yourdomain.com/DesktopModules/Blog/blogpost.ashx?tabid=nn"&gt;http://www.yourdomain.com/DesktopModules/Blog/blogpost.ashx?tabid=nn&lt;/a&gt; where nn = the tabId your blog lives on.  You can get this from the 'Blog Settings' option of the Blog module if you don't know your tabid.&lt;/p&gt;  &lt;p&gt;Once you've done all that, there's one more step you need to do if you've got Url Master installed:&lt;/p&gt;  &lt;p&gt;5) Go to the 'Friendly Url Settings' screen, and scroll down to the 'Advanced Regex Settings' section.  Expand this, and in the 'doNotRedirectRegex' field, add this to the end:&lt;/p&gt;  &lt;p&gt;|/DesktopModules/&lt;/p&gt;  &lt;p&gt;If you don't already have anything in this field, you don't need the leading '|' character, you'd just enter /DesktopModules/.&lt;/p&gt;  &lt;p&gt;This will prevent the blogpost.ashx handler from getting a 301 redirect - this happens because the Url contains the 'tabId' key, so the Url Master code believes it to be of the 'old' unfriendly Url format, and tries to come up with a friendlier version.&lt;/p&gt;  &lt;p&gt;The same instructions will apply to those using the iFinity Friendly Url Provider : just put the aforementioned value into the 'doNotRedirectRegex' attribute in your web.config file.&lt;/p&gt;  &lt;p&gt;After doing this, you should be good to blog!&lt;/p&gt;  &lt;p&gt;Now that I've got this running, I'll have to prioritise the Feature Request to have the Tagger module also talk to WLW.   It's a feature request I receive often enough, so I'll look into it.&lt;/p&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/51/Blog-Posting-with-Windows-Live-Writer-and-DNN-Blog-3-5/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/51/Blog-Posting-with-Windows-Live-Writer-and-DNN-Blog-3-5/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/51/Blog-Posting-with-Windows-Live-Writer-and-DNN-Blog-3-5/</guid>
      <pubDate>Thu, 13 Nov 2008 06:10:50 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=51</trackback:ping>
    </item>
    <item>
      <title>Installing the New DotNetNuke Blog Module version 3.5</title>
      <description>&lt;p&gt;I've been waiting eagerly for the new Blog module to be released.  Quite a while back, I posted on here how the Blog module developers could make people happy by putting the module title into the Url using the 'page name' functionality of the Friendly Url API.   One of my readers thought it was a good idea and posted it on Gemini, now the results are in.  Here's my experience with the upgrade.&lt;/p&gt;&lt;a href=http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/49/Installing-the-New-DotNetNuke-Blog-Module-version-3-5/&gt;More...&lt;/a&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/49/Installing-the-New-DotNetNuke-Blog-Module-version-3-5/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/49/Installing-the-New-DotNetNuke-Blog-Module-version-3-5/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/49/Installing-the-New-DotNetNuke-Blog-Module-version-3-5/</guid>
      <pubDate>Mon, 10 Nov 2008 01:51:00 GMT</pubDate>
      <slash:comments>7</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=49</trackback:ping>
    </item>
    <item>
      <title>Designing, Structuring and Architecting DotNetNuke® Modules</title>
      <description>&lt;p&gt;I answered a post on the DNN Forum the other day relating to a question about how to go about structuring a custom build DotNetNuke® module.  It's an area probably covered well in various DNN books, but I think it's a question that most experienced developers but first-time DNN module builders ask.  Here's how I recommend you structure and build your  custom DNN modules.&lt;/p&gt;&lt;a href=http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/48/Designing-Structuring-and-Architecting-DotNetNuke-reg-Modules/&gt;More...&lt;/a&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/48/Designing-Structuring-and-Architecting-DotNetNuke-reg-Modules/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/48/Designing-Structuring-and-Architecting-DotNetNuke-reg-Modules/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/48/Designing-Structuring-and-Architecting-DotNetNuke-reg-Modules/</guid>
      <pubDate>Mon, 13 Oct 2008 00:26:00 GMT</pubDate>
      <slash:comments>4</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=48</trackback:ping>
    </item>
    <item>
      <title>Understanding 301 Redirects</title>
      <description>&lt;p&gt;A little while ago, I posted a blog entry as a guest blogger on seablick.com.  I'm putting a link in this blog to that entry, so that anyone searching for it here can find what they are looking for.&lt;/p&gt;&lt;a href=http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/47/Understanding-301-Redirects/&gt;More...&lt;/a&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/47/Understanding-301-Redirects/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/47/Understanding-301-Redirects/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/47/Understanding-301-Redirects/</guid>
      <pubDate>Thu, 09 Oct 2008 23:16:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=47</trackback:ping>
    </item>
    <item>
      <title>Why does Url Rewriting break all my image links?</title>
      <description>&lt;p&gt;Url Rewriting has been known to make sites act strange, with broken image links, missing CSS files and javascrtipt not found errors.  Here's why it happens, how to fix it and how to avoid it in the first place.&lt;/p&gt;&lt;a href=http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/46/Why-does-Url-Rewriting-break-all-my-image-links/&gt;More...&lt;/a&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/46/Why-does-Url-Rewriting-break-all-my-image-links/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/46/Why-does-Url-Rewriting-break-all-my-image-links/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/46/Why-does-Url-Rewriting-break-all-my-image-links/</guid>
      <pubDate>Fri, 22 Aug 2008 04:12:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=46</trackback:ping>
    </item>
    <item>
      <title>301 Redirecting from /default.aspx to the site root - the final word</title>
      <description>&lt;p&gt;Have you got two home pages indexed for your site?  I bet you have.  There are two home pages for most ASP.NET websites - www.domain.com and www.domain.com/default.aspx.  Read on for the final word on this.&lt;/p&gt;&lt;a href=http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/45/301-Redirecting-from-default-aspx-to-the-site-root-the-final-word/&gt;More...&lt;/a&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/45/301-Redirecting-from-default-aspx-to-the-site-root-the-final-word/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/45/301-Redirecting-from-default-aspx-to-the-site-root-the-final-word/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/45/301-Redirecting-from-default-aspx-to-the-site-root-the-final-word/</guid>
      <pubDate>Thu, 14 Aug 2008 02:09:00 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=45</trackback:ping>
    </item>
    <item>
      <title>Google A/B Ad Testing with DotNetNuke websites</title>
      <description>&lt;p&gt;If you're getting serious with your Google Adwords advertising, you should probably be trying out different types of page copy to see which works the best.  Here's a quick guide on how to setup Google Adwords testing in a DNN site.&lt;/p&gt;&lt;a href=http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/44/Google-A-B-Ad-Testing-with-DotNetNuke-websites/&gt;More...&lt;/a&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/44/Google-A-B-Ad-Testing-with-DotNetNuke-websites/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/44/Google-A-B-Ad-Testing-with-DotNetNuke-websites/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/44/Google-A-B-Ad-Testing-with-DotNetNuke-websites/</guid>
      <pubDate>Mon, 28 Jul 2008 01:15:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=44</trackback:ping>
    </item>
    <item>
      <title>Troubleshooting Url Master Installations</title>
      <description>&lt;p&gt;If you've installed the Url Master module, and it's not working exactly as you want, here's some things to try to work out where you're going wrong.&lt;/p&gt;&lt;a href=http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/43/Troubleshooting-Url-Master-Installations/&gt;More...&lt;/a&gt;</description>
      <link>http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/43/Troubleshooting-Url-Master-Installations/</link>
      <author>bchapman@ifinity.com.au</author>
      <comments>http://www.iFinity.com.au/Blog/Technical_Blog/EntryId/43/Troubleshooting-Url-Master-Installations/#Comments</comments>
      <guid isPermaLink="true">http://www.ifinity.com.au/Blog/Technical_Blog/EntryId/43/Troubleshooting-Url-Master-Installations/</guid>
      <pubDate>Fri, 18 Jul 2008 01:15:00 GMT</pubDate>
      <slash:comments>6</slash:comments>
      <trackback:ping>http://www.ifinity.com.au/DesktopModules/Blog/Trackback.aspx?id=43</trackback:ping>
    </item>
  </channel>
</rss>