We upgraded both CMS and Commerce a few weeks ago. We did not encounter any major issues while upgrading Commerce however I would like to point two issues worth sharing.
We had a plan to update EPiServer to version 7.19.2. It wasn’t the latest available nuget version, but we couldn’t upgrade directly to version 8. I didn’t want to risk and that’s why I chose Commerce package with similar release date. The closest one was 8.6.1.
Nuget dependencies
There is quite a lot of packages to update. Most of them have dependencies between themselves.
My first try was to update all EPiServer packages directly from Nuget Package Manager Console starting from the main package:
1 |
Update-Package EPiServer.CMS.UI -version 7.19.1 -Source http://nuget.episerver.com/feed/packages.svc/ |
I got an exception related with nuget packeges dependencies. Then I tried to update Commerce packages first, starting from Commerce package root. I got the same nuget exception. In both scenarios the problem was related to EPiServer.Common.Framework nuget which is now obsolete in EPiServer CMS and EPiServer Commerce.
While updating the EPiServer CMS, the NPM tried to remove EPiServer.Common.Framework while it was still in use by the old Commerce version and vice versa.When I tried to update Commerce packages first, the NPM tried to delete EPiServer.Common.Framework while it was still used by old version of EPiServer packages.
I ended up with uninstalling all Commerce libraries, then updating EPiServer nugets and then installing specific version of Commerce nugets once again. It was a time consuming process because our solution is divided into several projects. Each of those projects has nuget dependencies on some of EPiServer and Commerce packages, so I had to do this very carefully.
Finally, after solving the conflicts with references I maneged to get rid of all the compilation errors.
Types registration
Unfortunately that was not the end…
I already had my code updated so the next thing to do was to update the database. I did it using the Update‑EPiDatabase NPM Console command. All scripts were executed correctly, so I tried to run the application. Start page (and whole front-end) worked correctly, but when I logged into Edit mode I got this exception:
Could not create instance of content type “SysCampaignFolder” since it has an invalid .NET class associated: EPiServer.Core.CampaignFolder,EPiServer
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: EPiServer.Core.EPiServerException: Could not create instance of content type "SysCampaignFolder" since it has an invalid .NET class associated: EPiServer.Core.CampaignFolder,EPiServer Source Error: The source code that generated this unhandled exception can only be shown when compiled in debug mode. To enable this, please follow one of the below steps, then request the URL: 1. Add a "Debug=true" directive at the top of the file that generated the error. Example: <%@ Page Language="C#" Debug="true" %> or: 2) Add the following section to the configuration file of your application: <configuration> <system.web> <compilation debug="true"/> </system.web> </configuration> Note that this second technique will cause all files within a given application to be compiled in debug mode. The first technique will cause only that particular file to be compiled in debug mode. Important: Running applications in debug mode does incur a memory/performance overhead. You should make sure that an application has debugging disabled before deploying into production scenario. Stack Trace: [EPiServerException: Could not create instance of content type "SysCampaignFolder" since it has an invalid .NET class associated: EPiServer.Core.CampaignFolder,EPiServer] EPiServer.Construction.ContentFactory.CreateInstance(ContentType contentType) +564 EPiServer.Construction.ContentFactory.CreateContent(ContentType contentType, BuildingContext buildingContext) +46 EPiServer.Commerce.Catalog.Provider.Construction.CatalogContentFactory.CreateContent(ContentType contentType, BuildingContext buildingContext) +144 EPiServer.DataAccess.ContentLoadDB.LoadContentInternal(ContentReference contentLink, Int32 languageBranchId, DbDataReader reader) +334 EPiServer.DataAccess.<>c__DisplayClass1.b__0() +285 EPiServer.Data.Providers.<>c__DisplayClass11.b__0() +60 EPiServer.Data.Providers.SqlTransientErrorsRetryPolicy.Execute(Func
1 method) +150 EPiServer.Core.<>c__DisplayClass26.b__24() +141 EPiServer.Core.OptimisticCache1.Read(String cacheKey, ReadAndCacheObject
1 readAndCacheObject) +1175 EPiServer.Core.ContentProvider.LoadContentFromCacheOrRepository(ContentReference contentreference, ILanguageSelector selector) +945 EPiServer.Core.DefaultContentLoader.TryGet(ContentReference contentLink, LoaderSettings loaderSettings, T& content) +669 EPiServer.Core.DefaultContentLoader.Get(ContentReference contentLink, LoaderSettings loaderSettings) +90 EPiServer.Core.DefaultContentLoader.Get(Guid contentGuid, LoaderSettings loaderSettings) +151 EPiServer.Core.DefaultContentLoader.Get(Guid contentGuid, ILanguageSelector selector) +126 EPiServer.Core.DefaultContentLoader.Get(Guid contentGuid) +143 EPiServer.Core.CampaignFolder.GetCampaignRoot() +160 System.Lazy1.CreateValue() +455 System.Lazy
1.get_Value() +14390282 GetRoots(Object ) +94 Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target) +384 [JsonSerializationException: Error getting value from 'Roots' on 'EPiServer.Commerce.Shell.UIDescriptors.MarketingRepositoryDescriptor'.] Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target) +564 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue) +217 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) +1335 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) +1436 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) +1335 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty) +911 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType) +178 Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType) +936 EPiServer.Shell.Web.Mvc.Html.ScriptExtensions.SerializeObject(HtmlHelper html, Object value, String contentType) +255 ASP.secureui_shell_views_shared_bootstrapper_aspx.__Render__control5(HtmlTextWriter __w, Control parameterContainer) +513 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +131 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150 ASP.secureui_shell_views_shared_sleek_master.__Render__control1(HtmlTextWriter __w, Control parameterContainer) +625 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +131 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +249 System.Web.UI.Page.Render(HtmlTextWriter writer) +40 System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) +65 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +150 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5363
Table tblContentType stores all content types. It’s used by EPiServer to initialize ContentTypeRepository. SysCampaignFolder content type had a backend type set as EPiServer.Core.CampaignFolder, EPiServer in database while there was no such type in EPiSErver assembly. The type is defined in EPiServer.Business.Commerce library.
I searched for similar problems on forum, but with no luck, so the the only solution was to prepare a custom SQL script to manually update the backed type.
1 2 3 |
UPDATE tblContentType SET modelType = 'EPiServer.Core.CampaignFolder, EPiServer.Business.Commerce, Version=8.6.1.431, Culture=neutral, PublicKeyToken=8fe83dea738b45b7' WHERE [Name] like 'SysCampaignFolder' |
After executing the script everything started to work.
A few weeks later I realized that there was no need to prepare a custom SQL. I could just add one more step to our update process. After updating the code I should run the application before running schema update scripts. In that scenario the Episerver automatically registers all new content types and the SysCampaignFolder type will have full qualified assembly assigned correctly. Then running schema update will not create new type in DB so there will be no problem.
Upgrading EPiServer Commerce is not risky or time consuming when you do this frequently. The problems with nugets and type registration were probably caused by long time from last update of our solution.