The lazy way
var relativUrl = EPiServer.Web.Routing.UrlResolver.Current.GetUrl(pageReference, null, new EPiServer.Web.Routing.VirtualPathArguments { ContextMode = EPiServer.Web.ContextMode.Default }); var url = new Uri(UriSupport.SiteUrl, relativUrl); var htmlStr = string.Empty; using (var client = new WebClient()) { htmlStr = client.DownloadString(url); }
It depends a little on what MVC version you are using, there are a lot of questions like this on stackoverflow
MVC5
http://stackoverflow.com/questions/23494741/mvc-5-render-view-to-string
MVC2
http://stackoverflow.com/questions/483091/render-a-view-as-a-string
Here it is a little more explained
http://www.codemag.com/Article/1312081
Thanks guys, I have found out how to render the view thanks to stack but I still need answer on how to get the controller from a page reference, and to get the context right of that controller.
Hi Johan!
About gettting the controller, I think you should be able to go along these lines.
var myRef = currentPage.ContentLink; var httpContext = default(HttpContextBase); var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>(); var typeRepo = ServiceLocator.Current.GetInstance<IContentTypeRepository>(); var templateRepo = ServiceLocator.Current.GetInstance<TemplateResolver>(); var content = contentLoader.Get<IContent>(myRef); var type = typeRepo.Load(content.ContentTypeID); var template = templateRepo.Resolve(httpContext, type, TemplateTypeCategories.MvcController); var controllerName = template.Name.EndsWith("Controller", StringComparison.InvariantCultureIgnoreCase) ? template.Name.Substring(0, template.Name.LastIndexOf("Controller", StringComparison.InvariantCultureIgnoreCase)) : template.Name;
Depending on how you're running it the context part could be tricky though..
Cheers,
//Patrick
I wrote something to render EPiServer pages as a child action. :
using System.Globalization; using System.IO; using System.Web.Routing; using EPiServer.Core; using EPiServer.Web; using EPiServer.Web.Routing; public class MvcPageDataRenderer { private readonly TemplateResolver templateResolver; public MvcPageDataRenderer(TemplateResolver templateResolver) { this.templateResolver = templateResolver; } public string ExecuteChildRequest(RequestContext existingRequestContext, PageData pageToRender, string preferredLanguageToRender) { var templateModel = this.templateResolver.ResolveMvcTemplate(existingRequestContext.HttpContext, pageToRender); existingRequestContext.SetController(templateModel.TemplateType.Name.Replace("Controller", string.Empty)); existingRequestContext.SetControllerType(templateModel.TemplateType); existingRequestContext.SetContentLink(pageToRender.ContentLink); existingRequestContext.SetRoutedData(pageToRender); existingRequestContext.SetContextMode(ContextMode.Default); existingRequestContext.RouteData.Values["action"] = "Index"; existingRequestContext.RouteData.DataTokens["namespaces"] = new[] { templateModel.TemplateType.Namespace }; if (!string.IsNullOrWhiteSpace(preferredLanguageToRender)) { existingRequestContext.SetLanguage(preferredLanguageToRender); EPiServer.BaseLibrary.Context.Current["EPiServer:ContentLanguage"] = new CultureInfo(preferredLanguageToRender); } var handler = new ChildActionHandler(existingRequestContext); using (var stringWriter = new StringWriter(CultureInfo.CurrentCulture)) { existingRequestContext.HttpContext.Server.Execute(handler, stringWriter, true); return stringWriter.ToString(); } } } using System; using System.Web; using System.Web.Mvc; using System.Web.Routing; using System.Web.UI; /// <summary> /// Shamelessly "inspired" by classes in System.Web.Mvc assembly /// It appears that only a System.Web.UI.Page can be executed /// as a child request. If you try to execute an MvcHandler /// directly an exception (with no detail) is thrown /// </summary> internal class ChildActionHandler : Page, IHttpAsyncHandler { internal class ChildActionMvcHandler : MvcHandler { public ChildActionMvcHandler(RequestContext context) : base(context) { } protected override void AddVersionHeader(HttpContextBase httpContext) { } } private readonly ChildActionMvcHandler mvcHandler; public ChildActionHandler(RequestContext context) { this.mvcHandler = new ChildActionMvcHandler(context); } public override void ProcessRequest(HttpContext context) { ((IHttpHandler)this.mvcHandler).ProcessRequest(context); } public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData) { return ((IHttpAsyncHandler)this.mvcHandler).BeginProcessRequest(context, cb, extraData); } public void EndProcessRequest(IAsyncResult result) { ((IHttpAsyncHandler)this.mvcHandler).EndProcessRequest(result); } }
I want to render a view to a string, given a PageReference. So I need to:
1) Find the controller associated with the page type
2) Get an instance to the controller with correct controller context (node and language)
3) Render the view as a string
How can I achieve this?