Upgrading an Azure hosted Orchard install from 1.0 to 1.1
Last night, I finished upgrading this site from Orchard 1.0 to Orchard 1.1 (yay!). As such things go, it could have gone a lot worse, but it also took a long time. Most of that time was taken up because I had to essentially perform the upgrade twice – once an in-place attempt, and the second with a fresh copy of the Orchard source. So that I wouldn’t have to rely on my memory to recall the steps involved if I need to do this again, since the documentation doesn’t cover all of the gotchas, I’m posting the steps I followed. Feel free to leave feedback on what I’ve done wrong or how the process could be improved!
Here are a few general observations regarding the process. Note that I assume that you have an existing, working Orchard site running in Azure:
- If you want to use a theme other than ThemeMachine, use non-default modules, or customize any of the templates for your site, you’ll need to setup a source enlistment. Due to Azure’s distributed nature, making changes to the site through the file system on a running instance is a bad idea – you’ll lose them if the instance is rebooted
- Do not attempt to publish the site using Visual Studio’s Publish… feature. The publish itself will succeed and the instance will start, but you will get an exception like the following:
None of the constructors found with policy 'Orchard.Environment.AutofacUtil.DynamicProxy2.ConstructorFinderWrapper' on type 'Orchard.ContentManagement.DefaultContentManager' can be invoked with the available services and parameters:
Constructor 'Void .ctor(Autofac.IComponentContext, Orchard.Data.IRepository`1[Orchard.ContentManagement.Records.ContentTypeRecord], Orchard.Data.IRepository`1[Orchard.ContentManagement.Records.ContentItemRecord], Orchard.Data.IRepository`1[Orchard.ContentManagement.Records.ContentItemVersionRecord], Orchard.ContentManagement.MetaData.IContentDefinitionManager, System.Func`1[Orchard.ContentManagement.IContentManagerSession], System.Lazy`1[Orchard.ContentManagement.IContentDisplay])' parameter resolution failed at parameter 'Orchard.ContentManagement.MetaData.IContentDefinitionManager contentDefinitionManager'. - Just because it works in the Azure emulation environment doesn't mean it will actually work... it just means that it *could* work.
With that in mind, here are the steps I ended up following:
- Check out the latest default branch from the Orchard source enlistment into a new working directory
- Copy the service configuration and definition files (src\Orchard.Azure\Orchard.Azure.CloudService) from the old site to the new site. This is especially important if you want to enable RDP access to your instance.
- ServiceConfiguration.csdef
- ServiceDefinition.csdef
- Copy the web.config from \src\Orchard.Azure\Orchard.Azure.Web to your new working copy. If you want to be extra cautious, just copy your machine key over. It is critical that you have a machine key defined if you want to run more than one worker role instance! Without the machine key, visitors to your site will experience intermittent and mysterious errors. This is because your site is running in a web farm (Azure), and sessions are shared between instances.
- Open the azure solution (\src\Orchard.Azure\Orchard.Azure.sln) in VS as an Administrator, make sure that storage and computing emulators are started and working. You won’t be technically using the storage emulation since you’ll point your local instance at the cloud data, but the project expects it to be working.
- Download and install the 1.1 version of your theme and any desired modules into the solution (use these directions for guidance)
- Make any changes to your templates and views now; you won’t be able to reliably change it later without redeploying. I don’t have a lot of customization yet for this site, so my changes were relatively limited:
- This site currently uses the Contoso theme, so I changed \Themes\Contoso\Views\BadgeOfHonor.cshtml to match the footer text with my company name.
- EDIT: Bertrand LeRoy pointed out in the comments that there is indeed a better way to do this. I wanted to adjust how the blog posts on the home page are truncated with the “more…” link, and also keep images in the excerpted summary, so I modified \src\Orchard.Web\Core\Common\Views\Parts.Common.Body.Summary.cshtml dropped a file into my Theme's Views folder named Parts.Common.Body.Summary.cshtml - thanks to Orchard's dynamic customizations, it will override the base template!to look like this:
Orchard.ContentManagement.ContentItem contentItem = Model.ContentPart.ContentItem;
string bodyHtml = Model.Html.ToString();
HtmlString body;
bool excerpt = bodyHtml.Length > 800;
if (excerpt)
{
var stoppingPoint = bodyHtml.IndexOf("</p>", 600, StringComparison.CurrentCultureIgnoreCase);
body = new HtmlString(bodyHtml.Substring(0, stoppingPoint < 0 ? 800 : stoppingPoint) + "...");
}
else
{
body = Model.Html;
}
}
<p>@body
@if (excerpt)
{
@Html.ItemDisplayLink(T("more").ToString(), contentItem)
}
</p>
- Make any changes to your templates and views now; you won’t be able to reliably change it later without redeploying. I don’t have a lot of customization yet for this site, so my changes were relatively limited:
- Check your SQL Azure settings to make sure of the following:
- Open a firewall port for your local IP address. You may already have this set up if you use SQL Management Studio to manage your SQL Azure instance. Your working copy will need to be able to access both blob and SQL storage
- Make sure that the SQL login that you’ve configured your site to use has CREATE TABLE permissions on your Orchard DB (see below for why)
- Launch the solution in the emulation environment. You should see your site’s home page (yay! almost there!)
- Login to the new dashboard (ooo! pretty!). It will have a message saying that you need to upgrade some modules.
- Update modules individually (I started with Core and moved on from there, trying to update ones with the most dependents first). If you get an exception along the lines of "CommitTransaction without corresponding BeginTransaction”, you need to make sure that the SQL account Orchard is using has the appropriate perms. I gave my account dbo perms and called it a day; it’s not difficult to remove that later, and it ensures that lack of permissions won’t cause any upgrades to fail.
- Once you’ve upgraded everything and you’re satisfied that the site has the desired modules and themes installed and working, it’s time to deploy to the cloud. Run the ClickToBuildAzurePackage.cmd in the /src/ directory of your local copy, and deploy your site to the staging slot in the usual manner.
- The documentation talks about wiping BLOB and SQL storage before redeploying, but that’s not accurate; Orchard seems to support and allow you to redeploy the app without wiping storage. As always though, YMMV.
- If everything checks out, just do an in-place VIP swap of your staging and production slots, and we’re done!
Final Thoughts:
Upgrading from Orchard 1.0 to 1.1 is currently a straight-forward, if rather tedious, process. On the plus side, hosting in Azure makes the actual migration very simple since there’s no need to copy media folders and files around. On the minus side, it takes quite a long time! Much of the lengthy time involved is just inherent in working with Azure; deployments take a while. The other pain point is having to download and adding all of the theme and module files to the source solutions. It would be nice if we could add themes and modules normally through the gallery, but the problem of file system access is a thorny one. It seems like it should be possible to have a virtual machine worker role with Orchard installed normally to avoid having to jump through all of these same hoops, but further research is needed.
If you want to learn more about Orchard, visit their site at http://orchardproject.net.