How to render an Episerver ContentReference via your WebApi

casper.rasmussen/ November 1, 2016/ Content Types and Properties, Episerver CMS/ 2 comments

ASP.NET MVC and the Razor Engine that is used to render Episerver content is, in combination, an excellent text and HTML template-rendering engine. Together, they make it easy to merge text, model data, and code to produce HTML output. Merging these three parts, through a WebApi, may seem odd to some people.. but it can indeed be beneficial in some (rare) instances.

Let me try and frame a situation. Your current Episerver CMS project demands a personalized dashboard, where your user are able to select and add gadgets (Episerver content blocks) amongst a predefined list- e.g. investment portfolio visuals such as stock graphs. One vital detail is, that all available gadgets cannot be rendered server-side and you are, due to performance reasons, therefore required to render them on demand. One solution to this challenge, could be to rely your front-end implementation on an exposed WebApi, where your gadget framework are able to request the rendition of a certain gadget via it’s ContentReference.

How to render an Episerver ContentReference via your WebApi

Fellow Episerver evangelists has previously surfaced an approach to do something similar. It were though assuming your ApiController where in procession of some implementation information, which inevitably will change dependent on the type of gadget – e.g. path to the view and an understanding of how to construct the view model. In my opinion, the right approach would be to mimic the actual request pipeline in Episever and MVC and thereby let the Razor viewengine, our native ASP.NET MVC controller factory and Episervers template engine manage the unknowns. Let me show you how it’s possible to achieve this.

The implementation is pretty straight forward and are, at very high level, mimicking what’s happening when Episerver and ASP.NET converts an URL, that equals a ContentReference, to digestible output. That’s of course only applicable to e.g. pages or products. First off, our requested content reference is converted to a piece of content, who’s type afterwards is the foundation for a template lookup.

//Resolve the right Template based on Episervers own templating engine
TemplateModel model = this._templateResolver.Resolve(HttpContext.Current, matchedContent.GetOriginalType(), TemplateTypeCategories.MvcPartial | TemplateTypeCategories.MvcPartialController, new string[0]);

Above snippet utilizes Episervers template engine that allows us to control a few conditions: the type of our template – in our scenario MvcPartial and MvcPartialController – and optional tags (display options). The returned result is used to build a route, which ensures our request is dispatched to correct controller for handling according to our expectations.

If we move a bit further down the code, then it again starts to get interesting when below snippet mimics the contexts required to render content according to a route. These contexts binds it all together and acts as the container for our ‘asynchronous’ rendering request – independently of the state of our current ApiController.

//Create a fake context, that can be executed based on the route
ViewContext viewContext = new ViewContext(new ControllerContext(new HttpContextWrapper(HttpContext.Current), routeData, contentController), new FakeView(), new ViewDataDictionary(), new TempDataDictionary(), new StringWriter());

One important detail in above code is, that we are required to specify a faked view, which gets no responsibility in the actual rendition.

Above implementation hopefully provided you with a way to solve my framed scenario. As always, the code has been taken out of a greater context and requires adjustments to fit in to a production scenario. One detail, which especially is important to mention, is the fact that my code relies on Episerver’s ContentLanguage.PreferredCulture.Name, which in a native WebApi context will be your fallback language – it won’t change according to your current language branch.

Dislaimer: Always remember to protect your WebApi endpoint to ensure your application is safeguarded from DDOS attacks. It may require extensive resources to render advanced content types, which during an attack could take down your production system.

2 Comments

  1. Hi, I\\’m trying to use this setup to lazy load some blocks.I have created a method on the block called \\”LazyLoad\\”.When changing:routeData.Values.Add(\\”action\\”, \\”Index\\”);to:routeData.Values.Add(\\”action\\”, \\”LazyLoad\\”);It still calls the Index method of the block.Do you have any suggestions to why that is?

  2. Hi,

    I am trying to implement this into a setup where I want to lazy-load blocks. ( Please let me know if there is a better pattern for this)

    To achieve that, I have changed “index” to a new action “lazyload”

    But the routing always execute the index method, instead of the lazyload.

    Do you have any suggestions to why this is happening?

    Do I have to implement a custom routing in Global.asax ?

Leave a Comment

Your email address will not be published. Required fields are marked *

Please type the characters of this captcha image in the input box

Please type the characters of this captcha image in the input box
You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>
*
*