Breaking changes in CMS 8
This topic describes breaking changes for Optimizely Content Management System (CMS 8) in relation to previous version 7.5+, and the steps needed to update affected code.
To view the complete list of changes, see the release notes feed.
Some changes are binary breaking but do not necessarily require code changes but rather just a project recompilation. Breaking changes are changes in method signatures or behavior of methods compared to the documented API in the previous version. These APIs are described below.
Language selectors (ILanguageSelector in IContentRepository/IContentLoader)
Who/what is affected:
If you have code that uses ILanguageSelector
or LanguageSelector
.
Description:
The content API had something called LanguageSelector
which was one of the more misunderstood and complex areas when working with multilingual content via the API. This API has now been rewritten from scratch. Much effort was invested to ensure these changes do not affect sites; in most cases, a recompilation is enough. There are no changes in behavior, so if the recompilation goes through, no more changes are required. The MVC sample site for Commerce requires that you change the uses of ILanguageSelector
to LanguageSelector
in one code file, no changes to the CMS sample site Alloy are required. See Changes to content loading in CMS 8.
PageData.LinkURL and classic links
Who/what is affected:
If you have code that parses query string "?id=x" or are displaying "?id=" links on the website. This change does not cause compilation warnings.
Description:
"Classic links" in the traditional Web Forms style were available in EPiServer since the beginning, these have consisted of the path to the template and an "id" querystring on the end. The friendly URLs were later introduced, where the URL contains the name of the pages that the editor creates instead of technical details. Then permanent links containing a GUID instead of the ID number, the format stored in the database was introduced. Because there is no template to link to in MVC, the classic link is the permanent link combined with the "id" parameter, basically a hybrid between permanent and classic link.
- Permanent links: Format stored in a database (for example
~/link/bbaadfc8-44d8-42a6-b559-b20f08714084.aspx
). - Classic links: Format shown in some APIs (
/templates/mypage.aspx?id=44
). - Friendly URL: Format shown to the user (
/somepage/someotherpage
).
As of this release, "Classic links" were removed to simplify the API, instead permanent links are being returned from APIs, such as PageData.LinkURL
, the URL is determined with routing to the Friendly URL at rendering time. If you display a permanent link on the site and a user clicks on the link, the user is redirected to the friendly URL (determined via routing).
URL Rewrite providers (and the episerver/urlRewrite element)
Who/what is affected:
Anyone using the element with custom providers.
Description:
Up to CMS 6 an URL rewrite provider system was used to rewrite both incoming links and outgoing links for WebForms, this system is being phased out and extensibility using this system is not supported. This system was replaced with ASP.NET Routing in CMS 7.
Categories API refresh
Who/what is affected:
Code that is creating or modifying categories.
Description:Â
Previous versions would clone a category before returning it. Due to the double-linked nature of the category tree structure, this would mean that every category in tree would be cloned whenever a category was requested. This could lead to performance issues for sites with large category structures.
As of this release, Categories
and CategoryCollection
now implement the IReadOnly
interface. You must call the CreateWritableClone
method on a Category
to get an instance that can be modified.
The Category
API now includes a CategoryRepository
service that is responsible for all loading, saving and deleting of categories; this task was previously done directly on the Category
class. In addition, several smaller changes were made to remove previously quirky behavior. See Changes to the Category API for a complete list of breaking changes.
Method Preload removed from interface IInitializableModule
Who/what is affected:
No change is required unless you implement an explicit interface because the method has never been called.
Description:
Preload has never been called and was created for future use. It was removed to fix code.
Save published content with save action Save and ForceCurrentVersion
Who/what is affected: Check for code using "SaveAction.Save | SaveAction.ForceCurrentVersion"
Description:
The expected behavior is that this is not allowed since the current behind-the-scenes upgrading to Publish that was added in CMS 7 bypassed both the publishing events and access checks and other type of code. You are supposed to pass in either Save on versions or Publish to modify a published content without changing status. Calling this combination now throws an exception.
PropertyDataCollection no longer inherits NameObjectCollectionBase
Who/what is affected:
Code assuming NameObjectCollectionBase is the base class.
Description:
The base class had performance issues and the implementation had to be replaced. The class keeps the same semantics as previously with a few minor exceptions.
- Add will now throw an ArgumentException if the name is an empty string – This will probably mainly affect some of your tests, if the property name is not set.
- Add will now throw an ArgumentNullException instead of a NullReferenceException if the property is null.
- The GetByIndexHandler is deprecated and will no longer be used by the numeric indexer, for example, content.Property[42].
- Remove method now returns a Boolean indicating if a property was removed or not.
- CreateWritableClone now clones the OwnerLink as well.
- CreateWritableClone no longer calls InitializeData if the original wasn’t initialized.
- TryGetValue and GetValue methods have been renamed to TryGetPropertyValue and GetPropertyValue respectively to avoid confusion with Dictionary methods. The old methods remain as obsoleted for the time being.
- TryGetPropertyValue and GetPropertyValue now accept a type parameter that is a base type of the property value type, for example, TryGetPropertyValue will work with PropertyPageReference.
- TryGetPropertyValue and GetPropertyValue will now only use the GetHandler when in read-only mode in the same manner as the string indexer.
Possible to set EntryPoint for content provider that have exactly 1 child
Who/what is affected:
If you have exactly 1 child under the entry point for a content provider.
Description:
The documentation states that you are only supposed to attach content providers to leaf nodes, but there was a validation in the code that allowed 1 child to be present. This scenario will now throw an exception requiring you to detach the provider and delete that content (if that is not possible, Support can help you with deleting the item directly from the database).
Possible to change Hosts property on read-only SiteDefinition
Who/what is affected:
Programmatically changing Hosts property on SiteDefinition without cloning the site definition.
Description:
The fix involves making sure CreateWritableClone is called on SiteDefinition before making any changes.
ContentLanguageSetting is not mockable
Who/what is affected:
If you are calling methods Save/Load/ListTree on ContentLanguageSetting.
Description:
Methods are left obsolete and will continue to work but we recommend using ContentLanguageSettingRepository instead when making changes to language settings.
ContentReference comparisons
Who/what is affected:
If you are sorting your ContentReferences without specifying a comparer and are dependent on that they are sorted primarily on ID and not ProviderName or if you have started using ContentReferenceComparer.IgnoreVersion and are dependent on that it includes the GetPublishOrLatest property when comparing.
Description:
Comparison methods on ContentReference have been modified to take the ProviderName into account when doing comparisons. It has also been updated to match the .NET Framework specifications for comparisons to not throw exception when comparing with null values. This also includes a small change to the newly introduced ContentReferenceComparer to align the behavior with the standard ContentReference functionality.
-
ContentReference.CompareToIgnoreWorkID with null no longer throws exception but returns false.
-
ContentReference.CompareTo with null no longer throws exception but returns -1 as per IComparer specification.
-
ContentReference.CompareTo will now compare by WorkID correctly if ID is the same.
-
ContentReference.CompareTo will now use ProviderName in comparison (before ID and WorkID is compared).
-
ContentReferenceComparer.Standard.Compare now includes ProviderName and GetPublishedOrLatest.
-
ContentReferenceComparer.IgnoreVersion.Compare now compares ProviderName before ID and WorkID.
-
ContentReferenceComparer.IgnoreVersion.Compare and Equals no longer include GetPublishedOrLatest in comparison.
UrlResolver, TemplateResolver and ContentAssetHelper changed to abstract classes
Who/what is affected:
Mainly code in unit tests where classes are replaced by mocked instances.
Description:
To simplify mocking classes UrlResolver, TemplateResolver and ContentAssetHelper changed from being concrete instantiable classes to be abstract base classes. If you previously created new instances of UrlResolver use the shared instance UrlResolver.Current or dependency injection, you can also use ServiceLocator.Current.GetInstance to load instances of theses classes.
UrlResolver returns absolute URL outside of web context
Who/what is affected:
Code that is expecting a relative URL when calling the UrlResolver.GetUrl() method outside of a web context.
Description:
A new feature allows for sites with multiple hostname bindings to identify primary hosts and hosts that should be redirected when requested. As a part of this change the UrlResolver has been updated to ensure that links are returned using the primary hostnamn if not already on this site. This also includes calls that are done outside of the web context, such as scheduled jobs.
AllowedTypes adds server validation
Who/what is affected:
Code that assumes that AllowedTypes do no server validation.
Description:
The AllowedTypes attribute now inherits ValidationAttribute and adds server validation for ContentReference and ContentArea. The attribute is not supported on other property types.
Default root for custom content routes
Who/what is affected:
Code that registers custom routes using method MapContentRoute without explicitly specifying which content root the route should start from.
Description:
A custom route using a {node} segment will start the routing from the content root given when the route was registered. Previously, if no content root was explicitly specified, the routing started from SiteDefinition.Current.RootPage. This has now changed so the default value is SiteDefinition.Current.StartPage.
Validation of collection properties marked with Ignore attribute
Who/what is affected:
Content model classes with collection properties marked with the Ignore attribute.
Description:
Properties marked with the Ignore attribute will no longer be part of validation during saving of content instances. Previously, collections were always validated even with the Ignore attribute.
ContentRoute events
Who/what is affected:
Code that added an eventhandler to ContentRoute.RoutingContent, ContentRoute.RoutedContent, ContentRoute.CreatingVirtualPath or ContentRoute.CreatedVirtualPath using operator '='.
Description:
Previously, the events on ContentRoute were exposed as event handlers (delegates) which made it possible to assign an event handler through usage of the '=' operator. The event handlers have now been changed to events meaning that event handlers should be assigned using '+=' operator.
IContentTypeAdvisor and DefaultContentTypeAdvisor
Who/what is affected:
If you have implemented IContentTypeAdvisor or you are using DefaultContentTypeAdvisor in your code.
Description:
The interface IContentTypeAdvisor has changed, any code implementing this interface needs to be changed:
-  GetSuggestions method now accepts parent argument that is IContent and contentFolder argument that is boolean, for example, GetSuggestions(IContent parent, bool contentFolder, IEnumerable requestedTypes).
The default implementation of IContentTypeAdvisor is DefaultContentTypeAdvisor. There are two changes in this class.Â
- The constructor no longer accepts ContentTypeService, instead this argument is replaced with ContentTypeAvailablilityService.
- The method GetSuggestions has changed to match the new implementation of IContentTypeAdvisor mentioned above.
Add-On dependencies to "Shell" or "CMS" 3.x must be changed to EPiServer.CMS.UI
Who/what is affected:
Add-on developers.
Description:
When the CMS UI Add-On was moved into a NuGet package, the naming and versioning was streamlined with the EPiServer.CMS.Core package, resulting in an initial release package named EPiServer.CMS.UI with version 7.6.
To satisfy any add-on with a dependency on the CMS UI packages, previously named CMS and Shell, two additional assemblies was added: CMS.dll and Shell.dll. These assemblies have now been removed, meaning that any add-on which still depend on CMS or Shell can no longer be installed.
Any add-on dependency to CMS or Shell should instead be to EPiServer.CMS.UI.
Multiple changes to CSS styling in the user interfaces
Who/what is affected:
If you have used not-documented CSS classes.
ASP.NET 2.0 Web Services: PageStoreService.asmx, DataFactoryService.asmx, ContentChannelService.asmx
Who/what is affected:
If you are using these services, installed in the WebServices folder in versions up to 7.5, start migrating to use other alternatives of integration. Services already installed will continue to work in CMS 8 but support is planned to be removed in a future update.
Description:
The XML Web Services (described in this article) are based on the legacy ASP.NET 2.0 Web Services Technology. These extensions are no longer shipped with EPiServer CMS as of version 8.0. We recommend using either the Service API to integrate with external systems or Windows Communication Foundation (WCF) to create your own custom XML Web Services.
Updated 2 months ago