Sitecore MVC ViewContext Stack Diagram and Introduction
There are a couple important stacks provided by the Sitecore MVC ContextService API. The ViewContext stack is one of the more useful when you are trying to share data between a view rendering and a controller or across multiple view renderings.
Sitecore MVC ViewContext Stack Diagram and Introduction
There are a couple important stacks provided by the Sitecore MVC ContextService API. The ViewContext stack is one of the more useful when you are trying to share data between a view rendering and a controller or across multiple view renderings.
David Morrison Twitter: @dmo_sc Diagram 1 View Context Stack View Layout View Context View Rendering 2 View Context View Rendering 3 View Context View Rendering 1 View Context View Data View Rendering 1 View Context Model Shared View Data Dictionary Any Model IRendering Model IRendering Model IRendering Model IRendering Model Sitecore Controller View Context View Rendering 1 Placeholder: Main Sitecore MVC View Context Stack Rev 02 David Morrison Twitter: @dmo_sc View Data View Bag View Layout View Context Model Create Placeholder: Main View Layout Sitecore Controller View Context Sitecore Controller View Data View Bag Model View Bag Create Placeholder: PH1 View Data View Rendering 1 View Context Model View Rendering 1 Placeholder: Main View Data View Bag View Rendering 2 View Context Model Create Placeholder: PH2 View Rendering 2 Placeholder: PH1 View Data View Bag View Rendering 3 View Context Model View Rendering 3 Placeholder: PH2
Introduction There are a couple important stacks provided by the Sitecore MVC ContextService API. The ViewContext stack is one of the more useful when you are trying to share data between a view rendering and a controller or across multiple view renderings. The ContextService API is worthy of its own discussion but this introduction will focus on just one stack. Sitecore MVC brings the dynamic placeholder rendering pattern to MVC and with it new conventions that developers need to know. The View Context stack plays an integral part by keeping track of the hierarchy of ViewContext objects created by the recursive nature of layouts, placeholders and renderings used to create a complex tree of HTML output. The ViewContext stack is available as a list using the following syntax Sitecore.Mvc.Common.ContextService.Get().GetInstances<ViewContext>() In Microsoft MVC, the ViewContext object is used for passing data from the controller to the desired view, typically by populating a model. The controller action sets the Model property to the desired view model and any other data in the view data dictionary. The view is rendered by the Razor rendering engine and the view model properties and view data dictionary are used to output HTML. Sitecore MVC provides a default route and controller implementation so that you dont need to unless the situation requires. You can do a lot with just the default controller. The ViewContext from the default or a custom controller is the topmost object on the ViewContext stack in the center of Diagram 1. Some applications will use a custom controller to set the Model in the ViewContext stack to be used later. Dynamic views can easily peek at the ViewContext stack to quickly get properties from the topmost or parent view models. The default controller, the presentation engine and many pipelines take care of everything up until the point where the HTML needs to be rendered. Sitecore developers are responsible at a minimum for providing Razor views and populating any view models. The mvc.getXmlLayoutDefinition pipeline determines which views to render by parsing the XML presentation settings on each content item and populating the context PageDefinition object. Sitecore MVC View Layouts and View Renderings still use a ViewContext but additional ViewContext objects are created, one for each dynamic view on the page. The dynamic views do not use a controller so the model, if defined, is initialized instead by the mvc.getModel pipeline and added to the ViewContext. All dynamic view models must implement the IRenderingModel interface. The Layout View is the first view to be rendered so its ViewContext object is always the second on the stack and second on Diagram 1. Placeholders defined in the Layout View begin the process of executing the dynamic views. The rendering process is repeated for every dynamic view in every placeholder. When the presentation engine starts to render each individual dynamic view rendering, a new ViewContext is placed on the stack. The ViewContext Model is initialized and set. When the rendering is finished, the ViewContext object is popped off the stack and the previous ViewContext object resumes its role as the context. You wouldnt want view model data from one view unintentionally spilling over into other views. On Diagram 1 this starts at the third object level and continues down as more placeholders are nested in dynamic views. Dont be distracted at this point by the multiple controller types that Sitecore MVC supports. Sitecore MVC can execute a couple different types of controllers during a single request. There is only one primary controller that follows the full MVC lifecycle. If you use the default Sitecore route, the primary controller is determined by the Sitecore route handler and CreateController pipeline. This is the same type of controller that you would expect to find in a typical Microsoft MVC project. You might be wondering about ControllerRendering items. A Controller Rendering however does not follow the full lifecycle and the result is rendered inline as a string. The primary controller and the first ViewContext on the stack is probably the most useful when just getting started. Traditionally in MVC you just have a single controller and a single primary view (followed by partial views). In Sitecore MVC, you can set a custom controller by name on the Controller field on all content items and the template standard values. By providing your own controller, views can quickly make use of the topmost ViewContext object to share data. Views can always rely on that ViewContext to be there in any view renderings and model initialization method. The code fragment below demonstrates how to get the ViewContext for the primary controller at any point during the rendering process and then get the primary view model. var topViewContext = Sitecore.Mvc.Common.ContextService.Get().GetInstances<ViewContext>().FirstOrDefault(); var topViewModel = topViewContext.ViewData.Model; It is also important to understand that every View Context object shares the same View Data dictionary even though the model is different. When a new ViewContext is created, the ViewData dictionary is set by reference from the previous ViewContext (represented in orange on Diagram 1). This allows all views to share a single view data dictionary. This dictionary is another mechanism that can be used to share data. Care must be taken to ensure that the views do not use keys that unintentionally overlap with other views. By using the view context stack correctly with the populated view models the dictionary key collision can be avoided programmatically.
ASP.NET MVC Fundamentals : Step-by-Step Instructions for Building Web Applications with ASP.NET 8, Integrating SQLite for Robust Data Handling, and Utilizing Entity Framework