In this tutorial, you will learn how to manually render a block within Episerver CMS. In most situations, you will never need to manually render a block yourself in code. Unless you have a very unusual requirement, you should normally use the standard way of rendering a block in Episerver CMS. By making use of the
ContentArea property and the
PropertyFor() helper it is pretty easy to render components on pages within Episerver. If you are new to Episerver and you are trying to figure out how to render a block, this is the approach you should take and this is not the tutorial for you. If you find yourself with a very specific need to bypass all the Episerver goodness, like trying to write a custom cache where you need to manually render a block yourself, this is the tutorial for you 🔥🔥🔥
Depending on where in the code you are trying to render a block will determine what context data and access to helpers you will have at your disposal. We will start this tutorial, by creating an action filter attribute.
How To Render A Block Using An Action Filter Attribute
Within an action attribute, you have access to the page context. Create a new class and inherit from
ActionFilterAttribute. You will need to implement two methods,
OnResultExecuted(). Both these methods get passed a parameter called
ActionExecutingContext. Using the data within this context you can manually build your own view context to render the block:
Within this attribute, we manually create a view context and return the block HTML to the response stream. We do this using a
StringWriter to store the HTML output of the block. When Episerver tries to render the block later, the output of the helper will be added to the current responses output buffer which is a stream rather than HTML rendered in a view.
In order to render a block manually, you will need access to the HTTP context object and an output stream. In this example, I am going to access this context by creating a custom HTMLHelper. A HTMLHelper takes a
ViewContext and a
ViewPage. Using properties found in the
ActionExecutingContext instance, we pass in the controller context, the view data, and our new
StringWriter. After the helper has been created, we return the HTML helper for use later on. We will use this object to access this context later when we render the block. With access to the context and the rendering stream sorted, its time to render the block.
In order to render a block, you need to get the correct template model to use with it. To do this, you can use the Episerver TemplateResolver API. I access this API via
ServiceLocator on Line 28. Ideally, you should use constructor injection, however, I am using
ServiceLocator to keep things simple for this example:
Using the page context and the Episerver content object. You can get additional rendering information from ASP.NET- about which controller and view are associated against a block. In this situation, we only care about blocks and not pages, so on Line 29, I use the
MvcPartial template type. If you get this configuration wrong, the template resolver will return
null. Be warned you may need to experiment with the input parameters a little before you get data returned.
The last thing you need to check before rendering a block is the Episerver display tag. Display tags are used for rendering blocks at different widths. You can learn more about this process in episerver here.
I access the tag on Line 8. I will not cover what this code does here, however, you can learn what it is doing from this tutorial.
The last step is to render the block. To render Episerver content you use the
IContentRenderer API. To use
IContentRenderer, you need to pass in the content, if the items are located within a content area, the template model and the content renderer object.
To get the block HTML all you need to do is call the
ToString() method on the
StringWriter and, voila, you have it 😊
The theory behind rendering the block content is quite simple. We create a new instance of HTMLHelper, create a stream writer, then call the Episerver extension to render the block passing in the correct template resolver. Happy Coding 🤘