By now, a lot of us have already participated in one or more Optimizely CMS 12 upgrade projects. The others are still evaluating whether they should do it now or wait some more. Regardless of when you do it, there will definitely be some unique upgrade challenges you will come across, as I and many others did with the projects we worked on. And most of these depend on the actual project and its previous implementations that need more than normal tweaking with upgrade, or sometimes a complete redo as the existing logic just doesn’t work with the new stuff.
There are several posts already out there going through the actual upgrade process and what steps to follow in what order. I myself have referenced some and written some of those while working on my upgrade projects, as they served as a handy guide with details on what to do and what not to do. Then why am I also writing about this?
Well, technically I’m not. This post will not tell you how to go about the upgrade process itself. You can google for several of those that already exist. This one will highlight some of those unique challenges that I came across and could not find a verbatim solution for them in any of the existing posts out there. These are things that I had to figure out after spending much time, after talking to other Optimizely experts and support, and doing a deep dive into some libraries that I normally wouldn’t need to.
So hoping this serves as a handy guide for anyone jumping on the upgrade bandwagon going forward and facing any of these unique issues.
Here goes my list of Optimizely CMS 12 – Unique Upgrade Challenges :
1. ModelSyncInitialization Exception
We upgraded our CMS 11 project to CMS 12 and when most of the content types were converted, we connected the CMS 12 codebase to CMS 11 database. We did expect some runtime errors at this time, because we had drastically refactored code, so there were bound to be some type mismatches here and there. And as expected, we launched and got a 500 error. In logs, it gave us ModelSyncInitialization exception. But strangely forgot to tell us where and what type was throwing this exception.
We spent days commenting/uncommenting different codes, comparing GUIDs on content and property definition types, adding/removing things in initialization and more.. but nothing helped. We even reached out to Optimizely support but even they had a hard time identifying what might be causing this exception.
At this point, one colleague decided to go back in time, figuratively. Basically, he started pulling code from commits made 2 weeks ago and started connecting that code to CMS 11 database. The first few commits worked and launched site. He then jumped a few and found one where it broke on the same exception. He then backtracked a bit more and finally found the exact commit where this connection broke without sharing any useful details. It was the one where we had upgraded from Episerver.CMS 12.13.2 to 12.15 and Episerver.Framework 12.9 to 12.11.
Usually, nuget upgrades are for better only, but not this time. When we reverted this particular change, and tested again with a few further commits, we got the ModelSyncInitialization exception again, but this time it had a detailed message with it, telling us which property and content types have the mismatch that we should go back and fix. Apparently there was a settings class with a ton of propertylists that were tied to a selectionList of class A in CMS 11 and we changed it to class B in CMS 12, with pretty much the same structure within both classes. But the way this was now in CMS 11 DB, it wouldn’t match saved class A type data to new class B. So we had to go back and revert this change and the exception was gone.
This has been logged as an official CMS bug now. Until it resolves, whoever encounters similar issues, please go back to the versions that give you details on these type of exceptions.
2. Marketing Connectors
We had Salesforce and Pardot connectors setup in CMS 11 for this project, and anyone’s who’s worked with these, knows where to configure them : CMS > Admin > Config > Tools. When we upgraded to CMS 12, there is no such section under CMS Admin. So I went looking through the Optimizely documentation, and the user guide still pointed to the same setup for CMS 12. So now I had to figure this out myself, and I did. And now this Optimizely user guide will also point to the right area for setting up these connectors (the screenshots might still need updating).
Another interesting issue we faced with this was that I went into the AddOns > Marketing Connector section in CMS and setup my Salesforce Connector, on the DXP site. When I made the next deployment to DXP, this connector disappeared and I had to recreate it. After observing this behavior multiple times, I opened a support ticket with Optimizely. And after a good couple of weeks, we found the reason.
If you’ve gone through this documentation on how to setup the connectors, there is a section around encryption and configuring a MAICryptoKey. The documentation still refers to web.config, but essentially this will need to go into your appsettings.json file and that too under the root node. In my case, for some reason, it was under a sub node under root, so wasn’t actually effective at all. When we figured and fixed this, I saved a connector on DXP site and made the deployment. The expectation was the connector would stay put after deployment, but it was gone again.
After a chat with my colleague, we concluded that now that the MAICryptoKey is in the right place in appsettings, now if I save the connector setup, it should effectively encrypt that and upon another deployment, will be able to decrypt the same using this key and then show. So all I needed to do was another deployment. And what do you know, that was it!
Definitely an interesting find, this one.
3. Visitor Groups – Failed to Bind Model error
If you have custom visitor group criterion in code, one thing we’ve learnt with the upgrades is to keep the namespace and assembly names intact on them, otherwise, post upgrade, they won’t match with what the database has and won’t work. I have a more detailed post on this here.
However, I had another unique error with custom visitor groups in my case. I had custom criterion model with boolean properties :
If you notice, these had DojoWidget attribute with Ignore=true on them and only a getter, no setter. This worked fine in CMS 11, where these boolean properties did not even show under the criteria because of the attribute. All logic was within the custom Criterion created based on this model.
In CMS 12, DojoWidget attribute is obsolete and needs to be replaced by CriterionPropertyEditor attribute. It allowed us to keep Ignore=true on it, and it built successfully, so that’s all we changed. But now when we went to the Visitor Group UI and tried editing one of the existing visitor groups created based on this custom criterion model, or even create a new one based on this, we got this error :
After a lot of back and forth on support ticket, we were finally told to add a setter on the properties, which essentially meant, we needed to show them too. And we did that and saw checkboxes for the boolean properties and now when we hit save, the error was gone.
Essentially, the way the new visitor group logic worked, it needed the properties to show in order to be able to save/bind any values to the model. In this case, even if I didn’t select the checkboxes, they needed to show just to be able to save a false value on the model.
Another interesting thing we noticed here, and maybe useful to know for others who need to work with boolean properties, they don’t take the property name as label anymore. CriterionPropertyEditor attribute lets you specify labels by asking you the <path in xml> for where the label text is stored. This documentation on Optimizely says to create your own xml file under /lang directory.
It took me a while to get this right and working on DXP, but basically, you need to add a “lang” folder under solution root and then a “visitorgroupcriterion.xml” file under it with the label texts in it. Please note the lower casing on both the folder and filenames as that is crucial to getting it to work in DXP.
4. DXP Project Migration Steps
This is a great document to begin this process, however, I had a little bit of a challenge understanding exactly what each step/button click did here. So I reached out to support for more clarity. And I definitely got it from them.. some things that are probably missing from this documentation :
- In order to test the upgrade on Integration first, the only steps we need to do are copy content and hostnames and setup any new ones. This will provision the CMS 12 environment and let you access using the new hostnames. I hit Go Live during the initial migration process itself which led to a lot of confusion and rollbacks.
- Go Live step is essentially to be done towards the end of the process when you are actually ready to go live on PROD. Until go live button is hit, both CMS 11 and 12 sites are up and running under their hostnames and you can compare the two versions. Once you hit Go Live for any environment, the CMS 11 hostname on that environment starts pointing to CMS 12 instance. You do have the option to abort Go Live if you are not satisfied still. But once you do this for all environments and complete migration, all CMS 11 hostnames start pointing to CMS 12 instances and CMS 11 environments are scheduled to be decommissioned after 7 days.
It was quite a journey to get past these unique issues and took a fair bit or time and effort. So hoping this spares others on the same path!
If you have encountered any other unique issues yourself, please do share in comments. We’ll try to figure out solutions and add on to this list.
Ritu, this article help me solved an issue I had with my clients. Thanks very much for saving me a bunch of investigation time!
Hey Surjit, I’m glad this was helpful. It definitely took me a while to sort through some of these, so happy that paid off not just for me but others too.
Hi Ritu!
We have the same issue with the marketo connector but I do not understand what MAICryptoKey is, where to find it / choose it or what you did to resolve it. Could you please elaborate on it?
Hi Emilija
MAICryptoKey is something you need to use to encrypt the marketing connector information entered in CMS. So if you add any Episerver.MarketingAutomationIntegration packages to your solution, you’ll need to add a MAICryptoKey in the appsettings.json file. This is basically an SHA-256 hash of any text you choose.
See here for the Opti documentation – https://docs.developers.optimizely.com/content-management-system/docs/connect-for-salesforce
Here is a link to generate the SHA-256 hash that you can then use as your MAICryptoKey – https://workat.tech/developer-tools/sha256-hash-generator
What is the syntax to add it to the appsettings?
Shouldn’t it be added to some additional place as well?
Hi Emilija
The syntax is pretty straightforward. You need to add this at the root of your appsettings.json file.
And the additional place is the marketingAutomationIntegration package added to solution where it looks for this key. Its already configured there to look for what we have specified in our appsettings.
Hi Ritu,
Facing issue with
Error CS0433 The type ‘ContentLanguage’ exists in both ‘EPiServer.Cms.AspNet, Version=11.20.2.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7’ and ‘EPiServer.Cms.AspNetCore, Version=12.4.0.0, Culture=neutral, PublicKeyToken=8fe83dea738b45b7
Could you please help if you’ve come across with the above error?
Thanks
Hey Snehal
You need to remove the Episerver.CMS.AspNet package from solutions. If you see, its tied to CMS version 11 and .net framework not .netcore. With CMS 12, we only need .net core one.
Once you remove this package, this error should go away.