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

Get full HTML from Page

Vote:
 

Hello,
Is there a way to programmatically get the full HTML content of a page if the url or instance of the page exists?
The HTML content is read out or edited in an HttpHandler and in a ScheduledJob.

I have already tried the following approaches:
http://fellow.aagaardrasmussen.dk/2016/11/01/how-to-render-an-episerver-contentreference-via-your-webapi/
http://www.jondjones.com/learn-episerver-cms/episerver-developers-guide/episerver-customizing-episervers-ui/how-to-manually-render-a-episerver-page-or-block-using- net
https://www.eyecatch.no/blog/full-customization-of-xforms-with-episerver-7-and-mvc/
http://joelabrahamsson.com/rendercontentdata-with-support-for-rendering-tag/

Unfortunately, none of the approaches worked, in most cases it did not even jump into the controller or it did not have the layout data that would be put in by the filters.

Is there a way to get all HTML content without having to run a separate web request?

Thank you and best regards
Christian

#186241
Dec 14, 2017 13:19
Vote:
 

This way it nearly works:

        public string GetPageContent(HttpContext httpContext, string content)
        {
            var httpContextBase = new HttpContextWrapper(httpContext);

            var urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>();
            var page = urlResolver.Route(new UrlBuilder(httpContext.Request.Url));

            //Resolve the right Template based on Episervers own templating engine
            var templateResolver = ServiceLocator.Current.GetInstance<TemplateResolver>();
            var model = templateResolver.ResolvePageTemplate(httpContextBase, page);

            //Resolve the controller
            var contentController = ServiceLocator.Current.GetInstance(model.TemplateType) as ControllerBase;
            string controllerName = contentController.GetType().Name.Replace("Controller", string.Empty);

            RouteData routeData = new RouteData();
            routeData.Values.Add("currentContent", page);
            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", page.ContentLink.ID);

            //var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
            var controllerFactory = ServiceLocator.Current.GetInstance<IControllerFactory>();
            var controller = (ControllerBase)controllerFactory.CreateController(httpContextBase.Request.RequestContext, controllerName);
            var controllerContext = new ControllerContext(httpContextBase, routeData, controller);            
            var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType());

            var actionDescriptor = controllerDescriptor.FindAction(controllerContext, "Index");

            var actionViewResult = actionDescriptor.Execute(controllerContext, new Dictionary<string, object>() {{"currentPage", page }}) as ViewResult;
            var viewResult = actionViewResult.ViewEngineCollection.FindView(controllerContext, actionViewResult.ViewName, actionViewResult.MasterName);

            using (var stringWriter = new StringWriter())
            {
                var viewContext = new ViewContext(controllerContext, viewResult.View, actionViewResult.ViewData, actionViewResult.TempData, stringWriter);                
                viewResult.View.Render(viewContext, stringWriter);
                return stringWriter.ToString();
            }
        }
    }

When I start to render the action result, there is a NullReferenceException, because the IResultFilter, with is normaly set by an IInitializableModule, is not executed.

It seems, that the initiazation module is not loaded in that context. Is there a posibility to execute the module in that context or to execute the action with all filters?

Best regards

Christian

#186288
Dec 15, 2017 14:13
Vote:
 

Hi,

Why not just use HttpClient https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.118).aspx?

#186294
Edited, Dec 15, 2017 15:53
Vote:
 

Actually, I was trying to avoid an Http request because I thought it was cleaner and faster to get the html generated by code, but with the volume of calls, I'm not sure anymore if that's really faster.

#186310
Dec 16, 2017 11:54
Vote:
 

I for one think that just making an http call is much cleaner and less code is required. Why would it be slower, and is speed important here? If your website is fast already, the call will be fast as well.

#186336
Dec 18, 2017 10:01
Vote:
 

I would go with a http client call 

#186339
Dec 18, 2017 10:39
* 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.