diff --git a/src/Umbraco.Web/Mvc/ControllerExtensions.cs b/src/Umbraco.Web/Mvc/ControllerExtensions.cs
index 42b60bb410..3fa8495a72 100644
--- a/src/Umbraco.Web/Mvc/ControllerExtensions.cs
+++ b/src/Umbraco.Web/Mvc/ControllerExtensions.cs
@@ -69,23 +69,28 @@ namespace Umbraco.Web.Mvc
return sw.ToString().Trim();
}
}
-
+
///
/// Renders the partial view to string.
///
/// The controller context.
/// Name of the view.
/// The model.
+ /// true if it is a Partial view, otherwise false for a normal view
///
- internal static string RenderPartialViewToString(this ControllerBase controller, string viewName, object model)
+ internal static string RenderViewToString(this ControllerBase controller, string viewName, object model, bool isPartial = false)
{
+ if (controller.ControllerContext == null)
+ throw new ArgumentException("The controller must have an assigned ControllerContext to execute this method.");
controller.ViewData.Model = model;
- using (StringWriter sw = new StringWriter())
+ using (var sw = new StringWriter())
{
- ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
- ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
+ var viewResult = !isPartial
+ ? ViewEngines.Engines.FindView(controller.ControllerContext, viewName, null)
+ : ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
+ var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs
index 30483cd022..dc65b726b3 100644
--- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs
+++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs
@@ -65,13 +65,11 @@ namespace Umbraco.Web.Mvc
{
throw new NullReferenceException("There is not current PublishedContentRequest, it must be initialized before the RenderRouteHandler executes");
}
-
- var renderModel = new RenderModel(docRequest.PublishedContent, docRequest.Culture);
-
- //put essential data into the data tokens, the 'umbraco' key is required to be there for the view engine
- requestContext.RouteData.DataTokens.Add("umbraco", renderModel); //required for the RenderModelBinder
- requestContext.RouteData.DataTokens.Add("umbraco-doc-request", docRequest); //required for RenderMvcController
- requestContext.RouteData.DataTokens.Add("umbraco-context", UmbracoContext); //required for UmbracoTemplatePage
+
+ SetupRouteDataForRequest(
+ new RenderModel(docRequest.PublishedContent, docRequest.Culture),
+ requestContext,
+ docRequest);
return GetHandlerForRoute(requestContext, docRequest);
@@ -79,6 +77,20 @@ namespace Umbraco.Web.Mvc
#endregion
+ ///
+ /// Ensures that all of the correct DataTokens are added to the route values which are all required for rendering front-end umbraco views
+ ///
+ ///
+ ///
+ ///
+ internal void SetupRouteDataForRequest(RenderModel renderModel, RequestContext requestContext, PublishedContentRequest docRequest)
+ {
+ //put essential data into the data tokens, the 'umbraco' key is required to be there for the view engine
+ requestContext.RouteData.DataTokens.Add("umbraco", renderModel); //required for the RenderModelBinder and view engine
+ requestContext.RouteData.DataTokens.Add("umbraco-doc-request", docRequest); //required for RenderMvcController
+ requestContext.RouteData.DataTokens.Add("umbraco-context", UmbracoContext); //required for UmbracoTemplatePage
+ }
+
///
/// Checks the request and query strings to see if it matches the definition of having a Surface controller
/// posted value, if so, then we return a PostedDataProxyInfo object with the correct information.
diff --git a/src/Umbraco.Web/Routing/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs
similarity index 75%
rename from src/Umbraco.Web/Routing/TemplateRenderer.cs
rename to src/Umbraco.Web/Templates/TemplateRenderer.cs
index 55abfa2924..ce2da96730 100644
--- a/src/Umbraco.Web/Routing/TemplateRenderer.cs
+++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs
@@ -1,23 +1,21 @@
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Web;
using System.Web.Compilation;
+using System.Web.Mvc;
+using System.Web.Routing;
using Umbraco.Core;
+using Umbraco.Web.Models;
+using Umbraco.Web.Mvc;
+using Umbraco.Web.Routing;
using umbraco;
-using System.Linq;
-namespace Umbraco.Web.Routing
+namespace Umbraco.Web.Templates
{
///
/// This is used purely for the RenderTemplate functionality in Umbraco
///
///
- /// Currently the only place where you can use RenderTemplate is from within the library class (which is legacy)
- /// but i guess we still need to support it. In order to do that we need to be able to render both an MVC and Webforms
- /// template. So we will do a Server.Execute to execute this handler, this will then need to find put the 'id' request through
- /// the routing logic again, the execute the correct handler.
- /// Its is pretty round about but is required.
+ /// This allows you to render either an MVC or Webforms template based purely off of a node id and an optional alttemplate id as string output.
///
internal class TemplateRenderer
{
@@ -27,21 +25,23 @@ namespace Umbraco.Web.Routing
private PublishedContentRequest _oldPublishedContentRequest;
private object _oldAltTemplate;
- public TemplateRenderer(UmbracoContext umbracoContext)
+ public TemplateRenderer(UmbracoContext umbracoContext, int pageId, int? altTemplateId)
{
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
+ PageId = pageId;
+ AltTemplate = altTemplateId;
_umbracoContext = umbracoContext;
}
///
/// Gets/sets the page id for the template to render
///
- public int PageId { get; set; }
+ public int PageId { get; private set; }
///
/// Gets/sets the alt template to render if there is one
///
- public int? AltTemplate { get; set; }
+ public int? AltTemplate { get; private set; }
public void Render(StringWriter writer)
{
@@ -103,7 +103,7 @@ namespace Umbraco.Web.Routing
RestoreItems();
}
- private void ExecuteTemplateRendering(StringWriter sw, PublishedContentRequest contentRequest)
+ private void ExecuteTemplateRendering(TextWriter sw, PublishedContentRequest contentRequest)
{
//NOTE: Before we used to build up the query strings here but this is not necessary because when we do a
// Server.Execute in the TemplateRenderer, we pass in a 'true' to 'preserveForm' which automatically preserves all current
@@ -112,11 +112,29 @@ namespace Umbraco.Web.Routing
//var queryString = _umbracoContext.HttpContext.Request.QueryString.AllKeys
// .ToDictionary(key => key, key => context.Request.QueryString[key]);
-
+
switch (contentRequest.RenderingEngine)
{
case RenderingEngine.Mvc:
- throw new NotImplementedException("Currently the TemplateRender does not support rendering MVC templates");
+ var requestContext = new RequestContext(_umbracoContext.HttpContext, new RouteData()
+ {
+ Route = RouteTable.Routes["Umbraco_default"]
+ });
+ var routeHandler = new RenderRouteHandler(ControllerBuilder.Current.GetControllerFactory(), _umbracoContext);
+ var routeDef = routeHandler.GetUmbracoRouteDefinition(requestContext, contentRequest);
+ var renderModel = new RenderModel(contentRequest.PublishedContent, contentRequest.Culture);
+ //manually add the action/controller, this is required by mvc
+ requestContext.RouteData.Values.Add("action", routeDef.ActionName);
+ requestContext.RouteData.Values.Add("controller", routeDef.ControllerName);
+ //add the rest of the required route data
+ routeHandler.SetupRouteDataForRequest(renderModel, requestContext, contentRequest);
+ //create and assign the controller context
+ routeDef.Controller.ControllerContext = new ControllerContext(requestContext, routeDef.Controller);
+ //render as string
+ var stringOutput = routeDef.Controller.RenderViewToString(
+ routeDef.ActionName,
+ renderModel);
+ sw.Write(stringOutput);
break;
case RenderingEngine.WebForms:
default:
@@ -126,7 +144,8 @@ namespace Umbraco.Web.Routing
// to build up the url again, it will just work.
_umbracoContext.HttpContext.Server.Execute(webFormshandler, sw, true);
break;
- }
+ }
+
}
private void SetNewItemsOnContextObjects(PublishedContentRequest contentRequest)
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 9c98dee1ef..5d8846ba5d 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -312,7 +312,7 @@
-
+
ASPXCodeBehind
diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs
index 4be9eba95f..a8a9c69466 100644
--- a/src/Umbraco.Web/UmbracoHelper.cs
+++ b/src/Umbraco.Web/UmbracoHelper.cs
@@ -17,6 +17,7 @@ using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
+using Umbraco.Web.Routing;
using Umbraco.Web.Templates;
using umbraco;
using System.Collections.Generic;
@@ -63,6 +64,28 @@ namespace Umbraco.Web
}
}
+ ///
+ /// Renders the template for the specified pageId and an optional altTemplateId
+ ///
+ ///
+ /// If not specified, will use the template assigned to the node
+ ///
+ public IHtmlString RenderTemplate(int pageId, int? altTemplateId = null)
+ {
+ var templateRenderer = new TemplateRenderer(_umbracoContext, pageId, altTemplateId);
+ using (var sw = new StringWriter())
+ {
+ try
+ {
+ templateRenderer.Render(sw);
+ }
+ catch(Exception ex)
+ {
+ sw.Write("", pageId, ex);
+ }
+ return new HtmlString(sw.ToString());
+ }
+ }
#region RenderMacro
diff --git a/src/Umbraco.Web/umbraco.presentation/library.cs b/src/Umbraco.Web/umbraco.presentation/library.cs
index 0d8f413a58..8a78f77168 100644
--- a/src/Umbraco.Web/umbraco.presentation/library.cs
+++ b/src/Umbraco.Web/umbraco.presentation/library.cs
@@ -12,6 +12,7 @@ using System.Xml.XPath;
using Umbraco.Core;
using Umbraco.Web;
using Umbraco.Web.Routing;
+using Umbraco.Web.Templates;
using umbraco.BusinessLogic;
using umbraco.cms.businesslogic;
using umbraco.cms.businesslogic.media;
@@ -1105,25 +1106,21 @@ namespace umbraco
{
if (!UmbracoContext.Current.LiveEditingContext.Enabled)
{
- var sw = new StringWriter();
-
- try
- {
- var altTemplate = TemplateId == -1 ? null : (int?)TemplateId;
- var templateRenderer = new TemplateRenderer(Umbraco.Web.UmbracoContext.Current)
+ using (var sw = new StringWriter())
+ {
+ try
{
- PageId = PageId,
- AltTemplate = altTemplate
- };
- templateRenderer.Render(sw);
- }
- catch (Exception ee)
- {
- sw.Write("", ee);
- }
-
- return sw.ToString();
+ var altTemplate = TemplateId == -1 ? null : (int?)TemplateId;
+ var templateRenderer = new TemplateRenderer(Umbraco.Web.UmbracoContext.Current, PageId, altTemplate);
+ templateRenderer.Render(sw);
+ }
+ catch (Exception ee)
+ {
+ sw.Write("", PageId, ee);
+ }
+ return sw.ToString();
+ }
}
else
{
@@ -1136,10 +1133,14 @@ namespace umbraco
var p = new page(((IHasXmlNode)GetXmlNodeById(PageId.ToString()).Current).GetNode());
p.RenderPage(TemplateId);
var c = p.PageContentControl;
- var sw = new StringWriter();
- var hw = new HtmlTextWriter(sw);
- c.RenderControl(hw);
- return sw.ToString();
+
+ using (var sw = new StringWriter())
+ using(var hw = new HtmlTextWriter(sw))
+ {
+ c.RenderControl(hw);
+ return sw.ToString();
+ }
+
}
}