Friday, April 6, 2012

Sitecore 6.1 -> Sitecore 6.5 CMS upgrade process


Having previously gone through the painful and incremental process of upgrading from Sitecore 5.3 to Sitecore 6.1 and then reading this article, I am attempting to upgrade from 6.1 to 6.5 via a clean install then content migration. Here are my notes as I went through this process.

  1. Read release notes
    1. http://sdn.sitecore.net/Resources/Sitecore%206/Sitecore%20CMS.aspx
  2. Install fresh Sitecore 6.5 CMS instance & dbs
    1. http://sdn.sitecore.net/SDN5/Products/Sitecore%20V5/Sitecore%20CMS%206/Update/6_5_0_rev_111230.aspx
    2. configure a second iis site to point to the new instance, config everything, etc.
  3. Export existing roles from 6.1 instance
    1. Sitecore
    2. Security Tools
    3. Role Manager
    4. Serialize All Roles
  4. Export existing users from 6.1 instance
    1. Sitecore
    2. Security Tools
    3. User Manager
    4. Serialize All Users
  5. I didn’t have any custom domains, but would guess you should do this for domains, if applicable.
  6. Copy the serialization folder from the 6.1 instance to the 6.5 instance
    1. /Sitecore/data/serialization
  7. Import users into 6.5 instance
    1. Sitecore
    2. Security Tools
    3. User Manager
    4. Revert All Users
  8. Import users into 6.5 instance
    1. Sitecore
    2. Security Tools
    3. Role Manager
    4. Revert All Roles
  9. note that this will NOT serialize user passwords and other caveats may apply
    1. http://sdn.sitecore.net/forum/ShowPost.aspx?PostID=28899
    2. solution is to write a job that will reset every password and email the user a notification
      1. http://sdn.sitecore.net/forum//ShowPost.aspx?PostID=39959
  10. profile info migration?
    1. Not sure if this is included with the user when serialized.
    2. I would guess not which would mean I’ll need to write some sort of utility to port it over from the old db to the new db.
    3. Maybe a DTS package?
  11. Update: Steps 3 - 10 above didn't get me anywhere and I think emailing every user to let them know their password changed on them could end up being a huge hassle. I instead used the Sql Server Import/Export Wizard to just migrate the asp.net membership tables from the 6.1 core db to the new 6.5 core db. I checked the content and structure of both sets fo tables and couldn't find any changes so it feel like this was safe. We tested in dev prior to going live as well.
  12. Create package for templates
  13. Create package for layouts/sublayouts/renderings
  14. Create package(s) for media
    1. allow plenty of room for the zip(s) (at least as much as the master db size)
    2. first attempt at single zip failed to import (was almost 5gb). got a “Could not read signature - no data!” error with no other explanation.
    3. tried to do a 4gb file and got “Specified argument was out of the range of valid values. Parameter name: count”
    4. later attempt with a 2gb file did work.
  15. Create package for content
  16. Copy above packages from 6.1 instance to 6.5 instance
    1. /Sitecore/data/packages
  17. Import all the packages in the following order:
    1. templates
    2. layouts
    3. media library
    4. content
  18. Do a full republish on everything
  19. Branch your SVN tree so you can keep working on the base code during migration. (Just in case this takes a while, I get pulled away for other stuff all the time.)

So now that your Sitecore content is up to snuff it’s code time. We had checked the Sitecore install into our SVN repository and had our code intermingled with it. Not sure if this is the best practice since I personally don’t like to check in anything that isn’t compiled from our code but this is where we’re at currently. The first attempt was to just map the layouts, xsl, et al., directories from the branched tree to the new Sitecore website in IIS but Sitecore wasn’t so happy with that.

Could not load type 'SiteCore_Custom.layouts.Main'.

Or so I thought. Turns out that I didn’t copy over my custom dlls to the Sitecore/Website/bin dir. Just reminds me of when my dad used to say a good craftsman doesn’t blame his tools. Lesson learned, pops. Fair enough, then i got this:

Method 'get_EnableCdn' in type 'System.Web.UI.ScriptManager' from assembly 'System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' does not have an implementation

Thisx was easily solved with the googles, which directed me to a StackOverflow article (http://stackoverflow.com/questions/5341324/method-get-enablecdn-in-type-system-web-ui-scriptmanager-from-assembly-syst). I should probably spend some time researching what that actually means (I think that section binds specific calls from older dlls to newer stuff but not totally sure), but I removed the code and winner winner chicken dinner!

With the older code essentially functional under the new Sitecore 6.5 install, it’s time to get down to nuts and bolts. Some stuff that was working prior to upgrade just started failing. There is also some weirdness when debugging in Visual Studio and it seems to enjoy spiking the CPU to 100% and not returning (but seems ok when not attached).

A weird issue I’m seeing is when i try to edit the presentation for one of our product nodes. Everything seems to edit properly but whenever i click OK to save i get the following exception:

Invalid column name 'TargetVersion'.

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.
System.Data.SqlClient.SqlException: Invalid column name 'TargetVersion'.

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.

[SqlException (0x80131904): Invalid column name 'TargetVersion'.]
  System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +404
  System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +412
  System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1363
  System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +6387757
  System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +6389458
  System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +538
  System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) +689
  System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +327
  Sitecore.Data.DataProviders.Sql.DataProviderCommand.ExecuteNonQuery() +89

[DataException: Error executing SQL command:  INSERT INTO [Links](   [SourceDatabase], [SourceItemID], [SourceLanguage], [SourceVersion], [SourceFieldID], [TargetDatabase], [TargetItemID], [TargetLanguage], [TargetVersion], [TargetPath] ) VALUES(  @database, @itemID, @sourceLanguage, @sourceVersion, @fieldID, @targetDatabase, @targetID, @targetLanguage, @targetVersion, @targetPath )]

[Exception: Invalid column name 'TargetVersion'.]
  Sitecore.Data.DataProviders.Sql.DataProviderCommand.ExecuteNonQuery() +342
  Sitecore.Data.DataProviders.Sql.SqlDataApi.Execute(String sql, Object[] parameters) +61
  Sitecore.Links.SqlLinkDatabase.AddLink(Item item, ItemLink link) +908
  Sitecore.Links.SqlLinkDatabase.UpdateItemVersionLinks(Item item, ItemLink[] links) +438
  Sitecore.Events.EventSubscribers.RaiseEvent(String eventName, Object[] parameters, EventResult result) +397
  Sitecore.Events.Event.RaiseEvent(String eventName, Object[] parameters) +390
  Sitecore.Events.Event.RaiseItemSaved(Object sender, ItemSavedEventArgs args) +325
  System.EventHandler`1.Invoke(Object sender, TEventArgs e) +0
  Sitecore.Data.Engines.EngineCommand`2.Execute() +267
  Sitecore.Data.Engines.DataEngine.SaveItem(Item item) +234
  Sitecore.Data.Managers.ItemProvider.SaveItem(Item item) +291
  Sitecore.Data.Items.ItemEditing.AcceptChanges(Boolean updateStatistics, Boolean silent) +229
  Sitecore.Shell.Framework.Commands.SetLayoutDetails.Run(ClientPipelineArgs args) +670

[TargetInvocationException: Exception has been thrown by the target of an invocation.]
  System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner) +0
  System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks) +640
  System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +38
  System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +35
  Sitecore.Nexus.Pipelines.NexusPipelineApi.Resume(PipelineArgs args, Pipeline pipeline) +379
  Sitecore.Web.UI.Sheer.ClientPage.ResumePipeline() +285
  Sitecore.Web.UI.Sheer.ClientPage.OnPreRender(EventArgs e) +498
  Sitecore.Shell.Applications.ContentManager.ContentEditorPage.OnPreRender(EventArgs e) +25
  System.Web.UI.Control.PreRenderRecursiveInternal() +113
  System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4201

I don’t see anything non-sitecore in the stack so maybe not. Oddly enough, re-opening the presentation shows it saves the changes and I can publish successfully. My initial thought is that we have some custom event handler in the pipeline that needs to get updated for 6.5 but will look at that later.

The reason I’m playing with the presentation is because one of the xlst’s on the page is not rendering. In the Sitecore logs I see this:

ERROR A rendering error occurred: Xsl file could not be processed (details: System.Xml.Xsl.XslTransformException: Cannot find a script or an extension object associated with namespace 'http://www.sitecore.net/xslext'.

While that looks like it is a Sitecore issue, we actually named our custom XSL extensions using that namespace and in retrospect that was probably not a great idea but still fairly easy to track down. After re-tracing how the extensions get loaded (using the xslExtensions section in web.config) and printing out the executing dll location to verify it did indeed have the extensions built in, I’m kind of stumped. Kind of fatigued right now so I’m just going to post this as is and do a follow up once I have a fix for teh xsl extensions issue. I don’t think re-writing all the xlst’s as sublayouts is a viable option since that would take a huge effort.