When you use either the
GetChildren<T>() methods from
ContentRepository, the object that is returned will always be a read-only version. If you try and update any property on these objects and try to persist that data back to the CMS using the
Save() method you will encounter an exception ❌. Read on to learn why 🔥🔥🔥
Why does Episerver make everything read-only?
The first reason is to simplify the API for everyone. When you work with pages or blocks in code, 95% of the time you will only need to access them in a read-only context, like displaying data on the screen. By making all the objects returned from the API immutable (read-only) when you work with an object, you know that it won't change. This allows the API to share the same object instance between several different threads. You can access the same object in different controllers at the same time and you will get exactly the same behaviour each time. This type of architecture significantly reduces the number of short-lived objects being created and consequently reduces the amount of memory that your website will need to consume.
If you use a reflection tool, like DotPeek to look at the underlining code of
PageData, you will notice it implements the
IReadOnly interface (look in
EPiServer.Core.PageData). Behind the scenes when you call either
GetChildren<T>(), Episerver first creates a writable
PageData object. The object is then populated with its corresponding data. A call is made to
IReadOnly.MakeReadOnly(), which in turn converts the object to an immutable object. This object is then added to the cache and any subsequent calls from that page or block from the API will return in a read-only state.
How Do I Update A Page?
If you try to update an object returned from the API and save it you will encounter a
System.NotSupportedException exception stating that the
The property ***** is read-only. When you work with pages and blocks, you may notice they both expose a method called
CreateWritableClone() makes a mutable copy of the page. With this new writable copy, you can then update the content and persist the values back into Episerver.
Note the codes uses
IContentRepository rather than
IContentRepository will give you access to the
Save() method, while
IContentLocator only gives read-only CMS content access. We retrieve the page/block from the database using the
Get<T>() method. On Line6, the
CreateWritableClone() method is used to create an ibject that is not reead-only. On Line8,
Save() is used to store the data. If you need to know if the page/block you are currently working with is read-only or a clone you can use the
Happy Coding 🤘