HomeDev GuideRecipesAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsGitHubNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev Guide

Changes to the Category API in CMS 8

This topic describes improvements to the performance of categories in Optimizely Content Management System (CMS 8), by updating the Category API to use the read-only instance pattern commonly used in other areas of the API.

To improve the performance of categories in Optimizely Content Management System (CMS 8), the Category API was updated to use the read-only instance pattern commonly used in other areas of the API. This means that requested categories are returned as read-only instances by default, and modification can be done only after a writable clone has been requested. As a part of the change, a new CategoryRepository class is introduced to improve the testability of the API. This repository replaces the now-obsolete methods directly on the Category class, such as GetRoot() and Save.

Example of modifying a Category:

var categoryRepository = ServiceLocator.Current.GetInstance<CategoryRepository>();
    var myCategory = categoryRepository.Get("MyCategory"); // Returns a read-only instance
    myCategory = myCategory.CreateWritableClone();
    myCategory.Description = "My category is really nice";
    categoryRepository.Save(myCategory);

Changes to the parent collection

Another smaller change is that the parent Category instance is no longer modified beyond the current when adding or deleting a category. This means you must reload the parent category to get an updated version with/without the added/deleted category. For example:

var parent = categoryRepository.Get("Parent");
    var childCategory = new Category(parent, "Child");
    categoryRepository.Save(childCategory);
    
    // parent.Categories will not contain a "Child" category here.
    
    parent = categoryRepository.Get("ParentCategory");
    
    // parent.Categories will now contain the "Child" category

Support for moving categories

The Save method now respects changes to the Parent property. So, it's possible to move a category from one parent to another without having to recreate it. This also means that content items associated with the moved category maintain their association after the move.

Changes to CategoryCollection

To make the category tree easier to use, we changed the CategoryCollection class to no longer inherit from CollectionBase. Now, it implements IList<Category> instead of just IList.

Full list of breaking Category API changes

While we tried to keep the API as backward-compatible as possible, some behavioral changes were introduced with version 8. The following changes made to the API are considered breaking:

  • Category now implements IReadOnly. Save() requires that the category is writable when called.
  • Category.GetRoot() now returns a read-only Category instance.
  • Category.Delete() no longer removes itself from its parent's categories.
  • Category.Delete() no longer clears the Categories property when called.
  • Category.Save() with a new category no longer adds itself to its parent's categories.
  • Category.Save() with new category now respects the sort order if given.
  • Category.Save() now requires the name to be unique among siblings.
  • Category.Save() now respects a change of parents.
  • Category.Save() now throws ArgumentException instead of DataAbstractionException when the Category is in an invalid state.
  • Category.GetList() implementation has changed to returns a list of type List<Category> instead of a CategoryCollection.
  • CategoryCollection no longer inherits from CollectionBase, it now implements IList<Category>.
  • CategoryCollection now implements IReadOnly.
  • CategoryCollection.AddRange() now validates and sets the Parent property of the inserted Categories the same way as Add() does.
  • CategoryCollection now throws InvalidOperationException instead of DataAbstractionException if the Parent value of the inserted Category doesn't match.
  • CategoryList.MemberOfAny() overloads were combined into one.
  • CategoryList.MemberOfAll() overloads were combined into one.
  • CategoryList.GetHashCode() now returns the same hash for two instances that match according to the Equals() method.

Note that many parts of the old API were marked obsolete. These items have compile-time information describing the change and where to find the equivalent method in the updated API.