diff --git a/src/Orchard/Mvc/Html/LayoutHelperExtensions.cs b/src/Orchard/Mvc/Html/LayoutHelperExtensions.cs new file mode 100644 index 000000000..41b58f685 --- /dev/null +++ b/src/Orchard/Mvc/Html/LayoutHelperExtensions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web.Mvc; +using Orchard.Mvc.ViewEngines; + +namespace Orchard.Mvc.Html { + public static class LayoutHelperExtensions { + public static void RenderBody(this HtmlHelper html) { + var layoutContext = OrchardLayoutContext.From(html.ViewContext); + html.ViewContext.HttpContext.Response.Output.Write(layoutContext.BodyContent); + } + } +} diff --git a/src/Orchard/Mvc/ViewEngines/LayoutView.cs b/src/Orchard/Mvc/ViewEngines/LayoutView.cs new file mode 100644 index 000000000..c2ec77bd0 --- /dev/null +++ b/src/Orchard/Mvc/ViewEngines/LayoutView.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Web.Mvc; + +namespace Orchard.Mvc.ViewEngines { + public class LayoutView : IView { + private IView[] _views; + + public LayoutView(IEnumerable views) { + _views = views.ToArray(); + } + + public void Render(ViewContext viewContext, TextWriter writer) { + + var orchardViewContext = OrchardLayoutContext.From(viewContext); + + for (var index = 0; index != _views.Length; ++index) + { + var view = _views[index]; + if (index == _views.Length - 1) { + view.Render(viewContext, writer); + } + else { + //TEMP: to be replaced with an efficient spooling writer + var childWriter = new StringWriter(); + view.Render(viewContext, childWriter); + orchardViewContext.BodyContent = childWriter.ToString(); + } + } + } + } +} diff --git a/src/Orchard/Mvc/ViewEngines/LayoutViewEngine.cs b/src/Orchard/Mvc/ViewEngines/LayoutViewEngine.cs new file mode 100644 index 000000000..7fd8325cf --- /dev/null +++ b/src/Orchard/Mvc/ViewEngines/LayoutViewEngine.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.Mvc; + +namespace Orchard.Mvc.ViewEngines { + public class LayoutViewEngine : IViewEngine { + private readonly ViewEngineCollection _viewEngines; + + public LayoutViewEngine(ViewEngineCollection viewEngines) { + _viewEngines = viewEngines; + } + + public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { + return new ViewEngineResult(Enumerable.Empty()); + } + + public ViewEngineResult FindView( + ControllerContext controllerContext, + string viewName, + string masterName, + bool useCache) { + + // TODO: is there an optimization around useCache for + // this implementation? since IView can't re-execute, maybe not... + + // if action returned a View with explicit master - + // this will bypass the multi-pass layout strategy + if (!string.IsNullOrEmpty(masterName)) + return new ViewEngineResult(Enumerable.Empty()); + + var bodyView = _viewEngines.FindPartialView(controllerContext, viewName); + var layoutView = _viewEngines.FindPartialView(controllerContext, "layout"); + var documentView = _viewEngines.FindPartialView(controllerContext, "document"); + + if (bodyView.View == null || + layoutView.View == null || + documentView.View == null) { + + return new ViewEngineResult( + (bodyView.SearchedLocations ?? Enumerable.Empty()) + .Concat((layoutView.SearchedLocations ?? Enumerable.Empty())) + .Concat((documentView.SearchedLocations ?? Enumerable.Empty())) + ); + } + + var view = new LayoutView(new[] { + bodyView.View, + layoutView.View, + documentView.View, + }); + + return new ViewEngineResult(view, this); + } + + public void ReleaseView(ControllerContext controllerContext, IView view) { + + } + } + + +} diff --git a/src/Orchard/Mvc/ViewEngines/OrchardLayoutContext.cs b/src/Orchard/Mvc/ViewEngines/OrchardLayoutContext.cs new file mode 100644 index 000000000..c7e31c904 --- /dev/null +++ b/src/Orchard/Mvc/ViewEngines/OrchardLayoutContext.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using System.Web.Mvc; + +namespace Orchard.Mvc.ViewEngines { + public class OrchardLayoutContext { + private static readonly object _key = typeof(OrchardLayoutContext); + + public string BodyContent { get; set; } + + public static OrchardLayoutContext From(ControllerContext context) { + return From(context.HttpContext); + } + + public static OrchardLayoutContext From(HttpContextBase context) { + if (context.Items.Contains(_key)) { + context.Items.Add(_key, new OrchardLayoutContext()); + } + return (OrchardLayoutContext)context.Items[_key]; + } + } +} diff --git a/src/Orchard/Orchard.csproj b/src/Orchard/Orchard.csproj index 361cfd95c..41200465c 100644 --- a/src/Orchard/Orchard.csproj +++ b/src/Orchard/Orchard.csproj @@ -200,6 +200,7 @@ + @@ -213,6 +214,9 @@ + + +