Skip to content

Instantly share code, notes, and snippets.

@LucGosso
Created October 27, 2020 21:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LucGosso/5b80acab3a9d8dcf0dd1a3c6c2db712e to your computer and use it in GitHub Desktop.
Save LucGosso/5b80acab3a9d8dcf0dd1a3c6c2db712e to your computer and use it in GitHub Desktop.
Render Episerver Blocks and ContentArea for use in web api https://devblog.gosso.se/?p=1463
using EPiServer;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.Framework.Web;
using EPiServer.Globalization;
using EPiServer.Logging;
using EPiServer.ServiceLocation;
using EPiServer.Web;
using EPiServer.Web.Mvc;
using System.Collections.Generic;
using System.IO;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace Gosso.Business.Services
{
public class ContentRendererService
{
private readonly ITemplateResolver _templateResolver;
private readonly IContentLoader _contentLoader;
private readonly IContentRenderer _contentRenderer;
public ContentRendererService(ITemplateResolver templateResolver, IContentLoader contentLoader, IContentRenderer contentRenderer)
{
_templateResolver = templateResolver;
_contentLoader = contentLoader;
_contentRenderer = contentRenderer;
}
public string Render(ContentReference contentReference, IEnumerable<string> tags = null)
{
//Find the content in question
IContent matchedContent = _contentLoader.Get<IContent>(contentReference);
if (matchedContent == null)
throw new ContentNotFoundException("Content was not found");
//Resolve the right Template based on Episervers own templating engine
TemplateModel model = _templateResolver.Resolve(HttpContext.Current, matchedContent.GetOriginalType(), TemplateTypeCategories.MvcPartial | TemplateTypeCategories.MvcPartialController | TemplateTypeCategories.MvcController, tags ?? new string[0]);
//Resolve the controller
ControllerBase contentController = null;
if (model.TemplateType != null)
contentController = ServiceLocator.Current.GetInstance(model.TemplateType) as ControllerBase;
if (contentController == null) // if view without controller
contentController = new CustomController(model.Name);
//Mimic the routing of our rendition
RouteData routeData = new RouteData();
routeData.Values.Add("currentContent", matchedContent);
routeData.Values.Add("controllerType", model.TemplateType);
routeData.Values.Add("language", ContentLanguage.PreferredCulture.Name);
routeData.Values.Add("controller", model.Name.Replace("Controller", ""));
routeData.Values.Add("action", "Index");
routeData.Values.Add("node", matchedContent.ContentLink.ID);
routeData.DataTokens["contextmode"] = ContextMode.Default;//important to declare that the rendering should not be "edit"-mode, we dont want that, and it will crash
//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());
HtmlHelper helper = new HtmlHelper(viewContext, new ViewPage());
//Render in our fake context
_contentRenderer.Render(helper, new PartialRequest(), matchedContent, model);
//helper.RenderContentData(matchedContent, false);//another way to execute it
//Derive the output based on our template and view engine
return viewContext.Writer.ToString();
}
public IEnumerable<string> RenderContentToHtml(IEnumerable<ContentAreaItem> filteredItems)
{
foreach (var item in filteredItems)
{
var tag = item.LoadDisplayOption()?.Tag;
if (tag != null)
{
yield return Render(item.ContentLink, new string[1] { tag });
}
else
{
yield return Render(item.ContentLink);
}
}
}
}
public class FakeView : IView
{
public void Render(ViewContext viewContext, TextWriter writer)
{
}
}
public class CustomController : Controller
{
private readonly string name;
public CustomController(string name)
{
this.name = name;
}
public ActionResult Index()
{
return PartialView(name);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment