mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-22 20:13:50 +08:00
Making the use of BaseViewModel optional
Providing BaseViewModel.From(x) static methods to adapt properties from various context objects Adds DevTools\HomeController actions to verify results AdaptedViewModel exposes public properties or view data dictionary entries as appropriate Layout view engine restriction loosened to allow any ViewResult to be themed (not Partial of course) --HG-- branch : dev
This commit is contained in:
@@ -14,7 +14,7 @@ namespace Orchard.Core.Feeds.Services {
|
||||
}
|
||||
|
||||
public void OnResultExecuting(ResultExecutingContext filterContext) {
|
||||
var model = filterContext.Controller.ViewData.Model as BaseViewModel;
|
||||
var model = BaseViewModel.From(filterContext.Result);
|
||||
if (model == null) {
|
||||
return;
|
||||
}
|
||||
|
@@ -16,11 +16,7 @@ namespace Orchard.Core.Themes.Preview {
|
||||
}
|
||||
|
||||
public void OnResultExecuting(ResultExecutingContext filterContext) {
|
||||
var viewResult = filterContext.Result as ViewResult;
|
||||
if (viewResult == null)
|
||||
return;
|
||||
|
||||
var baseViewModel = viewResult.ViewData.Model as BaseViewModel;
|
||||
var baseViewModel = BaseViewModel.From(filterContext.Result);
|
||||
if (baseViewModel == null)
|
||||
return;
|
||||
|
||||
|
@@ -1,19 +1,18 @@
|
||||
using System.Web.Mvc;
|
||||
using Orchard.DevTools.Models;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace Orchard.DevTools.Controllers
|
||||
{
|
||||
public class HomeController : Controller
|
||||
{
|
||||
namespace Orchard.DevTools.Controllers {
|
||||
//[Themed]
|
||||
public class HomeController : Controller {
|
||||
private readonly INotifier _notifier;
|
||||
|
||||
public HomeController(INotifier notifier) {
|
||||
_notifier = notifier;
|
||||
}
|
||||
|
||||
public ActionResult Index()
|
||||
{
|
||||
public ActionResult Index() {
|
||||
return View(new BaseViewModel());
|
||||
}
|
||||
|
||||
@@ -22,5 +21,12 @@ namespace Orchard.DevTools.Controllers
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
public ActionResult Simple() {
|
||||
return View(new Simple { Title = "This is a simple text", Quantity = 5 });
|
||||
}
|
||||
|
||||
public ActionResult _RenderableAction() {
|
||||
return PartialView("_RenderableAction", "This is render action");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,6 @@
|
||||
namespace Orchard.DevTools.Models {
|
||||
public class Simple {
|
||||
public string Title { get; set; }
|
||||
public int Quantity { get; set; }
|
||||
}
|
||||
}
|
@@ -70,6 +70,7 @@
|
||||
<Compile Include="Controllers\HomeController.cs" />
|
||||
<Compile Include="Models\DebugLinkHandler.cs" />
|
||||
<Compile Include="Models\ShowDebugLink.cs" />
|
||||
<Compile Include="Models\Simple.cs" />
|
||||
<Compile Include="Permissions.cs" />
|
||||
<Compile Include="Profiler.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
@@ -77,6 +78,8 @@
|
||||
<Compile Include="ViewModels\ContentDetailsViewModel.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Views\Home\_RenderableAction.ascx" />
|
||||
<Content Include="Views\Home\Simple.aspx" />
|
||||
<Content Include="_Module.txt" />
|
||||
<Content Include="Views\Content\Details.aspx" />
|
||||
<Content Include="Views\Content\Index.aspx" />
|
||||
|
@@ -0,0 +1,10 @@
|
||||
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<Simple>" %>
|
||||
|
||||
<%@ Import Namespace="Orchard.DevTools.Models" %>
|
||||
<h1>
|
||||
<%= H(Model.Title) %></h1>
|
||||
<p>
|
||||
Quantity:
|
||||
<%= Model.Quantity %></p>
|
||||
<div style="border: solid 1px #ccc;">
|
||||
<% Html.RenderAction("_RenderableAction"); %></div>
|
@@ -0,0 +1,2 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<string>" %>
|
||||
<h3><%=H(Model)%></h3>
|
@@ -9,9 +9,9 @@
|
||||
? Html.ActionLink(menuSection.Text, (string)firstSectionItem.RouteValues["action"], firstSectionItem.RouteValues).ToHtmlString()
|
||||
: string.Format("<span>{0}</span>", Html.Encode(menuSection.Text));
|
||||
var classification = "";
|
||||
if (menuSection == Model.AdminMenu.First())
|
||||
if (menuSection == Model.Menu.First())
|
||||
classification = "first ";
|
||||
if (menuSection == Model.AdminMenu.Last())
|
||||
if (menuSection == Model.Menu.Last())
|
||||
classification += "last ";
|
||||
|
||||
%>
|
||||
|
@@ -2,8 +2,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.UI.Zones;
|
||||
|
||||
namespace Orchard.Mvc.ViewEngines {
|
||||
public class LayoutView : IView {
|
||||
@@ -20,25 +24,37 @@ namespace Orchard.Mvc.ViewEngines {
|
||||
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];
|
||||
if (index == _viewEngineResults.Length - 1) {
|
||||
viewEngineResult.View.Render(viewContext, writer);
|
||||
}
|
||||
else {
|
||||
//TEMP: to be replaced with an efficient spooling writer
|
||||
var childContext = new ViewContext(
|
||||
|
||||
var effectiveContext = new ViewContext(
|
||||
viewContext,
|
||||
viewEngineResult.View,
|
||||
viewContext.ViewData,
|
||||
effectiveViewData,
|
||||
viewContext.TempData,
|
||||
new StringWriter());
|
||||
viewEngineResult.View.Render(childContext, childContext.Writer);
|
||||
layoutViewContext.BodyContent = childContext.Writer.ToString();
|
||||
effectiveWriter);
|
||||
|
||||
viewEngineResult.View.Render(effectiveContext, effectiveWriter);
|
||||
|
||||
if (!isLast)
|
||||
layoutViewContext.BodyContent = effectiveWriter.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ViewDataDictionary CoerceViewData(ViewDataDictionary dictionary) {
|
||||
if (dictionary.Model is BaseViewModel)
|
||||
return dictionary;
|
||||
|
||||
return new ViewDataDictionary<BaseViewModel>(BaseViewModel.From(dictionary));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void ReleaseViews(ControllerContext context) {
|
||||
foreach (var viewEngineResult in _viewEngineResults) {
|
||||
viewEngineResult.ViewEngine.ReleaseView(context, viewEngineResult.View);
|
||||
|
@@ -24,8 +24,6 @@ namespace Orchard.Mvc.ViewEngines {
|
||||
var skipLayoutViewEngine = false;
|
||||
if (string.IsNullOrEmpty(masterName) == false)
|
||||
skipLayoutViewEngine = true;
|
||||
if (!(controllerContext.Controller.ViewData.Model is BaseViewModel))
|
||||
skipLayoutViewEngine = true;
|
||||
if (_viewEngines == null || _viewEngines.Count == 0)
|
||||
skipLayoutViewEngine = true;
|
||||
if (skipLayoutViewEngine)
|
||||
|
62
src/Orchard/Mvc/ViewModels/AdaptedViewModel.cs
Normal file
62
src/Orchard/Mvc/ViewModels/AdaptedViewModel.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.UI.Zones;
|
||||
|
||||
namespace Orchard.Mvc.ViewModels {
|
||||
class AdaptedViewModel : BaseViewModel {
|
||||
private readonly Property<ZoneCollection> _zones;
|
||||
private readonly Property<IEnumerable<MenuItem>> _menu;
|
||||
private readonly Property<IList<NotifyEntry>> _messages;
|
||||
private readonly Property<IUser> _currentUser;
|
||||
|
||||
public AdaptedViewModel(ViewDataDictionary original) {
|
||||
_zones = new Property<ZoneCollection>(original, "Zones", () => new ZoneCollection());
|
||||
_menu = new Property<IEnumerable<MenuItem>>(original, "Menu", Enumerable.Empty<MenuItem>);
|
||||
_messages = new Property<IList<NotifyEntry>>(original, "Messages", () => new NotifyEntry[0]);
|
||||
_currentUser = new Property<IUser>(original, "CurrentUser", () => null);
|
||||
}
|
||||
|
||||
public override ZoneCollection Zones { get { return _zones.Value; } set { _zones.Value = value; } }
|
||||
public override IEnumerable<MenuItem> Menu { get { return _menu.Value; } set { _menu.Value = value; } }
|
||||
public override IList<NotifyEntry> Messages { get { return _messages.Value; } set { _messages.Value = value; } }
|
||||
public override IUser CurrentUser { get { return _currentUser.Value; } set { _currentUser.Value = value; } }
|
||||
|
||||
|
||||
class Property<TProperty> where TProperty : class {
|
||||
private readonly ViewDataDictionary _original;
|
||||
private readonly string _expression;
|
||||
private Func<TProperty> _builder;
|
||||
private TProperty _value;
|
||||
|
||||
public Property(ViewDataDictionary original, string expression, Func<TProperty> builder) {
|
||||
_original = original;
|
||||
_expression = expression;
|
||||
_builder = builder;
|
||||
}
|
||||
|
||||
public TProperty Value {
|
||||
get {
|
||||
if (_value == null && _builder != null) {
|
||||
_value = _original.Eval(_expression) as TProperty;
|
||||
if (_value == null)
|
||||
SetValue(_builder());
|
||||
}
|
||||
|
||||
return _value;
|
||||
}
|
||||
set { SetValue(value); }
|
||||
}
|
||||
|
||||
private void SetValue(TProperty value) {
|
||||
_builder = null;
|
||||
_value = value;
|
||||
_original[_expression] = _value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.Security;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.UI.Notify;
|
||||
@@ -10,18 +11,20 @@ namespace Orchard.Mvc.ViewModels {
|
||||
private ZoneCollection _zones = new ZoneCollection();
|
||||
private IList<NotifyEntry> _messages = new List<NotifyEntry>();
|
||||
|
||||
public virtual ZoneCollection Zones {
|
||||
get { return _zones; }
|
||||
set { _zones = value; }
|
||||
}
|
||||
|
||||
public virtual IList<NotifyEntry> Messages {
|
||||
get { return _messages; }
|
||||
set { _messages = value; }
|
||||
}
|
||||
|
||||
public virtual ZoneCollection Zones { get { return _zones; } set { _zones = value; } }
|
||||
public virtual IList<NotifyEntry> Messages { get { return _messages; } set { _messages = value; } }
|
||||
public virtual IUser CurrentUser { get; set; }
|
||||
public virtual IEnumerable<MenuItem> Menu { get; set; }
|
||||
|
||||
public static BaseViewModel From(ViewDataDictionary viewData) {
|
||||
var model = viewData.Model as BaseViewModel;
|
||||
return model ?? new AdaptedViewModel(viewData);
|
||||
}
|
||||
|
||||
public static BaseViewModel From(ActionResult actionResult) {
|
||||
var viewResult = actionResult as ViewResult;
|
||||
return viewResult == null ? null : From(viewResult.ViewData);
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Please change your code to use BaseViewModel, as AdminViewModel will likely be removed in the near future.")]
|
||||
|
@@ -153,6 +153,7 @@
|
||||
<Compile Include="Extensions\Loaders\AreaExtensionLoader.cs" />
|
||||
<Compile Include="Extensions\UriExtensions.cs" />
|
||||
<Compile Include="Mvc\AntiForgery\ValidateAntiForgeryTokenOrchardAttribute.cs" />
|
||||
<Compile Include="Mvc\ViewModels\AdaptedViewModel.cs" />
|
||||
<Compile Include="OrchardException.cs" />
|
||||
<Compile Include="Security\IAuthorizationServiceEvents.cs" />
|
||||
<Compile Include="Security\StandardPermissions.cs" />
|
||||
@@ -224,6 +225,7 @@
|
||||
<Compile Include="Extensions\ExtensionDescriptor.cs" />
|
||||
<Compile Include="Extensions\ExtensionEntry.cs" />
|
||||
<Compile Include="IOrchardServices.cs" />
|
||||
<Compile Include="Themes\ThemedAttribute.cs" />
|
||||
<Compile Include="UI\Admin\AdminAttribute.cs" />
|
||||
<Compile Include="UI\Admin\AdminFilter.cs" />
|
||||
<Compile Include="Mvc\AntiForgery\AntiForgeryAuthorizationFilter.cs" />
|
||||
|
@@ -19,11 +19,7 @@ namespace Orchard.Security {
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public void OnResultExecuting(ResultExecutingContext filterContext) {
|
||||
var viewResult = filterContext.Result as ViewResultBase;
|
||||
if (viewResult == null)
|
||||
return;
|
||||
|
||||
var baseViewModel = viewResult.ViewData.Model as BaseViewModel;
|
||||
var baseViewModel = BaseViewModel.From(filterContext.Result);
|
||||
if (baseViewModel == null)
|
||||
return;
|
||||
|
||||
|
14
src/Orchard/Themes/ThemedAttribute.cs
Normal file
14
src/Orchard/Themes/ThemedAttribute.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
|
||||
namespace Orchard.Themes {
|
||||
public class ThemedAttribute : Attribute {
|
||||
public ThemedAttribute() {
|
||||
Enabled = true;
|
||||
}
|
||||
public ThemedAttribute(bool enabled) {
|
||||
Enabled = enabled;
|
||||
}
|
||||
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
}
|
@@ -12,11 +12,7 @@ namespace Orchard.UI.Navigation {
|
||||
}
|
||||
|
||||
public void OnResultExecuting(ResultExecutingContext filterContext) {
|
||||
var viewResult = filterContext.Result as ViewResult;
|
||||
if (viewResult == null)
|
||||
return;
|
||||
|
||||
var baseViewModel = viewResult.ViewData.Model as BaseViewModel;
|
||||
var baseViewModel = BaseViewModel.From(filterContext.Result);
|
||||
if (baseViewModel == null)
|
||||
return;
|
||||
|
||||
|
@@ -53,7 +53,7 @@ namespace Orchard.UI.Notify {
|
||||
if (viewResult == null)
|
||||
return;
|
||||
|
||||
var baseViewModel = viewResult.ViewData.Model as BaseViewModel;
|
||||
var baseViewModel = BaseViewModel.From(viewResult);
|
||||
// if it's not a view model that holds messages, don't touch temp data either
|
||||
if (baseViewModel == null)
|
||||
return;
|
||||
|
@@ -13,7 +13,7 @@ namespace Orchard.UI.Resources {
|
||||
}
|
||||
|
||||
public void OnResultExecuting(ResultExecutingContext filterContext) {
|
||||
var model = filterContext.Controller.ViewData.Model as BaseViewModel;
|
||||
var model = BaseViewModel.From(filterContext.Result);
|
||||
if (model == null) {
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user