Passing data between Sitecore renderings can get tricky.
Sending messages between sibling renderings can lead us to worry about the order in which they render, and you may end up with renderings tightly coupled to other renderings. Jeremy Davis discusses ways to switch the order of rendering execution on his blog here: https://jermdavis.wordpress.com/2016/04/04/getting-mvc-components-to-communicate/
My preferred approach is for renderings to be as isolated as possible and not need to talk to siblings. In a regular MVC site, we would instantiate a
ViewModel, and pass it down to any child (or partial) views as needed. If a child view doesn’t change this
ViewModel at all, we don’t have to worry about order of execution or changes of state.
In Sitecore, we can achieve this by wrapping child renderings in a parent Controller Rendering. This Controller Rendering creates and prepares the
ViewModel, and then passes it down to one or more child renderings.
- Our parent Controller Rendering creates and prepares a
ViewModel. This parent specifies a view, which contains one or more placeholders.
ViewModelis passed along to any child renderings currently attached to the placeholders.
- During execution, child renderings do not modify the
ViewModel. We may even consider the
ViewModelimmutable while rendering takes place.
Sitecore has a peculiarity here which makes our job difficult. Each rendering gets a new instance of ViewData – explained by Kern Herskind Nightingale here: http://stackoverflow.com/a/35210022/638064.
This puts a stop to us using
ViewData to pass our
ViewModel down from the parent rendering to child renderings.
There’s a way you can ensure that
ViewData is correctly passed down from parent to child renderings. Let’s go through how this is possible.
- In your top level controller, create a
ViewModel, which will be passed down to all child renderings.
- Add it to the
ViewDatacollection in the current
- In each child rendering, fetch the
ViewModeland add it to the local
ViewDatafor the current rendering (which will be empty at this point). View Renderings will do this step for you, so you don’t need to do anything special there
Et voila! You now have access to the same
ViewModel for each of your child renderings.
MVC offers us even better tools to remove code duplication. If you have a lot of child renderings needing access to your shared
ViewModel, adding the code in step 3 will happen a lot. Let’s refactor that to an filter attribute.
Now, we just need to add this attribute to any Action Methods who may want to access shared
ViewData from higher up in the stack
There we go. I’m sure Sitecore will amend their implementation at some point, but until then, we have an immutable, single direction