Less broken than ever

Layout component injected by themed result filter
Composes three stage rendering
Obsoletes additional rendering placeholder components
Additional csproj files renamed to avoid broken modules from being included in view compilation
A dynamic language in views would be nice

--HG--
branch : theming
This commit is contained in:
Louis DeJardin
2010-09-03 18:58:24 -07:00
parent b09a276e97
commit 39cbf42c5a
11 changed files with 137 additions and 81 deletions

View File

@@ -43,7 +43,7 @@ namespace Orchard.Setup {
builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>().InstancePerLifetimeScope(); builder.RegisterType<ModelBinderPublisher>().As<IModelBinderPublisher>().InstancePerLifetimeScope();
builder.RegisterType<WebFormViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope(); builder.RegisterType<WebFormViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope();
builder.RegisterType<RazorViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope(); builder.RegisterType<RazorViewEngineProvider>().As<IViewEngineProvider>().InstancePerLifetimeScope();
builder.RegisterType<CurrentThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope(); builder.RegisterType<ThemedViewResultFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
builder.RegisterType<ThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope(); builder.RegisterType<ThemeFilter>().As<IFilterProvider>().InstancePerLifetimeScope();
builder.RegisterType<PageTitleBuilder>().As<IPageTitleBuilder>().InstancePerLifetimeScope(); builder.RegisterType<PageTitleBuilder>().As<IPageTitleBuilder>().InstancePerLifetimeScope();
builder.RegisterType<PageClassBuilder>().As<IPageClassBuilder>().InstancePerLifetimeScope(); builder.RegisterType<PageClassBuilder>().As<IPageClassBuilder>().InstancePerLifetimeScope();
@@ -70,6 +70,7 @@ namespace Orchard.Setup {
builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>(); builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>();
builder.RegisterType<ThemeAwareViewEngine>().As<IThemeAwareViewEngine>(); builder.RegisterType<ThemeAwareViewEngine>().As<IThemeAwareViewEngine>();
builder.RegisterType<LayoutAwareViewEngine>().As<ILayoutAwareViewEngine>();
builder.RegisterType<ConfiguredEnginesCache>().As<IConfiguredEnginesCache>(); builder.RegisterType<ConfiguredEnginesCache>().As<IConfiguredEnginesCache>();
} }

View File

@@ -1,61 +0,0 @@
using System.IO;
using System.Web.Mvc;
using Orchard.Mvc.ViewModels;
namespace Orchard.Mvc.ViewEngines {
public class LayoutView : IView {
private readonly LayoutViewEngine _viewEngine;
private ViewEngineResult[] _viewEngineResults;
public LayoutView(LayoutViewEngine viewEngine, ViewEngineResult[] views) {
_viewEngine = viewEngine;
_viewEngineResults = views;
}
public void Render(ViewContext viewContext, TextWriter writer) {
using (_viewEngine.CreateScope(viewContext)) {
var layoutViewContext = LayoutViewContext.From(viewContext);
for (var index = 0; index != _viewEngineResults.Length; ++index) {
bool isFirst = index == 0;
bool isLast = index == _viewEngineResults.Length - 1;
var effectiveWriter = isLast ? viewContext.Writer : new StringWriter();
var effectiveViewData = isFirst ? viewContext.ViewData : CoerceViewData(viewContext.ViewData);
var viewEngineResult = _viewEngineResults[index];
var effectiveContext = new ViewContext(
viewContext,
viewEngineResult.View,
effectiveViewData,
viewContext.TempData,
effectiveWriter);
viewEngineResult.View.Render(effectiveContext, effectiveWriter);
if (!isLast)
layoutViewContext.BodyContent = effectiveWriter.ToString();
}
}
}
private static ViewDataDictionary CoerceViewData(ViewDataDictionary dictionary) {
#if REFACTORING
if (dictionary.Model is BaseViewModel)
return dictionary;
return new ViewDataDictionary<BaseViewModel>(BaseViewModel.From(dictionary));
#else
return dictionary;
#endif
}
public void ReleaseViews(ControllerContext context) {
foreach (var viewEngineResult in _viewEngineResults) {
viewEngineResult.ViewEngine.ReleaseView(context, viewEngineResult.View);
}
}
}
}

View File

@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Web.Mvc;
namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
public interface ILayoutAwareViewEngine : IDependency, IViewEngine {
}
public class LayoutAwareViewEngine : ILayoutAwareViewEngine {
private readonly IThemeAwareViewEngine _themeAwareViewEngine;
public LayoutAwareViewEngine(IThemeAwareViewEngine themeAwareViewEngine) {
_themeAwareViewEngine = themeAwareViewEngine;
}
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) {
return _themeAwareViewEngine.FindPartialView(controllerContext, partialViewName, useCache, true);
}
public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) {
var bodyView = _themeAwareViewEngine.FindPartialView(controllerContext, viewName, useCache, true);
var layoutView = _themeAwareViewEngine.FindPartialView(controllerContext, "Layout", useCache, true);
var documentView = _themeAwareViewEngine.FindPartialView(controllerContext, "Document", useCache, true);
if (bodyView.View == null ||
layoutView.View == null ||
documentView.View == null) {
var missingTemplatesResult = new ViewEngineResult(
(bodyView.SearchedLocations ?? Enumerable.Empty<string>())
.Concat((layoutView.SearchedLocations ?? Enumerable.Empty<string>()))
.Concat((documentView.SearchedLocations ?? Enumerable.Empty<string>()))
);
return missingTemplatesResult;
}
var view = new LayoutView(new[] {
bodyView,
layoutView,
documentView,
});
return new ViewEngineResult(view, this);
}
public void ReleaseView(ControllerContext controllerContext, IView view) {
var layoutView = (LayoutView)view;
layoutView.ReleaseViews(controllerContext);
}
class LayoutView : IView {
private readonly ViewEngineResult[] _viewEngineResults;
public LayoutView(ViewEngineResult[] viewEngineResults) {
_viewEngineResults = viewEngineResults;
}
public void Render(ViewContext viewContext, TextWriter writer) {
var layoutViewContext = LayoutViewContext.From(viewContext);
for (var index = 0; index != _viewEngineResults.Length; ++index) {
bool isFirst = index == 0;
bool isLast = index == _viewEngineResults.Length - 1;
var effectiveWriter = isLast ? viewContext.Writer : new StringWriter();
var effectiveViewData = isFirst ? viewContext.ViewData : CoerceViewData(viewContext.ViewData);
var viewEngineResult = _viewEngineResults[index];
var effectiveContext = new ViewContext(
viewContext,
viewEngineResult.View,
effectiveViewData,
viewContext.TempData,
effectiveWriter);
viewEngineResult.View.Render(effectiveContext, effectiveWriter);
if (!isLast)
layoutViewContext.BodyContent = effectiveWriter.ToString();
}
}
private static ViewDataDictionary CoerceViewData(ViewDataDictionary dictionary) {
return dictionary;
}
public void ReleaseViews(ControllerContext context) {
foreach (var viewEngineResult in _viewEngineResults) {
viewEngineResult.ViewEngine.ReleaseView(context, viewEngineResult.View);
}
}
}
}
}

View File

@@ -7,7 +7,9 @@ using Orchard.Environment.Extensions;
using Orchard.Themes; using Orchard.Themes;
namespace Orchard.Mvc.ViewEngines.ThemeAwareness { namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
public interface IThemeAwareViewEngine : IDependency, IViewEngine { public interface IThemeAwareViewEngine : IDependency {
ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache, bool useDeepPaths);
ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache, bool useDeepPaths);
} }
public class ThemeAwareViewEngine : IThemeAwareViewEngine { public class ThemeAwareViewEngine : IThemeAwareViewEngine {
@@ -31,24 +33,33 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
_shellDescriptor = shellDescriptor; _shellDescriptor = shellDescriptor;
} }
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache, bool useDeepPaths) {
IViewEngine engines = _nullEngines; var engines = _nullEngines;
if (partialViewName.StartsWith("/") || partialViewName.StartsWith("~")) { if (partialViewName.StartsWith("/") || partialViewName.StartsWith("~")) {
engines = BareEngines(); engines = BareEngines();
} }
else if (_workContext.CurrentTheme != null) { else if (_workContext.CurrentTheme != null) {
if (controllerContext is ViewContext) { engines = useDeepPaths ? DeepEngines(_workContext.CurrentTheme) : ShallowEngines(_workContext.CurrentTheme);
engines = ShallowEngines(_workContext.CurrentTheme);
}
else {
engines = DeepEngines(_workContext.CurrentTheme);
}
} }
return engines.FindPartialView(controllerContext, partialViewName, useCache); return engines.FindPartialView(controllerContext, partialViewName, useCache);
} }
public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache, bool useDeepPaths) {
var engines = _nullEngines;
if (viewName.StartsWith("/") || viewName.StartsWith("~")) {
engines = BareEngines();
}
else if (_workContext.CurrentTheme != null) {
engines = useDeepPaths ? DeepEngines(_workContext.CurrentTheme) : ShallowEngines(_workContext.CurrentTheme);
}
return engines.FindView(controllerContext, viewName, masterName, useCache);
}
private IViewEngine BareEngines() { private IViewEngine BareEngines() {
return _configuredEnginesCache.BindBareEngines(() => new ViewEngineCollectionWrapper(_viewEngineProviders.Select(vep => vep.CreateBareViewEngine()))); return _configuredEnginesCache.BindBareEngines(() => new ViewEngineCollectionWrapper(_viewEngineProviders.Select(vep => vep.CreateBareViewEngine())));
} }
@@ -75,10 +86,6 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
}); });
} }
public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) {
return FindPartialView(controllerContext, viewName, useCache);
}
public void ReleaseView(ControllerContext controllerContext, IView view) { public void ReleaseView(ControllerContext controllerContext, IView view) {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@@ -13,15 +13,15 @@ namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) { public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) {
return Forward( return Forward(
controllerContext, controllerContext,
dve => dve.FindPartialView(controllerContext, partialViewName, useCache), dve => dve.FindPartialView(controllerContext, partialViewName, useCache, false /*useDeepPaths*/),
EmptyViewEngineResult); EmptyViewEngineResult);
} }
public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) {
return Forward( return Forward(
controllerContext, controllerContext,
dve => dve.FindView(controllerContext, viewName, masterName, useCache), dve => dve.FindView(controllerContext, viewName, masterName, useCache, false /*useDeepPaths*/),
EmptyViewEngineResult); EmptyViewEngineResult);
} }

View File

@@ -5,22 +5,32 @@ using Orchard.Themes;
namespace Orchard.Mvc.ViewEngines.ThemeAwareness { namespace Orchard.Mvc.ViewEngines.ThemeAwareness {
public class CurrentThemeFilter : FilterProvider, IResultFilter { public class ThemedViewResultFilter : FilterProvider, IResultFilter {
private readonly IThemeService _themeService; private readonly IThemeService _themeService;
private readonly WorkContext _workContext; private readonly WorkContext _workContext;
private readonly ILayoutAwareViewEngine _layoutAwareViewEngine;
public CurrentThemeFilter(IThemeService themeService, WorkContext workContext) { public ThemedViewResultFilter(IThemeService themeService, WorkContext workContext, ILayoutAwareViewEngine layoutAwareViewEngine) {
_themeService = themeService; _themeService = themeService;
_workContext = workContext; _workContext = workContext;
_layoutAwareViewEngine = layoutAwareViewEngine;
Logger = NullLogger.Instance; Logger = NullLogger.Instance;
} }
public ILogger Logger { get; set; } public ILogger Logger { get; set; }
public void OnResultExecuting(ResultExecutingContext filterContext) { public void OnResultExecuting(ResultExecutingContext filterContext) {
var viewResultBase = filterContext.Result as ViewResultBase;
if (viewResultBase == null) {
return;
}
if (_workContext.CurrentTheme == null) { if (_workContext.CurrentTheme == null) {
_workContext.CurrentTheme = _themeService.GetRequestTheme(filterContext.RequestContext); _workContext.CurrentTheme = _themeService.GetRequestTheme(filterContext.RequestContext);
} }
viewResultBase.ViewEngineCollection = new ViewEngineCollection(new[] { _layoutAwareViewEngine });
#if REFACTORING #if REFACTORING
var viewResultBase = filterContext.Result as ViewResultBase; var viewResultBase = filterContext.Result as ViewResultBase;
if (viewResultBase == null) { if (viewResultBase == null) {

View File

@@ -140,6 +140,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ConfiguredEnginesCache.cs" /> <Compile Include="Mvc\ViewEngines\ThemeAwareness\ConfiguredEnginesCache.cs" />
<Compile Include="Mvc\ViewEngines\ThemeAwareness\LayoutAwareViewEngine.cs" />
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemeAwareViewEngine.cs" /> <Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemeAwareViewEngine.cs" />
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemeAwareViewEngineShim.cs" /> <Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemeAwareViewEngineShim.cs" />
<Compile Include="Mvc\ViewEngines\ThemeAwareness\ViewEngineCollectionWrapper.cs" /> <Compile Include="Mvc\ViewEngines\ThemeAwareness\ViewEngineCollectionWrapper.cs" />
@@ -717,7 +718,7 @@
<Compile Include="Mvc\ViewEngines\LayoutView.cs" /> <Compile Include="Mvc\ViewEngines\LayoutView.cs" />
<Compile Include="Mvc\ViewEngines\LayoutViewEngine.cs" /> <Compile Include="Mvc\ViewEngines\LayoutViewEngine.cs" />
<Compile Include="Mvc\ViewEngines\LayoutViewContext.cs" /> <Compile Include="Mvc\ViewEngines\LayoutViewContext.cs" />
<Compile Include="Mvc\ViewEngines\ThemeAwareness\CurrentTheme.cs" /> <Compile Include="Mvc\ViewEngines\ThemeAwareness\ThemedViewResultFilter.cs" />
<Compile Include="Mvc\ViewEngines\WebForms\WebFormViewEngineProvider.cs" /> <Compile Include="Mvc\ViewEngines\WebForms\WebFormViewEngineProvider.cs" />
<Compile Include="UI\Admin\AdminThemeSelector.cs" /> <Compile Include="UI\Admin\AdminThemeSelector.cs" />
<Compile Include="UI\Navigation\INavigationManager.cs" /> <Compile Include="UI\Navigation\INavigationManager.cs" />