November Happy Hour will be moved to Thursday December 5th.

Render ContentPages manually

Vote:
 

Hi there

I am trying to build a SinglePageApplication and for that I need an WebAPI service that kan return the rendered HTML of any given EpiServer Page. But I seem to stumple into two problems:

  • Either the ContentAreas are ignored - just is printed, or
  • It tries to render the entire page with the _Layout.cshtml (and fails when trying render the first unknown Actions) even though I have specifically told it to use an empty layout that only contains the @RenderBody() part...
public IHttpActionResult Show(string url)
        {
            IContent contentReference = UrlResolver.Current.Route(new UrlBuilder(url));
            //Find the content in question
            IContent matchedContent = _contentRepository.Get(contentReference.ContentLink);

            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.Mvc, new string[0]);

            //Resolve the controller
            var contentController = ServiceLocator.Current.GetInstance(model.TemplateType) as ControllerBase;

            //Derive the name
            string controllerName = model.Name.Replace("Controller", "");
            
            //Mimic the routing of our rendition 
            var 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", controllerName);
            routeData.Values.Add("action", "Index");
            routeData.Values.Add("node", matchedContent.ContentLink.ID);
            
            //Create a fake context, that can be executed based on the route
            var controllerContext = new ControllerContext(new HttpContextWrapper(HttpContext.Current), routeData, contentController);
            var viewContext =
                new ViewContext(controllerContext, new RazorView(controllerContext, "~/Views/ContentPage/Index.cshtml", @"~/Views/Shared/Layouts/_EmptyLayout.cshtml", false, new []{".cshtml"}), new ViewDataDictionary(), new TempDataDictionary(), new StringWriter());

            var viewDataContainer = new ViewPage();
            //viewDataContainer.MasterLocation = @"~/Views/Shared/Layouts/_EmptyLayout.cshtml";
            var helper = new HtmlHelper(viewContext, viewDataContainer);

            //Render in our fake context
            _contentRenderer.Render(helper, new PartialRequest(), matchedContent, model);
            
            //Derive the output based on our template and view engine
            string html = viewContext.Writer.ToString();

            return Json(new
            {
                Html = html
            });
        }

I have found inspiration in these threads and blocks:
http://stackoverflow.com/questions/483091/render-a-view-as-a-string
http://fellow.aagaardrasmussen.dk/2016/11/01/how-to-render-an-episerver-contentreference-via-your-webapi/
http://jondjones.com/learn-episerver-cms/episerver-developers-guide/episerver-customizing-episervers-ui/how-to-manually-render-a-episerver-page-or-block-using-net

Any help would be much apreciated :-)

Thanks!

#178443
May 11, 2017 8:23
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.