Background:
Sometimes we get invalid pointers to renderings in the diffs stored in the rendering fields in Sitecore. (_Final Renderings in our case but maybe it appears in in the shared _Renderings too)
For example when having some renderings in the standard values and then edit some pages. Later removing the renderings in the standard values. If you combine this with synchronizing templates between development and production environments (for example with unicorn) you get after="non-existing-id" and other weird stuff in your delta values in _Final Renderings.
Updates from Sitecore says this should not occur... but you still get some weird values at some points. So...
This combined with the problem that Sitecore 8.someversion causes the page to totally crash in both Normal mode (visitors) and in Experience editor mode. With the not-saying-so-much:
Exception: System.NullReferenceException
Message: Object reference not set to an instance of an object.
Source: Sitecore.Mvc
at Sitecore.Mvc.Pipelines.Response.RenderPlaceholder.PerformRendering.CreateCyclePreventer(String placeholderName, Rendering rendering)
at Sitecore.Mvc.Pipelines.Response.RenderPlaceholder.PerformRendering.Render(String placeholderName, TextWriter writer, RenderPlaceholderArgs args)
...
Findings:
The problem can be "manually" fixed in content editor
- Open an item with such a problem in Content Editor
- Select Presentation and click Details it opens the dialog
- Click OK without changing anything
The values in the _Final Renderings fields are now slightly changed (still containing a diff, but "fixed") and the page may be edited i Experience Editor again.
Question:
Can we do the same work as the Ok-press on the dialog programmatically? I guess yes, but how?
(I plan to use it in a loop to fix items, but I do know how to loop items, that is not the problem in this question.)
Solution starters:
I guess we should read the existing Standard Values shared _Renderings field, the items _Renderings and _Final Renderings field. I guess into LayoutDefinition-objects.
Combine them somehow and then get the correct diffs back and write them to the field. Maybe using XmlDeltas that have been mentioned on some pages.
What I mainly need help on is how to combine them and get the correct diffs to write to _Renderings and _Final Renderings on the item.
References
Some pages i have found so far (to pages describing parts of it or related stuff):
- http://learnsitecore.cmsuniverse.net/en/Developers/Articles/2011/07/Programmatically-set-layout-in-sitecore.aspx (Just how you may modify/set the value, nothing about diffs)
- How to add rendering at a position programmatically (Just how you may modify/set the value, nothing about diffs)
- Change datasource in final layout through API (Modify final layout, but no full example?) https://doc.sitecore.net/sitecore_experience_platform/developing/developing_with_sitecore/versioned_layouts/the_versioned_layout_api_changes (About setting/getting)
- https://www.cognifide.com/our-blogs/sitecore/complex-layouts-in-sitecore-using-standard-values-hierarchy/ (some info about the diffs)
Update:
- https://jermdavis.wordpress.com/2015/07/20/editing-layout-details/ Saying that updating the values by just calling the right getter/setting will make it become a diff. But that is for _Renderings, not _Final Renderings.
The same crash as we get too: