World is now on Opti ID! Learn more

Jonas Bergqvist
Nov 5, 2012
  6722
(0 votes)

EPiServer MVC content rendering – Part 2

Some days ago I wrote the part 1 of rendering MVC content. I got a comment about the example content types, that they were strange implemented. I agree that it looks strange, how I use the block in the example, but it should be looked at as an “Hello World” example, and I just want to demonstrate how the rendering of a block works.

ControllerTypeControllerFactory

One thing I forgot in the last post was that we register an IControllerFactory in the CMS, to return controllers we have resolved with the “TemplateResolver” directly. You can find the logic in the “EPiServer.Web.Mvc.ControllerTypeControllerFactory.GetControllerType” with the reflector if you’re interested.

Render controller action

When the index action in the controller “BasicPageController” gets called, MVC will try to resolve the “BasicPage” type argument. This would not have worked out of the box without the “ContentDataModelBinder” (in the “EPiServer.Web.Mvc namespace”).

ContentDataModelBinder

The ContentDataModelBinder will look if the name of the parameter is “currentPage”, “currentBlock”, or “currentContent”. If it is one of them, it will try to get the current Page/Block/Content from the “DataTokens” in the “RouteData”.

In this case, we use the “currentPage” as parameter name, and the current page will be found in the “DataTokens” list. The current page will then simply be loaded from the content area, and the PageData will be returned from the “BindModel” method.

Edit hints

In the Index action, we start by creating an instance of the “BasicPageModel” and set it’s properties. Then we create an editing hits instance, by calling the extension method “GetEditHints<TModel, TContentType>”. We do this because the “MainBody” property in the content type has another name in the model (“Body”). By adding a connection between those, we make sure the on page edit will work as the editor expect.

Calling the view

When calling the default view (“Index"), with the view model, MVC will look for a folder with the same name as the controller name in the “RouteData” instance. In this case the folder name it looks for is “BasicPage”, and it will find a index view in that folder.

PropertyFor

The view contains three different “PropertyFor” calls, one for a string, one for a XhtmlString”, and one for a block.

The “PropertyFor” extension method are a wrapper of the MVC build in helper “DisplayFor”. Everything you normaly can do with “DisplayFor” are possible to do with “PropertyFor”. The difference are mainly that the “PropertyFor” will make the “on page edit” work.

Render string

MVC will look after a partial view handling “string”. By default, we have no partial view for this type, and we will therefor make an “ToString()” call for the property instead. This works for this type. behaviour can be overridden by adding a partial view with the name “String” in your MVC project that handles string”.

Render XhtmlString

MVC will look after a partial view handling “XhtmlString”. We have a default partial view with that name, that will call the extension method “RenderXhtmlString”. This behaviour can be overridden by adding a partial view with the name “XhtmlString” in your MVC project that handles “EPiServer.Core.XhtmlString”.

Render block

MVC will look after a partial view handling “BlockData”. We have a default partial view named “ContentData” that handles “ContentData”. This will be called becouse BlockData inherits from ContentData. This behaviour can be overridden by adding a partial view with the name “BlockData” or ContentData in your MVC project that handles BlockData/ContentData.

The "ContentData” view will call the html helper “RenderContentData”.

RenderContentData

By default, the html helper “RenderContentData” will be used when DisplayFor or PropertyFor are used for a property in a view.

The extension method will first use the “TemplateResolver” to figure out what template that should handle the content. Then it will call the “MvcContentRenderer” class (EPiServer.Web.Mvc namespace), which will use the template to render the content.

MvcContentRenderer

The render method in the “MvcContentRenderer” will first look if the template the “TemplateResolver” returned are a partial view. If it is a partial view, it means that it doesn't use any controller, and the view should be called directly.

In case the tamplate is a partial view, the “ViewEngine” will be used to call it. This is the fast way of rendering content. If it’s not a partial view, we will call the html helper method “RenderAction” instead, which will look for the controller, resolved by the “TemplateResolver”. When calling the “RenderAction”, we will add the content (in this case the block) to the “RouteValueCollection” with key “currentContent”.

BlockController

Just as for the page controller, the block controller have the block type as a parameter. The parameter are named “currentBlock” in this example, but it could also have hade the name “currentContent”. The same model binder as the one resolved the PageData object will now resolve the BlockData object in almost the same way.

This time, the model binder will not find any node to use, instead it will find a value for the key “currentContent”, and the binder will return the content (in this case the block) to the parameter.

Partial view

The block controller will look for a partial view in the same way as it does for a view. The block view in this example just outputs the Heading and the Body, just as the page, and that is done exactly in the same way as for the page.

Nov 05, 2012

Comments

Please login to comment.
Latest blogs
Make Global Assets Site- and Language-Aware at Indexing Time

I had a support case the other day with a question around search on global assets on a multisite. This is the result of that investigation. This co...

dada | Jun 26, 2025

The remote server returned an error: (400) Bad Request – when configuring Azure Storage for an older Optimizely CMS site

How to fix a strange issue that occurred when I moved editor-uploaded files for some old Optimizely CMS 11 solutions to Azure Storage.

Tomas Hensrud Gulla | Jun 26, 2025 |

Enable Opal AI for your Optimizely products

Learn how to enable Opal AI, and meet your infinite workforce.

Tomas Hensrud Gulla | Jun 25, 2025 |

Deploying to Optimizely Frontend Hosting: A Practical Guide

Optimizely Frontend Hosting is a cloud-based solution for deploying headless frontend applications - currently supporting only Next.js projects. It...

Szymon Uryga | Jun 25, 2025

World on Opti ID

We're excited to announce that world.optimizely.com is now integrated with Opti ID! What does this mean for you? New Users:  You can now log in wit...

Patrick Lam | Jun 22, 2025

Avoid Scandinavian Letters in File Names in Optimizely CMS

Discover how Scandinavian letters in file names can break media in Optimizely CMS—and learn a simple code fix to automatically sanitize uploads for...

Henning Sjørbotten | Jun 19, 2025 |