Migrating From Sitefinity 3: Disqus Comments

This post is part of a series exploring my migration from Sitefinity 3 to 4.4. Some of this information may become obsolete as newer versions are released. Always watch the official Sitefinity website for the latest info.

The final step in migrating this site from Sitefinity 3 was to restore the Disqus comments on my blog. As I mentioned sometime ago, I replaced the Sitefinity comments with Disqus and have used it ever since.

Unfortunately, Disqus uses the Url as the identity key for each discussion. As I’ve mentioned throughout this series of migration posts, I am using the new Sitefinity blog Url format, which means all my comments were lost. Disqus saw the new Urls and assumed these were new discussions.

Disqus Tools

Fortunately, Disqus has you covered with several helpful migration tools of their own for situations just like this.

Disqus-Migration-Tools

There is a Domain Migration Wizard, helpful if you are moving to a different domain. You can also upload a CSV file that manually maps old Urls to the new ones.

The easiest solution by far however has to be the Redirect Crawler. This tool will navigate through the original Disqus Urls and if there is a 301 redirect, update the identity Urls for the discussion so that they transfer to the new Url.

Thanks to the IIS Url Rewrite Module, this is already done, and I simply needed to run the tool and wait for it to crawl my site. Now all my old Disqus discussions have been redirected, and the existing comments are now visible on all my old posts.

Wrapping Up

And with that, my migration is complete! I transferred all my old pages and posts into a brand new theme. I migrated some content to my business site Page Init Solutions. I took advantage of the slick new Blog Url format, using a custom Blogs Provider to take full control of the Url format. I took care of redirecting all the old Urls, and imported all my old Disqus comments.

I hope that anyone else going through this process finds this series helpful, and if you have any questions, you can always consult the Sitefinity Migration Discussion Forum, or feel free to send me your questions as well!

Upgrading From Sitefinity 3: Url Rewriting

This post is part of a series exploring my migration from Sitefinity 3 to 4.4. Some of this information may become obsolete as newer versions are released. Always watch the official Sitefinity website for the latest info.

As part of the migration of my website from Sitefinity 3, I updated both the Url format for pages (now extensionless) and blog posts (also extensionless and different format) for better readability and SEO. This of course would leave a wake of broken links and search results linking to the old Urls.

There are many options available to resolve this, such as developing a custom HttpHandler to intercept the old Urls. Fortunately, there is a fantastic tool that handles all of this for you.

IIS Url Rewrite

IIS Url Rewrite is an extension for IIS that enables a wealth of Url handling features, including the two I needed for my site: Rewriting and Redirecting.

Redirects

As part of my website update, I moved some of the content such as the Sitefinity 3 Toolkit info to my company website Page Init Solutions. So I need to redirect all these requests from this site to that one.

The Url Rewrite module has an option for creating redirects, which you can manage in a friendly GUI for IIS.

IIS-UrlRewrite

You can also manage this directly in the web.config file. Here are some of the redirects I put in place using the module.

 <rewrite>
            <rules>
                <clear />
                <rule name="Redirect rule1 for PageInit">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{PageInit:{REQUEST_URI}}" pattern="(.+)" />
                    </conditions>
                    <action type="Redirect" url="{C:1}" appendQueryString="false" />
                </rule>
            </rules>
            <rewriteMaps>
                <rewriteMap name="PageInit">
                    <add key="/software.aspx" value="http://pageinit.net/software" />
                    <add key="/software/Sitefinity/Sitefinity_Toolkit.aspx" value="http://pageinit.net/software/sitefinity-toolkit" />
                    <add key="/software/jQuery/Banner_Swapper.aspx" value="http://pageinit.net/software/jquery-banner-swapper" />
                    <add key="/software/Sitefinity/Sitefinity_Password_Recovery.aspx" value="http://pageinit.net/software/sitefinity-3-password-recovery-tool" />
                    <add key="/blog.aspx" value="http://www.selarom.net/blog" />
                    <add key="/contact.aspx" value="http://www.selarom.net/contact" />
                </rewriteMap>
            </rewriteMaps>
      </rewrite>

This allowed me to easily map old Urls to new, including the old .aspx extensions for pages. Adding a new redirect is as simple as adding a new entry in the list.

Url Rewriting

The new blog Url format makes for SEO friendly as well as functionally useful Urls. They are, however, starkly different from the original format from Sitefinity 3, and clearly, redirecting every single post individually is not an ideal solution.

Fortunately, the Url Rewrite Module also has excellent support for Url rewriting using Regular Expressions. Using Regex, I was able to easily rewrite the old format of /YYYY-MM-DD/Title to the new /YYYY/MM/DD/Title format now used by Sitefinity. I was even able to rewrite some of the urls for the list of blogs by Tag and Category.

Admittedly, working with Regular Expressions is probably one of my weakest programming skills, and despite what everyone keeps saying on Twitter, it does NOT get easier the more you do it! That being said, here are the Regex rewrites I created for this site. If anyone has suggestions for improving or consolodating them, by all means let me know!

 <rule name="BlogPosts" stopProcessing="true">
                    <match url="^(.*)/([0-9]{4})[-]([0-9]{2})[-]([0-9]{2})/(.*)$" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false" />
                    <action type="Redirect" url="{R:1}/{R:2}/{R:3}/{R:4}/{R:5}" />
                </rule>
                <rule name="BlogYear2Month">
                    <match url="blog\.aspx$" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern="Year=([0-9]{4})" />
                        <add input="##{C:1}##_{QUERY_STRING}" pattern="##([^#]+)##_.*Month=(\d{2})" />
                    </conditions>
                    <action type="Redirect" url="blog/{C:1}/{C:2}" appendQueryString="false"/>
                </rule>
                <rule name="BlogYear1Month">
                    <match url="blog\.aspx$" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern="Year=([0-9]{4})" />
                        <add input="##{C:1}##_{QUERY_STRING}" pattern="##([^#]+)##_.*Month=(\d{1})" />
                    </conditions>
                    <action type="Redirect" url="blog/{C:1}/0{C:2}" appendQueryString="false"/>
                </rule>
                <rule name="BlogYear">
                    <match url="blog\.aspx$" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern="Year=([0-9]{4})" />
                    </conditions>
                    <action type="Redirect" url="blog/{C:1}" appendQueryString="false"/>
                </rule>
                <rule name="BlogTag">
                    <match url="blog\.aspx$" />
                    <conditions>
                        <add input="{QUERY_STRING}" pattern="tag=(.*)" />
                    </conditions>
                    <action type="Redirect" url="/blog/-in-Tags/Tags/{C:1}" appendQueryString="false"/>
                </rule>

Wrapping Up

The IIS Url Rewrite Module is a fantastic tool for ANY website that has a need for rewriting or maintaining Urls, and is highly recommended for anyone attempting to migrate to the latest verion of Sitefinity.

Finally, here are a few resources I found extremely helpful in preparing these rewrites and redirects:

Upgrading From Sitefinity 3: Blog Urls and Providers

I also mentioned in the previous post that although your original Urls for existing pages and content items are preserved, any new published blog posts will fallback to the default format. This also happens to any existing content that you republish.

Upgrading from Sitefinity 3: Extensionless Urls

By default, the Sitefinity Migration tool imports content items and pages with their original urls fully intact. That means all your old urls and SEO remain intact, including the original .aspx extensions from the old website.

Instead of trying to find a way to force Sitefinity to use my old url format, I decided it was much better (not to mention cleaner and more SEO friendly) to have my old urls convert to the new format.

Upgrading From Sitefinity 3 to 4.4

Now that I’ve fixed my issues with Windows Live Writer and Sitefinity, I can finally take some time to talk about the migration process itself, and hope that it will be helpful to anyone else going through the same process.

Sitefinity 4: Null Reference When Editing Templates

I experienced a "duh" moment today while trying to tackle an error I was receiving while playing with the Sitefinity 4 RC (due out later this week!). Whenever I created a template, I’d always get the following error when I tried to edit it:

Object reference not set to an instance of an object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[NullReferenceException: Object reference not set to an instance of an object.]
   Telerik.Sitefinity.Modules.Pages.DraftProxyBase.CreateChildControls(Page page) +1804
   Telerik.Sitefinity.Modules.Pages.TemplateEditorRouteHandler.ApplyLayoutsAndControls(Page page, RequestContext requestContext) +196
   Telerik.Sitefinity.Web.RouteHandler.InitializeContent(Page handler, RequestContext requestContext) +475
   System.Web.UI.Control.LoadRecursive() +94
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2759

I kept thinking it was a bug in the RC, or perhaps because I needed to build my project or because it was a Web Applicaiton Project and not a Web Site, as I’m used to working with…

Turns out this was once again another example of my tendency to be a complete bonehead.

Since I was using a free css template (courtesy of STUDIO7DESIGNS) I simply copied and pasted the HTML into my master page. Unfortunately I neglected to replace the <form runat=”server” > tag that is required by ASP.NET master pages to function properly!

Talk about duh. Sorry about that. I’m posting this in case I ever make this mistake again (and God knows, I will), when I search for the answer online, I’ll no doubt find the answer on my own blog!

Sitefinity Development: Targeting Multiple Platforms

As I mentioned in my recent post announcing the Sitefinity Toolkit 1.2, adding support to all of the different platforms and versions for Sitefinity 3.7 was an interesting challenge. In the end it required a total of 22 projects (one for each version/platform) organized into one solution. Today I’m going to walk you through the process I took in setting this solution up.

Sitefinity DLLs

It’s important to note that if you are not doing any kind of deep integration with Sitefinity’s inner core, you will probably never need to setup an elaborate project like this. The multiple projects are only necessary if you are hooking into the core libraries defined in the Sitefinity DLLs and developing a compiled, redistributable library. If you are simply developing a user control, or are developing a library that doesn’t require accessing the internal Sitefinity libraries, then you’re probably fine to keep doing things the way you are.

However, if you are developing a compiled, custom library, you need to be able to reference the Sitefinity libraries in your project by adding the DLL files from the different versions. Unfortunately, when you compile your project, it will then be tied to the version of DLL files you reference. This is why you need multiple projects for each version you intend to target.

A Better Way?

I spent some time researching and investigating whether there was a better way to do this, but didn’t come up with any viable solution. I am aware of the "Specific Reference" option for references. However, according to the documentation, this does not affect the actual compiled library. No matter how I referenced the projects, the final output always needed to reference a specific version of the DLLs.

If you know a better way that will make this entire post obsolete, I would certainly be GRATEFUL if you let me know!

Downloading Sitefinity DLLs

Obviously the first thing you’ll need to get started is a copy of all the Sitefinity DLL files for each of the projects you wish to reference. These are available in your Sitefinity Client account. Go into your downloads and you should immediately see the latest version (SP4) as of this writing.

Download-Sitefinity-Patches

There is also a link at the top that will take you to the previous versions so you can go as far back as you need to:

Download-Sitefinity-Versions

While you can certainly download the full project or installer for each version, it luckily turns out that the Patches contain all the updated libraries you will likely need for your project. After extracting all the downloads, each version will contain the needed DLL files in the bin folder.

Sitefinity-Patches Sitefinity-Patch-Contents

Creating the Projects

Now that you’ve got all the references you need for your projects, you need to create the projects themselves. I recommend using the Solution Folders available for Visual Studio Projects to better organize your solution.

Add-Solution-Folder

The solution folder allows you to create virtual folders to organize your projects by type so that you can keep better track of which projects go with which platform. Here’s how I organized mine:

Empty-Project

Now select the appropriate folder and add a new project to it:

Add-New-Project

In the dialog that follows, setup your project to match the platform (in this case ASP.NET 4.0). Be sure to name it in a way that identifies your project. Previously I used the full version number (i.e. 3.7.1990.2) but this ended up being more confusing that I thought and ended up labeling it with the version and Service Pack number.

Simply repeat this process for the different versions and platforms you wish to support, adding new projects into the appropriate Solution Folder.

Create-New-Project Create-New-Project-2.0

When you’re done you’ll have a mighty solution with all the projects needed to support the different versions of Sitefinity. Here’s what mine ended up looking like.

Full-Solution

Assembly Properties

Be sure to make sure all of the Assembly properties match your projects. Although they target different platforms, the project itself is usually a single product, so take some time to sync everything up:

Application-Properties Assembly-Information

Link Source Files

Now you may be thinking that managing 22 copies of source code is a nightmare and you would be absolutely right. Fortunately, Visual Studio has an excellent feature that allows you to "link" to existing source code files so that there is only ONE copy of the source file. This link can be shared to any number of projects, including our 22 Sitefinity projects!

This is exactly what I have done for the Sitefinity Toolkit. In fact, ALL of the project source files are housed within the original project. The other projects simply link to the source files using the "Add Existing Item" menu item, selecting the source code files, and selecting "Add as Link".

Add-As-Link

Keep in mind that some source files should not be linked, especially if they are for classes that target a specific version of Sitefinity. For example, I implemented workflow notifications for the Generic Content Modules. However, the Community Edition of Sitefinity does not support workflow. So this section of source code files are not linked into the Community Edition projects.

Develop, Build, Deploy!

At this point you are ready to begin developing your project. Be sure you add the references you downloaded for each platform above, and of course make sure you add the correct references to the correct project. It took me a few tries to get it right. However I now have all my solutions setup and they all compiled successfully, allowing me to publish the latest update to the Sitefinity Toolkit.

If by chance a new SP is released, it’s simply a matter of repeating this process for the new project. Just be sure to add it for both versions (Community and Standard) as well as the multiple versions of ASP.NET (assuming you want to support them all).

Of course, depending on your project, it might not be this simple. Some of your support libraries may not be available for other versions of asp.net. This was the case with JSON, which doesn’t yet have an official 4.0 version. However, I was able to compile the project targeting the 4.0 platform, so it wasn’t much of a setback. Your results may vary.

A Better Way!

One thing I am happy to report is that it appears this article will definitely be obsolete when Sitefinity 4.0 rolls out. Thanks to the new Facade Pattern and Fluent API, which is now version-agnostic, addons and extensions to Sitefinity no longer need to be tied to a specific version!

Want to know more about the new features coming in 4.0? Be sure to register for the Sitefinity 4.0 RC Webinar taking place November 11!

Wrap Up

Although the process to set up the full solution was slightly involved, in the end it wasn’t all that much work. And the benefits of being able to fully support all versions of the latest Sitefinity 3.7 are certainly worth the effort. I hope you’ll agree!

I’d love to hear your feedback, especially from other Marketplace developers. How are you handling targeting multiple platforms, or are you even attempting to do so? If you attempt to repeat this project, please share your results!

I&rsquo;ve Joined Telerik!

I’ve been sitting on this news for a few weeks now, waiting until today when I can officially announce it, but as the title suggests, I am now officially on the Telerik team as a Sitefinity Developer Support Specialist! I am excited beyond words at this new opportunity, and I can’t wait to dedicate myself to being a part of this magnificent team and platform I’ve come to know and love over the past 3 years.

This is a real turning point in my life, and I finally feel like I’ve "made it" as a developer. Working for the City of McAllen was great, and I wouldn’t trade that time for anything in the world. But now I feel like I have a real chance to truly grow as a developer, and immerse myself in a world I’ve only observed, but never actively joined.

I’m hoping this change means many things, including new and more frequent updates to this blog and other social outlets as I discover and create new resources and references (stay tuned for news about how this will affect the Sitefinity Toolkit!) I hope to help spread the word about Sitefinity not only as a current viable solution (because we all know it is!) but now with version 4.0 on the horizon, a true cutting-edge platform for developers and web sites of all shapes and sizes.

Web development isn’t just my job, it is my PASSION. I eat, sleep, and dream in code (my wife can attest to this), and I am honored to be a part of a team that shares this vision. My endless thanks to Telerik for this amazing opportunity, especially the Sitefinity team for providing the platform upon which I’m not only building this site, but now a fantastic new career!

Disqus Comments on Sitefinity

Things continue to be busy, but I’m doing my best to make time for this site and my various projects. At long last I FINALLY installed Disqus to manage comments for the blog and software posts

Best of all, after a few frustratingly productive hours of hacking the Disqus API, I managed to import all my Sitefinity comments into Disqus! This was actually a fun project, but man was it a pain in the ass trying to hack that poorly-documented, unfriendly API.

I have every intention of publishing my work, most likely as a module in the Sitefinity Marketplace. However, because of the time, effort, and (mostly) frustration, I might depart from tradition on this one and attach a small price on it. The project is too specific to be of use to everyone, and took way too much time that my wife would kill me if I just gave it away.

For once, I agree. No one is a bigger proponent to free and shared software than I, but every now and then, it is nice to be tangibly rewarded for one’s work, and this one is one I am really proud of.

What do you think? It’s not set in stone, and I guess I’d just like to get a feel for just how much of a demand there is for such a tool. Share your thoughts in the new Disqus comment box below!