Partially complete refactoring. Adding transactions. Adjusting template locations. CURRENTLY BROKEN

--HG--
extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4044385
This commit is contained in:
loudej
2009-12-21 01:30:24 +00:00
parent 3312bdd55f
commit 8d99ca8bee
65 changed files with 720 additions and 503 deletions

View File

@@ -50,6 +50,7 @@ namespace Orchard.Tests.Packages {
[TearDown]
public void Cleanup() {
_container.Dispose();
_session.Close();
}

View File

@@ -9,6 +9,7 @@ using Autofac.Builder;
using Moq;
using NUnit.Framework;
using Orchard.Data;
using Orchard.Environment;
using Orchard.Models;
using Orchard.Models.Driver;
using Orchard.Models.Records;
@@ -30,7 +31,10 @@ namespace Orchard.Tests.Packages.Users.Controllers {
builder.Register<DefaultContentQuery>().As<IContentQuery>().FactoryScoped();
builder.Register<MembershipService>().As<IMembershipService>();
builder.Register<UserHandler>().As<IContentHandler>();
builder.Register<OrchardServices>().As<IOrchardServices>();
builder.Register<TransactionManager>().As<ITransactionManager>();
builder.Register(new Mock<INotifier>().Object);
builder.Register(new Mock<IAuthorizer>().Object);
}
protected override IEnumerable<Type> DatabaseTypes {
@@ -76,10 +80,42 @@ namespace Orchard.Tests.Packages.Users.Controllers {
Assert.That(model.Rows, Is.Not.Null);
}
public static class Values {
public static IValueProvider Of<T>(T obj) {
return new ValueProvider<T>(obj);
}
class ValueProvider<T> : IValueProvider {
private readonly T _obj;
public ValueProvider(T obj) {
_obj = obj;
}
public bool ContainsPrefix(ControllerContext controllerContext, string prefix) {
return typeof(T).GetProperties().Any(x => x.Name.StartsWith(prefix));
}
public ValueProviderResult GetValue(ControllerContext controllerContext, string key) {
var property = typeof(T).GetProperty(key);
if (property == null)
return null;
return new ValueProviderResult(
property.GetValue(_obj, null),
Convert.ToString(property.GetValue(_obj, null)),
null);
}
}
}
[Test]
public void CreateShouldAddUserAndRedirect() {
var controller = _container.Resolve<AdminController>();
var result = controller.Create(new UserCreateViewModel { UserName = "four",Password="five",ConfirmPassword="five" });
controller.ValueProvider = Values.Of(new {
UserName = "four",
Password = "five",
ConfirmPassword = "five"
});
var result = controller._Create();
Assert.That(result, Is.TypeOf<RedirectToRouteResult>());
var redirect = (RedirectToRouteResult)result;
@@ -97,8 +133,12 @@ namespace Orchard.Tests.Packages.Users.Controllers {
var model = (UserEditViewModel)result.ViewData.Model;
Assert.That(model.UserName, Is.EqualTo("two"));
var input = new FormCollection { { "UserName", "bubba" }, { "Email", "hotep" } };
var result2 = _container.Resolve<AdminController>().Edit(id, input);
var controller = _container.Resolve<AdminController>();
controller.ValueProvider = Values.Of(new {
UserName = "bubba",
Email = "hotep",
});
var result2 = controller._Edit(id);
Assert.That(result2, Is.TypeOf<RedirectToRouteResult>());
}
}

View File

@@ -175,7 +175,7 @@ namespace Orchard.Tests.Models {
[Test]
public void EditorsShouldBeOrderedByPositionAndDefaultPositionIsSix() {
var alpha = _manager.New("alpha");
var templates = _manager.BuildDisplayModel(alpha, null, null).Displays;
var templates = _manager.BuildDisplayModel(alpha, null).Displays;
Assert.That(templates.Count(), Is.EqualTo(3));
var t0 = templates.First();

View File

@@ -41,7 +41,7 @@ namespace Orchard.Tests.Models {
});
var contentHandler = _container.Resolve<IContentHandler>();
var ctx = new BuildDisplayModelContext(new ItemDisplayModel(new ContentItem()), null, null, null);
var ctx = new BuildDisplayModelContext(new ItemDisplayModel(new ContentItem()), null);
driver1.Verify(x => x.BuildDisplayModel(ctx), Times.Never());
contentHandler.BuildDisplayModel(ctx);
@@ -58,7 +58,7 @@ namespace Orchard.Tests.Models {
var item = new ContentItem();
item.Weld(new StubPart { Foo = new[] { "a", "b", "c" } });
var ctx = new BuildDisplayModelContext(new ItemDisplayModel(item), "", "", null);
var ctx = new BuildDisplayModelContext(new ItemDisplayModel(item), "");
Assert.That(ctx.DisplayModel.Displays.Count(), Is.EqualTo(0));
contentHandler.BuildDisplayModel(ctx);
Assert.That(ctx.DisplayModel.Displays.Count(), Is.EqualTo(1));
@@ -71,7 +71,7 @@ namespace Orchard.Tests.Models {
get { return "Stub"; }
}
protected override DriverResult Display(StubPart part, string groupName, string displayType) {
protected override DriverResult Display(StubPart part, string displayType) {
var viewModel = new StubViewModel { Foo = string.Join(",", part.Foo) };
if (displayType.StartsWith("Summary"))
return PartialView(viewModel, "StubViewModelTerse").Location("topmeta");
@@ -79,12 +79,12 @@ namespace Orchard.Tests.Models {
return PartialView(viewModel).Location("topmeta");
}
protected override DriverResult Editor(StubPart part, string groupName) {
protected override DriverResult Editor(StubPart part) {
var viewModel = new StubViewModel { Foo = string.Join(",", part.Foo) };
return PartialView(viewModel).Location("last", "10");
}
protected override DriverResult Editor(StubPart part, string groupName, IUpdateModel updater) {
protected override DriverResult Editor(StubPart part, IUpdateModel updater) {
var viewModel = new StubViewModel { Foo = string.Join(",", part.Foo) };
updater.TryUpdateModel(viewModel, Prefix, null, null);
part.Foo = viewModel.Foo.Split(new[] { ',' }).Select(x => x.Trim()).ToArray();

View File

@@ -141,7 +141,7 @@
<Content Include="Common\Views\Shared\EditorTemplates\OwnerEditorViewModel.ascx" />
<Content Include="Themes\Styles\site.css" />
<Content Include="Themes\Views\Admin\Install.aspx" />
<Content Include="Themes\Views\Shared\document.aspx" />
<Content Include="Themes\Views\document.aspx" />
<Content Include="Themes\Views\Shared\EditorTemplates\ThemeSiteSettingsRecord.ascx" />
<Content Include="Themes\Views\Shared\layout.ascx" />
<Content Include="Themes\Views\Shared\user.ascx" />

View File

@@ -26,14 +26,14 @@ namespace Orchard.Core.Settings.Controllers {
public ActionResult Index(string tabName) {
var model = new Orchard.Core.Settings.ViewModels.SettingsIndexViewModel {
Site = _siteService.GetSiteSettings().As<SiteSettings>() };
model.EditorModel = _modelManager.BuildEditorModel(model.Site, tabName);
model.EditorModel = _modelManager.BuildEditorModel(model.Site);
return View(model);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(string tabName, FormCollection input) {
var viewModel = new SettingsIndexViewModel { Site = _siteService.GetSiteSettings().As<SiteSettings>() };
viewModel.EditorModel = _modelManager.UpdateEditorModel(viewModel.Site.ContentItem, tabName, this);
viewModel.EditorModel = _modelManager.UpdateEditorModel(viewModel.Site.ContentItem, this);
if (!TryUpdateModel(viewModel, input.ToValueProvider())) {
return View(viewModel);

View File

@@ -1,10 +1,28 @@
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Orchard.Core.Settings.ViewModels.SettingsIndexViewModel>" %>
<%@ Import Namespace="Orchard.Mvc.Html"%>
<h2>Edit Settings</h2>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<h2>
Edit Settings</h2>
<%using (Html.BeginForm()) { %>
<%= Html.ValidationSummary() %>
<%= Html.EditorForModel() %>
<%= Html.ValidationSummary() %>
<fieldset>
<legend>Global Settings</legend>
<fieldset>
<input class="button" type="submit" value="Save" />
<%=Html.LabelFor(x=>x.SiteName) %>
<%=Html.EditorFor(x=>x.SiteName) %>
<%=Html.ValidationMessage("SiteName", "*") %>
</fieldset>
<fieldset>
<%=Html.LabelFor(x => x.SuperUser) %>
<%=Html.EditorFor(x=>x.SuperUser) %>
<%=Html.ValidationMessage("SuperUser", "*") %>
</fieldset>
<%=Html.EditorFor(s=>s.Id) %>
</fieldset>
<% foreach (var e in Model.EditorModel.Editors) { %>
<%=Html.EditorFor(m => e.Model, e.TemplateName, e.Prefix)%>
<% } %>
<fieldset>
<input class="button" type="submit" value="Save" />
</fieldset>
<% } %>

View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
using Orchard.Mvc.ViewModels;
namespace Orchard.Core.Themes.ViewModels {
public class CreateThemeViewModel : AdminViewModel {
[Required]
public string Name { get; set; }
[Required]
public string Author { get; set; }
[Required]
public string Description { get; set; }
[Required]
public string Version { get; set; }
[Required]
public string Tags { get; set; }
[Required]
public string Homepage { get; set; }
}
}

View File

@@ -165,6 +165,7 @@
<Content Include="Content\Images\title_background.gif" />
<Content Include="Content\Site2.css" />
<Content Include="Content\Site3.css" />
<Content Include="Themes\BlueSky\Views\layout.ascx" />
<Content Include="Views\Shared\Messages.ascx" />
</ItemGroup>
<ItemGroup>

View File

@@ -20,7 +20,7 @@ namespace Orchard.Blogs.Controllers {
public ActionResult List() {
//TODO: (erikpo) Need to make templatePath be more convention based so if my controller name has "Admin" in it then "Admin/{type}" is assumed
var model = new AdminBlogsViewModel {
Blogs = _blogService.Get().Select(b => _contentManager.BuildDisplayModel(b, null, "Summary", "Admin/Blog"))
Blogs = _blogService.Get().Select(b => _contentManager.BuildDisplayModel(b, "SummaryAdmin"))
};
return View(model);
@@ -35,7 +35,7 @@ namespace Orchard.Blogs.Controllers {
//TODO: (erikpo) Need to make templatePath be more convention based so if my controller name has "Admin" in it then "Admin/{type}" is assumed
var model = new BlogForAdminViewModel {
Blog = _contentManager.BuildDisplayModel(blog, null, "Detail", "Admin/Blog")
Blog = _contentManager.BuildDisplayModel(blog, "DetailAdmin")
};
return View(model);

View File

@@ -37,7 +37,7 @@ namespace Orchard.Blogs.Controllers {
public ActionResult List() {
var model = new BlogsViewModel {
Blogs = _blogService.Get().Select(b => _contentManager.BuildDisplayModel(b, null, "Summary"))
Blogs = _blogService.Get().Select(b => _contentManager.BuildDisplayModel(b, "Summary"))
};
return View(model);
@@ -51,7 +51,7 @@ namespace Orchard.Blogs.Controllers {
return new NotFoundResult();
var model = new BlogViewModel {
Blog = _contentManager.BuildDisplayModel(blog, null, "Detail")
Blog = _contentManager.BuildDisplayModel(blog, "Detail")
};
return View(model);
@@ -68,7 +68,7 @@ namespace Orchard.Blogs.Controllers {
return new NotFoundResult();
var model = new CreateBlogViewModel {
Blog = _contentManager.BuildEditorModel(blog, null)
Blog = _contentManager.BuildEditorModel(blog)
};
return View(model);
@@ -80,7 +80,7 @@ namespace Orchard.Blogs.Controllers {
if (!_authorizer.Authorize(Permissions.CreateBlog, T("Couldn't create blog")))
return new HttpUnauthorizedResult();
model.Blog = _contentManager.UpdateEditorModel(_contentManager.New<Blog>("blog"), null, this);
model.Blog = _contentManager.UpdateEditorModel(_contentManager.New<Blog>("blog"), this);
if (!ModelState.IsValid)
return View(model);
@@ -106,7 +106,7 @@ namespace Orchard.Blogs.Controllers {
return new NotFoundResult();
var model = new BlogEditViewModel {
Blog = _contentManager.BuildEditorModel(blog, "")
Blog = _contentManager.BuildEditorModel(blog)
};
return View(model);
@@ -124,7 +124,7 @@ namespace Orchard.Blogs.Controllers {
return new NotFoundResult();
var model = new BlogEditViewModel {
Blog = _contentManager.UpdateEditorModel(blog, "", this)
Blog = _contentManager.UpdateEditorModel(blog, this)
};
if (!ModelState.IsValid)

View File

@@ -56,7 +56,7 @@ namespace Orchard.Blogs.Controllers {
var model = new BlogPostViewModel {
Blog = blog,
BlogPost = _contentManager.BuildDisplayModel(post, null, "Detail")
BlogPost = _contentManager.BuildDisplayModel(post, "Detail")
};
return View(model);
@@ -95,7 +95,7 @@ namespace Orchard.Blogs.Controllers {
if (blog == null)
return new NotFoundResult();
var blogPost = _contentManager.BuildEditorModel(_contentManager.New<BlogPost>("blogpost"), null);
var blogPost = _contentManager.BuildEditorModel(_contentManager.New<BlogPost>("blogpost"));
blogPost.Item.Blog = blog;
var model = new CreateBlogPostViewModel {
@@ -117,7 +117,7 @@ namespace Orchard.Blogs.Controllers {
return new NotFoundResult();
BlogPost blogPost = _contentManager.Create<BlogPost>("blogpost", bp => { bp.Blog = blog; });
model.BlogPost = _contentManager.UpdateEditorModel(blogPost, null, this);
model.BlogPost = _contentManager.UpdateEditorModel(blogPost, this);
if (!ModelState.IsValid)
return View(model);
@@ -145,7 +145,7 @@ namespace Orchard.Blogs.Controllers {
return new NotFoundResult();
var model = new BlogPostEditViewModel {
BlogPost = _contentManager.BuildEditorModel(post, null)
BlogPost = _contentManager.BuildEditorModel(post)
};
return View(model);
@@ -168,7 +168,7 @@ namespace Orchard.Blogs.Controllers {
return new NotFoundResult();
var model = new BlogPostEditViewModel {
BlogPost = _contentManager.UpdateEditorModel(post, null, this)
BlogPost = _contentManager.UpdateEditorModel(post, this)
};
IValueProvider values = input.ToValueProvider();

View File

@@ -16,7 +16,7 @@ namespace Orchard.Blogs.Models {
Filters.Add(new ActivatingFilter<CommonAspect>("blog"));
Filters.Add(new ActivatingFilter<RoutableAspect>("blog"));
Filters.Add(new StorageFilter<BlogRecord>(repository));
Filters.Add(new ContentItemTemplates<Blog>("Detail", "Summary"));
Filters.Add(new ContentItemTemplates<Blog>("Items/Blogs.Blog", "Detail Summary"));
OnGetEditorViewModel<Blog>((context, blog) =>
context.AddEditor(new TemplateViewModel(blog) { TemplateName = "Blog/Fields", ZoneName = "primary", Position = "1" })

View File

@@ -24,7 +24,7 @@ namespace Orchard.Blogs.Models {
Filters.Add(new ActivatingFilter<RoutableAspect>("blogpost"));
Filters.Add(new ActivatingFilter<BodyAspect>("blogpost"));
Filters.Add(new StorageFilter<BlogPostRecord>(repository));
Filters.Add(new ContentItemTemplates<BlogPost>("Detail", "Summary"));
Filters.Add(new ContentItemTemplates<BlogPost>("Items/Blogs.BlogPost", "Detail Summary"));
OnCreated<BlogPost>((context, bp) => bp.Blog.PostCount++);
@@ -59,10 +59,15 @@ namespace Orchard.Blogs.Models {
switch(context.DisplayType) {
case "Detail":
context.AddDisplay(
//TODO: (erikpo) Need to make templatePath be more convention based so if my controller name has "Admin" in it then "Admin/{type}" is assumed
new TemplateViewModel(posts.Select(bp => contentManager.BuildDisplayModel(bp, null, "Summary", "Admin/BlogPost")))
{
TemplateName = "Admin/BlogPost/List",
new TemplateViewModel(posts.Select(bp => contentManager.BuildDisplayModel(bp, "Summary"))) {
TemplateName = "BlogPost/List",
ZoneName = "body"
});
break;
case "DetailAdmin":
context.AddDisplay(
new TemplateViewModel(posts.Select(bp => contentManager.BuildDisplayModel(bp, "SummaryAdmin"))) {
TemplateName = "BlogPost/ListAdmin",
ZoneName = "body"
});
break;

View File

@@ -158,9 +158,8 @@
<IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>http://orchard.codeplex.com/</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>

View File

@@ -36,8 +36,8 @@ namespace Orchard.DevTools.Controllers {
.Select(x => x.GetType())
.SelectMany(x => AllTypes(x))
.Distinct();
model.DisplayModel = _contentManager.BuildDisplayModel(model.Item, null, null);
model.EditorModel = _contentManager.BuildEditorModel(model.Item, null);
model.DisplayModel = _contentManager.BuildDisplayModel(model.Item, null);
model.EditorModel = _contentManager.BuildEditorModel(model.Item);
return View(model);
}

View File

@@ -4,10 +4,10 @@ using Orchard.Models.ViewModels;
namespace Orchard.DevTools.Models {
public class DebugLinkHandler : ContentHandler {
protected override void BuildDisplayModel(BuildDisplayModelContext context) {
context.AddDisplay(new TemplateViewModel(new ShowDebugLink { ContentItem = context.ContentItem }) { ZoneName = "recap", Position = "9999" });
context.AddDisplay(new TemplateViewModel(new ShowDebugLink { ContentItem = context.ContentItem }) { TemplateName="Parts/DevTools.ShowDebugLink", ZoneName = "recap", Position = "9999" });
}
protected override void BuildEditorModel(BuildEditorModelContext context) {
context.AddEditor(new TemplateViewModel(new ShowDebugLink { ContentItem = context.ContentItem }) { ZoneName = "recap", Position = "9999" });
context.AddEditor(new TemplateViewModel(new ShowDebugLink { ContentItem = context.ContentItem }) { TemplateName = "Parts/DevTools.ShowDebugLink", ZoneName = "recap", Position = "9999" });
}
}
}

View File

@@ -75,8 +75,8 @@
<Content Include="Views\Content\Details.aspx" />
<Content Include="Views\Content\Index.aspx" />
<Content Include="Views\Home\Index.aspx" />
<Content Include="Views\Shared\DisplayTemplates\ShowDebugLink.ascx" />
<Content Include="Views\Shared\EditorTemplates\ShowDebugLink.ascx" />
<Content Include="Views\DisplayTemplates\Parts\DevTools.ShowDebugLink.ascx" />
<Content Include="Views\EditorTemplates\Parts\DevTools.ShowDebugLink.ascx" />
<Content Include="Web.config" />
<Content Include="Views\Web.config" />
</ItemGroup>
@@ -88,6 +88,8 @@
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />
<Folder Include="Views\Shared\DisplayTemplates\" />
<Folder Include="Views\Shared\EditorTemplates\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />

View File

@@ -3,121 +3,100 @@
<%@ Import Namespace="System.Reflection" %>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TwoColumns</title>
<link href="<%=ResolveUrl("~/Content/Site2.css") %>" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="header">
<div id="innerheader">
<% Html.Include("header"); %>
</div>
</div>
<div id="page">
<div id="sideBar">
<% Html.Include("Navigation"); %>
</div>
<div id="main">
<h3>
Content Item</h3>
<p>
Id:
<%=Model.Item.ContentItem.Id %></p>
<p>
ContentType:
<%=Model.Item.ContentItem.ContentType%> <%=Html.ItemDisplayLink(Model.Item) %> <%=Html.ItemEditLink("edit", Model.Item) %></p>
<h3>
Content Item Parts</h3>
<ul>
<%foreach (var partType in Model.PartTypes.OrderBy(x => x.Name)) {%>
<li><span style="font-weight: bold;">
<%if (partType.IsGenericType) {%><%=Html.Encode(partType.Name +" "+partType.GetGenericArguments().First().Name)%></span>
<%=Html.Encode(" (" + partType.GetGenericArguments().First().Namespace + ")")%><%}
else {%><%=Html.Encode(partType.Name)%></span>
<%=Html.Encode( " (" + partType.Namespace + ")")%><%
}
%>
<ul style="margin-left: 20px">
<%foreach (var prop in partType.GetProperties().Where(x => x.DeclaringType == partType)) {
var value = prop.GetValue(Model.Locate(partType), null);%>
<li style="font-weight: normal;">
<%=Html.Encode(prop.Name) %>:
<%=Html.Encode(value) %>
<%var valueItem = value as ContentItem;
if (valueItem == null && value is IContent) {
valueItem = (value as IContent).ContentItem;
}
if (valueItem != null) {
%><%=Html.ActionLink(valueItem.ContentType + " #" + valueItem.Id, "details", new { valueItem.Id }, new { })%><%
}
%>
<ul style="margin-left: 20px">
<%if (value == null || prop.PropertyType.IsPrimitive || prop.PropertyType == typeof(string)) { }
else if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType)) {
foreach (var item in value as IEnumerable) {
%>
<li><%=Html.Encode(item.GetType().Name) %>:<%=Html.Encode(item) %></li>
<%
}
}
else {%>
<%foreach (var prop2 in value.GetType().GetProperties().Where(x => x.GetIndexParameters().Count() == 0)) {%>
<li>
<%=Html.Encode(prop2.Name)%>
<%=Html.Encode(prop2.GetValue(value, null))%></li>
<%} %>
<%} %>
</ul>
</li>
<%} %>
</ul>
</li>
<%}%>
</ul>
<h3>
Displays</h3>
<ul>
<%foreach (var display in Model.Displays) {%>
<li><span style="font-weight: bold">
<%=Html.Encode(display.Prefix)%></span>
<%=Html.Encode(display.Model.GetType().Name)%>
(<%=Html.Encode(display.Model.GetType().Namespace)%>)
Prefix:<%=Html.Encode(display.Prefix ?? "(null)")%>
Zone:<%=Html.Encode(display.ZoneName ?? "(null)")%>
Position:<%=Html.Encode(display.Position ?? "(null)")%>
<div style="margin-left: 20px; border: solid 1px black;">
<%=Html.DisplayFor(x => display.Model, display.TemplateName, display.Prefix)%>
</div>
</li>
<%
}%>
</ul>
<h3>
Editors</h3>
<ul>
<%foreach (var editor in Model.Editors) {%>
<li><span style="font-weight: bold">
<%=Html.Encode(editor.Prefix) %></span>
<%=Html.Encode(editor.Model.GetType().Name) %>
(<%=Html.Encode(editor.Model.GetType().Namespace) %>)
Prefix:<%=Html.Encode(editor.Prefix ?? "(null)")%>
Zone:<%=Html.Encode(editor.ZoneName ?? "(null)")%>
Position:<%=Html.Encode(editor.Position??"(null)") %>
<div style="margin-left: 20px; border: solid 1px black;">
<%=Html.EditorFor(x=>editor.Model, editor.TemplateName, editor.Prefix) %>
</div>
</li>
<%
}%>
</ul>
<h3>Content Item</h3>
<p>
Id:
<%=Model.Item.ContentItem.Id %></p>
<p>
ContentType:
<%=Model.Item.ContentItem.ContentType%> <%=Html.ItemDisplayLink(Model.Item) %> <%=Html.ItemEditLink("edit", Model.Item) %></p>
<h3>Content Item Parts</h3>
<ul>
<%foreach (var partType in Model.PartTypes.OrderBy(x => x.Name)) {%>
<li><span style="font-weight: bold;">
<%if (partType.IsGenericType) {%><%=Html.Encode(partType.Name +" "+partType.GetGenericArguments().First().Name)%></span>
<%=Html.Encode(" (" + partType.GetGenericArguments().First().Namespace + ")")%><%}
else {%><%=Html.Encode(partType.Name)%></span>
<%=Html.Encode( " (" + partType.Namespace + ")")%><%
}
%>
<ul style="margin-left: 20px">
<%foreach (var prop in partType.GetProperties().Where(x => x.DeclaringType == partType)) {
var value = prop.GetValue(Model.Locate(partType), null);%>
<li style="font-weight: normal;">
<%=Html.Encode(prop.Name) %>:
<%=Html.Encode(value) %>
<%var valueItem = value as ContentItem;
if (valueItem == null && value is IContent) {
valueItem = (value as IContent).ContentItem;
}
if (valueItem != null) {
%><%=Html.ActionLink(valueItem.ContentType + " #" + valueItem.Id, "details", new { valueItem.Id }, new { })%><%
}
%>
<ul style="margin-left: 20px">
<%if (value == null || prop.PropertyType.IsPrimitive || prop.PropertyType == typeof(string)) { }
else if (typeof(IEnumerable).IsAssignableFrom(prop.PropertyType)) {
foreach (var item in value as IEnumerable) {
%>
<li><%=Html.Encode(item.GetType().Name) %>:<%=Html.Encode(item) %></li>
<%
}
}
else {%>
<%foreach (var prop2 in value.GetType().GetProperties().Where(x => x.GetIndexParameters().Count() == 0)) {%>
<li>
<%=Html.Encode(prop2.Name)%>
<%=Html.Encode(prop2.GetValue(value, null))%></li>
<%} %>
<%} %>
</ul>
</li>
<%} %>
</ul>
</li>
<%}%>
</ul>
<h3>Displays</h3>
<ul>
<%foreach (var display in Model.Displays) {%>
<li><span style="font-weight: bold">
<%=Html.Encode(display.Prefix)%></span>
<%=Html.Encode(display.Model.GetType().Name)%>
(<%=Html.Encode(display.Model.GetType().Namespace)%>)
Prefix:<%=Html.Encode(display.Prefix ?? "(null)")%>
Zone:<%=Html.Encode(display.ZoneName ?? "(null)")%>
Position:<%=Html.Encode(display.Position ?? "(null)")%>
<div style="margin-left: 20px; border: solid 1px black;">
<%=Html.DisplayFor(x => display.Model, display.TemplateName, display.Prefix)%>
</div>
<div id="footer">
<% Html.Include("footer"); %>
</li>
<%
}%>
</ul>
<h3>Editors</h3>
<ul>
<%foreach (var editor in Model.Editors) {%>
<li><span style="font-weight: bold">
<%=Html.Encode(editor.Prefix) %></span>
<%=Html.Encode(editor.Model.GetType().Name) %>
(<%=Html.Encode(editor.Model.GetType().Namespace) %>)
Prefix:<%=Html.Encode(editor.Prefix ?? "(null)")%>
Zone:<%=Html.Encode(editor.ZoneName ?? "(null)")%>
Position:<%=Html.Encode(editor.Position??"(null)") %>
<div style="margin-left: 20px; border: solid 1px black;">
<%=Html.EditorFor(x=>editor.Model, editor.TemplateName, editor.Prefix) %>
</div>
</div>
</body>
</html>
</li>
<%
}%>
</ul>

View File

@@ -1,27 +1,7 @@
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Orchard.DevTools.ViewModels.ContentIndexViewModel>" %>
<%@ Import Namespace="Orchard.Mvc.Html"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TwoColumns</title>
<link href="<%=ResolveUrl("~/Content/Site2.css") %>" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="header">
<div id="innerheader">
<% Html.Include("header"); %>
</div>
</div>
<div id="page">
<div id="sideBar">
<% Html.Include("Navigation"); %>
</div>
<div id="main">
<h3>Content Types</h3>
<ul>
<%foreach(var item in Model.Types.OrderBy(x=>x.Name)){%>
@@ -38,13 +18,3 @@
<%}%>
</ul>
</div>
<div id="footer">
<% Html.Include("footer"); %>
</div>
</div>
</body>
</html>

View File

@@ -2,37 +2,4 @@
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
<%@ Import Namespace="Orchard.Mvc.Html"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TwoColumns</title>
<link href="<%=ResolveUrl("~/Content/Site2.css") %>" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="header">
<div id="innerheader">
<% Html.Include("header"); %>
</div>
</div>
<div id="page">
<div id="sideBar">
<% Html.Include("Navigation"); %>
</div>
<div id="main">
<p><%=Html.ActionLink("Contents", "Index", "Content") %></p>
</div>
<div id="footer">
<% Html.Include("footer"); %>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.Data;
using Orchard.Models;
using Orchard.Models.Driver;
using Orchard.Models.ViewModels;
using Orchard.Roles.Models.NoRecord;
using Orchard.Roles.Records;
using Orchard.Roles.Services;
using Orchard.Roles.ViewModels;
using Orchard.Security;
using Orchard.UI.Notify;
namespace Orchard.Roles.Controllers {
public class UserRolesDriver : PartDriver<UserRoles> {
private readonly IRepository<UserRolesRecord> _userRolesRepository;
private readonly IRoleService _roleService;
private readonly INotifier _notifier;
public UserRolesDriver(
IRepository<UserRolesRecord> userRolesRepository,
IRoleService roleService,
INotifier notifier) {
_userRolesRepository = userRolesRepository;
_roleService = roleService;
_notifier = notifier;
}
protected override string Prefix {
get {
return "UserRoles";
}
}
protected override DriverResult Editor(UserRoles userRoles) {
var roles =
_roleService.GetRoles().Select(
x => new UserRoleEntry {
RoleId = x.Id,
Name = x.Name,
Granted = userRoles.Roles.Contains(x.Name)
});
var model = new UserRolesViewModel {
User = userRoles.As<IUser>(),
UserRoles = userRoles,
Roles = roles.ToList(),
};
return PartialView(model, "Parts/Roles.UserRoles");
}
protected override DriverResult Editor(UserRoles userRoles, IUpdateModel updater) {
var model = new UserRolesViewModel {
User = userRoles.As<IUser>(),
UserRoles = userRoles,
};
if (updater.TryUpdateModel(model, "UserRoles", null, null)) {
var currentUserRoleRecords = _userRolesRepository.Fetch(x => x.UserId == model.User.Id);
var currentRoleRecords = currentUserRoleRecords.Select(x => x.Role);
var targetRoleRecords = model.Roles.Where(x => x.Granted).Select(x => _roleService.GetRole(x.RoleId));
foreach (var addingRole in targetRoleRecords.Where(x => !currentRoleRecords.Contains(x))) {
_notifier.Warning(string.Format("Adding role {0} to user {1}", addingRole.Name, userRoles.As<IUser>().UserName));
_userRolesRepository.Create(new UserRolesRecord { UserId = model.User.Id, Role = addingRole });
}
foreach (var removingRole in currentUserRoleRecords.Where(x => !targetRoleRecords.Contains(x.Role))) {
_notifier.Warning(string.Format("Removing role {0} from user {1}", removingRole.Role.Name, userRoles.As<IUser>().UserName));
_userRolesRepository.Delete(removingRole);
}
}
return PartialView(model, "Parts/Roles.UserRoles");
}
}
}

View File

@@ -13,13 +13,9 @@ using Orchard.UI.Notify;
namespace Orchard.Roles.Models {
public class UserRolesHandler : ContentHandler {
private readonly IRepository<UserRolesRecord> _userRolesRepository;
private readonly IRoleService _roleService;
private readonly INotifier _notifier;
public UserRolesHandler(IRepository<UserRolesRecord> userRolesRepository, IRoleService roleService, INotifier notifier) {
public UserRolesHandler(IRepository<UserRolesRecord> userRolesRepository) {
_userRolesRepository = userRolesRepository;
_roleService = roleService;
_notifier = notifier;
Filters.Add(new ActivatingFilter<UserRoles>("user"));
OnLoaded<UserRoles>((context, userRoles) => {
@@ -29,51 +25,6 @@ namespace Orchard.Roles.Models {
});
}
protected override void BuildEditorModel(BuildEditorModelContext context) {
var userRoles = context.ContentItem.As<UserRoles>();
if (userRoles != null) {
var roles =
_roleService.GetRoles().Select(
x => new UserRoleEntry {
RoleId = x.Id,
Name = x.Name,
Granted = userRoles.Roles.Contains(x.Name)
});
var viewModel = new UserRolesViewModel {
User = userRoles.As<IUser>(),
UserRoles = userRoles,
Roles = roles.ToList(),
};
context.AddEditor(new TemplateViewModel(viewModel, "UserRoles"));
}
}
protected override void UpdateEditorModel(UpdateEditorModelContext context) {
var userRoles = context.ContentItem.As<UserRoles>();
if (userRoles != null) {
var viewModel = new UserRolesViewModel();
if (context.Updater.TryUpdateModel(viewModel, "UserRoles", null, null)) {
var currentUserRoleRecords = _userRolesRepository.Fetch(x => x.UserId == context.ContentItem.Id);
var currentRoleRecords = currentUserRoleRecords.Select(x => x.Role);
var targetRoleRecords = viewModel.Roles.Where(x => x.Granted).Select(x => _roleService.GetRole(x.RoleId));
foreach (var addingRole in targetRoleRecords.Where(x => !currentRoleRecords.Contains(x))) {
_notifier.Warning(string.Format("Adding role {0} to user {1}", addingRole.Name, userRoles.As<IUser>().UserName));
_userRolesRepository.Create(new UserRolesRecord { UserId = context.ContentItem.Id, Role = addingRole });
}
foreach (var removingRole in currentUserRoleRecords.Where(x => !targetRoleRecords.Contains(x.Role))) {
_notifier.Warning(string.Format("Removing role {0} from user {1}", removingRole.Role.Name, userRoles.As<IUser>().UserName));
_userRolesRepository.Delete(removingRole);
}
}
context.AddEditor(new TemplateViewModel(viewModel, "UserRoles"));
}
}
}
}

View File

@@ -63,6 +63,7 @@
<ItemGroup>
<Compile Include="AdminMenu.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\UserRolesDriver.cs" />
<Compile Include="Records\PermissionRecord.cs" />
<Compile Include="Records\RoleRecord.cs" />
<Compile Include="Models\UserRoles.cs" />
@@ -82,7 +83,7 @@
<Content Include="Views\Admin\Create.aspx" />
<Content Include="Views\Admin\Edit.aspx" />
<Content Include="Views\Admin\Index.aspx" />
<Content Include="Views\Shared\EditorTemplates\UserRolesViewModel.ascx" />
<Content Include="Views\EditorTemplates\Parts\Roles.UserRoles.ascx" />
<Content Include="Web.config" />
<Content Include="Content\Site.css" />
<Content Include="Views\Web.config" />

View File

@@ -0,0 +1,18 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Orchard.Roles.ViewModels.UserRolesViewModel>" %>
<fieldset>
<legend>Roles</legend>
<% if (Model.Roles.Count > 0) {
var index = 0;
foreach (var entry in Model.Roles) {%>
<%=Html.Hidden("Roles[" + index + "].RoleId", entry.RoleId)%>
<%=Html.Hidden("Roles[" + index + "].Name", entry.Name)%>
<label for="<%="Roles[" + index + "]_Granted"%>">
<%= Html.CheckBox("Roles[" + index + "].Granted", entry.Granted)%>
<%=Html.Encode(entry.Name)%></label>
<%++index;
}
}
else {
%><p>There are no roles</p><%
} %>
</fieldset>

View File

@@ -32,7 +32,7 @@ namespace Orchard.Sandbox.Controllers {
Pages = _contentManager.Query<SandboxPage, SandboxPageRecord>()
.OrderBy(x => x.Name)
.List()
.Select(x => _contentManager.BuildDisplayModel(x, null, "SummaryList"))
.Select(x => _contentManager.BuildDisplayModel(x, "SummaryList"))
};
return View(model);
}
@@ -40,7 +40,7 @@ namespace Orchard.Sandbox.Controllers {
public ActionResult Show(int id) {
var page = _contentManager.Get<SandboxPage>(id);
var model = new PageShowViewModel {
Page = _contentManager.BuildDisplayModel(page, null, "Detail")
Page = _contentManager.BuildDisplayModel(page, "Detail")
};
return View(model);
}
@@ -80,7 +80,7 @@ namespace Orchard.Sandbox.Controllers {
var page = _contentManager.Get<SandboxPage>(id);
var model = new PageEditViewModel {
Page = _contentManager.BuildEditorModel(page, null)
Page = _contentManager.BuildEditorModel(page)
};
return View(model);
}
@@ -95,7 +95,7 @@ namespace Orchard.Sandbox.Controllers {
var page = _contentManager.Get<SandboxPage>(id);
var model = new PageEditViewModel {
Page = _contentManager.UpdateEditorModel(page, null, this)
Page = _contentManager.UpdateEditorModel(page, this)
};
if (!ModelState.IsValid)
return View(model);

View File

@@ -22,7 +22,7 @@ namespace Orchard.Sandbox.Models {
Filters.Add(new ActivatingFilter<RoutableAspect>(SandboxPage.ContentType.Name));
Filters.Add(new ActivatingFilter<BodyAspect>(SandboxPage.ContentType.Name));
Filters.Add(new StorageFilter<SandboxPageRecord>(pageRepository) { AutomaticallyCreateMissingRecord = true });
Filters.Add(new ContentItemTemplates<SandboxPage>("Summary"));
Filters.Add(new ContentItemTemplates<SandboxPage>("Items/Sandbox.Page", "Summary"));
OnGetItemMetadata<SandboxPage>((context, page) => {
context.Metadata.DisplayText = page.Record.Name;

View File

@@ -102,7 +102,7 @@ namespace Orchard.Tags.Controllers {
var tag = _tagService.GetTagByName(tagName);
var items =
_tagService.GetTaggedContentItems(tag.Id).Select(
ic => _contentManager.BuildDisplayModel(ic, null, "SummaryForSearch"));
ic => _contentManager.BuildDisplayModel(ic, "SummaryForSearch"));
var viewModel = new TagsSearchViewModel {
TagName = tag.TagName,

View File

@@ -13,65 +13,64 @@ using Orchard.Users.ViewModels;
namespace Orchard.Users.Controllers {
public class AdminController : Controller, IUpdateModel {
private readonly IMembershipService _membershipService;
private readonly IContentManager _contentManager;
private readonly IRepository<UserRecord> _userRepository;
private readonly INotifier _notifier;
public AdminController(
IMembershipService membershipService,
IContentManager contentManager,
IRepository<UserRecord> userRepository,
INotifier notifier) {
IOrchardServices services,
IMembershipService membershipService) {
Services = services;
_membershipService = membershipService;
_contentManager = contentManager;
_userRepository = userRepository;
_notifier = notifier;
T = NullLocalizer.Instance;
}
public IUser CurrentUser { get; set; }
public IOrchardServices Services { get; set; }
public Localizer T { get; set; }
public ActionResult Index() {
var model = new UsersIndexViewModel();
var users = _contentManager.Query<User, UserRecord>("user")
public ActionResult Index() {
var users = Services.ContentManager
.Query<User, UserRecord>(Models.User.ContentType.Name)
.Where(x => x.UserName != null)
.List();
model.Rows = users.Select(x => new UsersIndexViewModel.Row { User = x }).ToList();
var model = new UsersIndexViewModel {
Rows = users
.Select(x => new UsersIndexViewModel.Row { User = x })
.ToList()
};
return View(model);
}
public ActionResult Create() {
var user = _contentManager.New("user");
var user = Services.ContentManager.New<IUser>(Models.User.ContentType.Name);
var model = new UserCreateViewModel {
EditorModel = _contentManager.BuildEditorModel(user, null)
User = Services.ContentManager.BuildEditorModel(user)
};
return View(model);
}
[HttpPost]
public ActionResult Create(UserCreateViewModel model) {
[HttpPost, ActionName("Create")]
public ActionResult _Create() {
var model = new UserCreateViewModel();
UpdateModel(model);
if (model.Password != model.ConfirmPassword) {
ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match").ToString());
}
if (ModelState.IsValid == false) {
model.EditorModel = _contentManager.UpdateEditorModel(_contentManager.New("user"), null, this);
return View(model);
}
var user = _membershipService.CreateUser(new CreateUserParams(
model.UserName,
model.Password,
model.Email,
null, null, true));
model.EditorModel = _contentManager.UpdateEditorModel(user, null, this);
model.User = Services.ContentManager.UpdateEditorModel(user, this);
if (model.Password != model.ConfirmPassword) {
AddModelError("ConfirmPassword", T("Password confirmation must match"));
}
if (ModelState.IsValid == false) {
//TODO: rollback transaction
Services.TransactionManager.Cancel();
return View(model);
}
@@ -79,29 +78,33 @@ namespace Orchard.Users.Controllers {
}
public ActionResult Edit(int id) {
var model = new UserEditViewModel { User = _contentManager.Get<User>(id) };
model.EditorModel = _contentManager.BuildEditorModel(model.User.ContentItem, null);
return View(model);
return View(new UserEditViewModel {
User = Services.ContentManager.BuildEditorModel<User>(id)
});
}
[HttpPost]
public ActionResult Edit(int id, FormCollection input) {
var model = new UserEditViewModel { User = _contentManager.Get<User>(id) };
model.EditorModel = _contentManager.UpdateEditorModel(model.User.ContentItem, null, this);
[HttpPost, ActionName("Edit")]
public ActionResult _Edit(int id) {
var model = new UserEditViewModel {
User = Services.ContentManager.UpdateEditorModel<User>(id, this)
};
if (!TryUpdateModel(model, input.ToValueProvider())) {
// apply additional model properties that were posted on form
UpdateModel(model);
if (!ModelState.IsValid) {
Services.TransactionManager.Cancel();
return View(model);
}
_notifier.Information(T("User information updated"));
Services.Notifier.Information(T("User information updated"));
return RedirectToAction("Edit", new { id });
}
bool IUpdateModel.TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) {
return TryUpdateModel(model, prefix, includeProperties, excludeProperties);
}
void IUpdateModel.AddModelError(string key, LocalizedString errorMessage) {
public void AddModelError(string key, LocalizedString errorMessage) {
ModelState.AddModelError(key, errorMessage.ToString());
}
}

View File

@@ -1,10 +0,0 @@
using System.Web.Mvc;
namespace Orchard.Users.Controllers {
[HandleError]
public class HomeController : Controller {
public ActionResult Index() {
return View();
}
}
}

View File

@@ -12,6 +12,7 @@ namespace Orchard.Users.Models {
public UserHandler(IRepository<UserRecord> repository) {
Filters.Add(new ActivatingFilter<User>("user"));
Filters.Add(new StorageFilter<UserRecord>(repository));
Filters.Add(new ContentItemTemplates<User>("Items/Users.User"));
}
}
}

View File

@@ -62,7 +62,6 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Models\User.cs" />
<Compile Include="Models\UserHandler.cs" />
<Compile Include="Models\UserRecord.cs" />
@@ -78,10 +77,9 @@
<Content Include="Views\Admin\Edit.aspx" />
<Content Include="Views\Admin\Create.aspx" />
<Content Include="Views\Admin\EditorTemplates\inputPasswordLarge.ascx" />
<Content Include="Views\Admin\EditorTemplates\UserEditViewModel.ascx" />
<Content Include="Views\Admin\EditorTemplates\inputTextLarge.ascx" />
<Content Include="Views\Admin\EditorTemplates\UserCreateViewModel.ascx" />
<Content Include="Views\Admin\Index.aspx" />
<Content Include="Views\EditorTemplates\Items\Users.User.ascx" />
<Content Include="Web.config" />
<Content Include="Views\Web.config" />
</ItemGroup>

View File

@@ -3,6 +3,8 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Orchard.Models.ViewModels;
using Orchard.Mvc.ViewModels;
using Orchard.Security;
using Orchard.Users.Models;
namespace Orchard.Users.ViewModels {
public class UserCreateViewModel : AdminViewModel {
@@ -18,6 +20,6 @@ namespace Orchard.Users.ViewModels {
[Required, DataType(DataType.Password)]
public string ConfirmPassword { get; set; }
public ItemEditorModel EditorModel { get; set; }
public ItemEditorModel<IUser> User { get; set; }
}
}

View File

@@ -7,26 +7,23 @@ using Orchard.Users.Models;
namespace Orchard.Users.ViewModels {
public class UserEditViewModel : AdminViewModel {
public User User { get; set; }
public ItemEditorModel EditorModel { get; set; }
[HiddenInput(DisplayValue = false)]
public int Id {
get { return User.Id; }
get { return User.Item.Id; }
}
[Required]
public string UserName {
get { return User.As<User>().Record.UserName; }
set { User.As<User>().Record.UserName = value; }
get { return User.Item.Record.UserName; }
set { User.Item.Record.UserName = value; }
}
[Required]
public string Email {
get { return User.As<User>().Record.Email; }
set { User.As<User>().Record.Email = value; }
get { return User.Item.Record.Email; }
set { User.Item.Record.Email = value; }
}
public ItemEditorModel<User> User { get; set; }
}
}

View File

@@ -1,11 +1,16 @@
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Orchard.Users.ViewModels.UserCreateViewModel>" %>
<%@ Import Namespace="Orchard.Security" %>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<h2>Add User</h2>
<%using (Html.BeginForm()) { %>
<%= Html.ValidationSummary() %>
<%= Html.EditorForModel() %>
<%=Html.ValidationSummary() %>
<%=Html.EditorFor(m=>m.UserName, "inputTextLarge") %>
<%=Html.EditorFor(m=>m.Email, "inputTextLarge") %>
<%=Html.EditorFor(m=>m.Password, "inputPasswordLarge") %>
<%=Html.EditorFor(m=>m.ConfirmPassword, "inputPasswordLarge") %>
<%=Html.EditorForItem(Model.User) %>
<fieldset>
<input class="button" type="submit" value="Create" />
</fieldset>
<% } %>
<% } %>

View File

@@ -1,12 +1,16 @@
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Orchard.Users.ViewModels.UserEditViewModel>" %>
<%@ Import Namespace="Orchard.Security" %>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<h2>Edit User</h2>
<h2>
Edit User</h2>
<%using (Html.BeginForm()) { %>
<ol>
<%= Html.ValidationSummary() %>
<%= Html.EditorForModel() %>
<fieldset>
<input class="button" type="submit" value="Save" />
</fieldset>
<% } %>
<%=Html.ValidationSummary() %>
<%=Html.EditorFor(m=>m.Id) %>
<%=Html.EditorFor(m=>m.UserName, "inputTextLarge") %>
<%=Html.EditorFor(m=>m.Email, "inputTextLarge") %>
<%=Html.EditorForItem(Model.User) %>
<fieldset>
<input class="button" type="submit" value="Save" />
</fieldset>
<% } %>

View File

@@ -1,11 +0,0 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Orchard.Users.ViewModels.UserCreateViewModel>" %>
<%@ Import Namespace="Orchard.Utility" %>
<%=Html.EditorFor(m=>m.UserName, "inputTextLarge") %>
<%=Html.EditorFor(m=>m.Email, "inputTextLarge") %>
<%=Html.EditorFor(m=>m.Password, "inputPasswordLarge") %>
<%=Html.EditorFor(m=>m.ConfirmPassword, "inputPasswordLarge") %>
<%
foreach(var e in Model.EditorModel.Editors) {
var editor = e;%>
<%=Html.EditorFor(m => editor.Model, editor.TemplateName, editor.Prefix)%>
<% } %>

View File

@@ -1,8 +0,0 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Orchard.Users.ViewModels.UserEditViewModel>" %>
<%@ Import Namespace="Orchard.Utility" %>
<%=Html.EditorFor(m=>m.Id) %>
<%=Html.EditorFor(m=>m.UserName, "inputTextLarge") %>
<%=Html.EditorFor(m=>m.Email, "inputTextLarge") %>
<% foreach(var e in Model.EditorModel.Editors) {%>
<%=Html.EditorFor(m => e.Model, e.TemplateName, e.Prefix)%>
<%} %>

View File

@@ -0,0 +1,5 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ItemEditorModel<User>>" %>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<%@ Import Namespace="Orchard.Models.ViewModels" %>
<%@ Import Namespace="Orchard.Users.Models" %>
<%=Html.EditorZonesAny() %>

View File

@@ -0,0 +1,16 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BaseViewModel>" %>
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<% Html.RegisterStyle(ResolveUrl("~/Themes/BlueSky/Styles/site.css")); %>
<div class="page">
<div id="header">
<div id="title"><h1>My MVC Application</h1></div>
<%Html.Zone("header"); Html.Zone("menu"); %>
</div>
<div id="main">
<%Html.Zone("content", () => Html.RenderBody() );%>
<div id="footer"><%Html.Zone("footer");%></div>
</div>
</div>

View File

@@ -78,7 +78,7 @@ namespace Orchard.Data {
public void Dispose() {
if (_session != null) {
_session.Flush();
//_session.Flush();
_session.Close();
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Transactions;
using System.Web.Mvc;
using Orchard.Mvc.Filters;
namespace Orchard.Data {
public interface ITransactionManager : IDependency {
void Cancel();
}
public class TransactionManager : ITransactionManager, IDisposable {
private readonly TransactionScope _scope;
private bool _cancelled;
public TransactionManager() {
_scope = new TransactionScope(TransactionScopeOption.Required);
}
void IDisposable.Dispose() {
if (!_cancelled)
_scope.Complete();
_scope.Dispose();
}
void ITransactionManager.Cancel() {
_cancelled = true;
}
}
public class TransactionFilter : FilterProvider, IExceptionFilter{
private readonly ITransactionManager _transactionManager;
public TransactionFilter(ITransactionManager transactionManager) {
_transactionManager = transactionManager;
}
public void OnException(ExceptionContext filterContext) {
_transactionManager.Cancel();
}
}
}

View File

@@ -5,6 +5,7 @@ using Autofac.Builder;
using Autofac.Integration.Web;
using System.Collections.Generic;
using Orchard.Mvc;
using Orchard.Mvc.ViewEngines;
namespace Orchard.Environment {
public class DefaultOrchardHost : IOrchardHost {
@@ -36,6 +37,7 @@ namespace Orchard.Environment {
shell.Activate();
_current = shell;
ViewEngines.Engines.Insert(0, new LayoutViewEngine(null));
_controllerBuilder.SetControllerFactory(new OrchardControllerFactory());
ServiceLocator.SetLocator(t=>_containerProvider.RequestContainer.Resolve(t));
}

View File

@@ -39,40 +39,40 @@ namespace Orchard.Environment {
public ILogger Logger { get; set; }
static IEnumerable<string> OrchardLocationFormats() {
return new[] {
"~/Packages/{2}/Views/{1}/{0}.aspx",
"~/Packages/{2}/Views/{1}/{0}.ascx",
"~/Packages/{2}/Views/Shared/{0}.aspx",
"~/Packages/{2}/Views/Shared/{0}.ascx",
"~/Core/{2}/Views/{1}/{0}.aspx",
"~/Core/{2}/Views/{1}/{0}.ascx",
"~/Core/{2}/Views/Shared/{0}.aspx",
"~/Core/{2}/Views/Shared/{0}.ascx",
};
}
//static IEnumerable<string> OrchardLocationFormats() {
// return new[] {
// "~/Packages/{2}/Views/{1}/{0}.aspx",
// "~/Packages/{2}/Views/{1}/{0}.ascx",
// "~/Packages/{2}/Views/Shared/{0}.aspx",
// "~/Packages/{2}/Views/Shared/{0}.ascx",
// "~/Core/{2}/Views/{1}/{0}.aspx",
// "~/Core/{2}/Views/{1}/{0}.ascx",
// "~/Core/{2}/Views/Shared/{0}.aspx",
// "~/Core/{2}/Views/Shared/{0}.ascx",
// };
//}
public void Activate() {
_routePublisher.Publish(_routeProviders.SelectMany(provider => provider.GetRoutes()));
_modelBinderPublisher.Publish(_modelBinderProviders.SelectMany(provider => provider.GetModelBinders()));
var viewEngine = _viewEngines.OfType<VirtualPathProviderViewEngine>().Single();
viewEngine.AreaViewLocationFormats = OrchardLocationFormats()
.Concat(viewEngine.AreaViewLocationFormats)
.Distinct()
.ToArray();
viewEngine.AreaPartialViewLocationFormats = OrchardLocationFormats()
.Concat(viewEngine.AreaPartialViewLocationFormats)
.Distinct()
.ToArray();
//var viewEngine = _viewEngines.OfType<VirtualPathProviderViewEngine>().Single();
//viewEngine.AreaViewLocationFormats = OrchardLocationFormats()
// .Concat(viewEngine.AreaViewLocationFormats)
// .Distinct()
// .ToArray();
//viewEngine.AreaPartialViewLocationFormats = OrchardLocationFormats()
// .Concat(viewEngine.AreaPartialViewLocationFormats)
// .Distinct()
// .ToArray();
var activePackageDescriptors = _extensionManager.ActiveExtensions().Select(x => x.Descriptor);
var sharedLocationFormats = activePackageDescriptors.Select(x => ModelsLocationFormat(x));
viewEngine.PartialViewLocationFormats = sharedLocationFormats
.Concat(viewEngine.PartialViewLocationFormats)
.Distinct()
.ToArray();
//var activePackageDescriptors = _extensionManager.ActiveExtensions().Select(x => x.Descriptor);
//var sharedLocationFormats = activePackageDescriptors.Select(x => ModelsLocationFormat(x));
//viewEngine.PartialViewLocationFormats = sharedLocationFormats
// .Concat(viewEngine.PartialViewLocationFormats)
// .Distinct()
// .ToArray();
_events.Invoke(x => x.Activated(), Logger);
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using JetBrains.Annotations;
using Orchard.Data;
using Orchard.Models;
using Orchard.Security;
using Orchard.UI.Notify;
namespace Orchard.Environment {
[UsedImplicitly]
public class OrchardServices : IOrchardServices {
public OrchardServices(
IContentManager contentManager,
ITransactionManager transactionManager,
IAuthorizer authorizer,
INotifier notifier) {
ContentManager = contentManager;
TransactionManager = transactionManager;
Authorizer = authorizer;
Notifier = notifier;
}
public IContentManager ContentManager { get; set; }
public ITransactionManager TransactionManager {get;set;}
public IAuthorizer Authorizer { get; set; }
public INotifier Notifier { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Orchard.Data;
using Orchard.Models;
using Orchard.Security;
using Orchard.UI.Notify;
namespace Orchard {
public interface IOrchardServices : IDependency {
IContentManager ContentManager { get; }
ITransactionManager TransactionManager { get; }
IAuthorizer Authorizer { get; set; }
INotifier Notifier { get; }
}
}

View File

@@ -1,11 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Orchard.Models.Driver;
using Orchard.Models.Records;
using Orchard.Models.ViewModels;
namespace Orchard.Models {
public static class ContentExtensions {
/* Item creation and accessing extension methods */
public static T New<T>(this IContentManager manager, string contentType) where T : class, IContent {
var contentItem = manager.New(contentType);
if (contentItem == null)
@@ -18,6 +23,10 @@ namespace Orchard.Models {
return part;
}
public static T Create<T>(this IContentManager manager, string contentType) where T : class, IContent {
return manager.Create<T>(contentType, init => { });
}
public static T Create<T>(this IContentManager manager, string contentType, Action<T> initialize) where T : class, IContent {
var content = manager.New<T>(contentType);
if (content == null)
@@ -34,6 +43,23 @@ namespace Orchard.Models {
}
/* Display and editor convenience extension methods */
public static ItemDisplayModel<T> BuildDisplayModel<T>(this IContentManager manager, int id, string displayType) where T : class, IContent {
return manager.BuildDisplayModel(manager.Get<T>(id), displayType);
}
public static ItemEditorModel<T> BuildEditorModel<T>(this IContentManager manager, int id) where T : class, IContent {
return manager.BuildEditorModel(manager.Get<T>(id));
}
public static ItemEditorModel<T> UpdateEditorModel<T>(this IContentManager manager, int id, IUpdateModel updater) where T : class, IContent {
return manager.UpdateEditorModel(manager.Get<T>(id), updater);
}
/* Query related extension methods */
public static IContentQuery<TPart> Query<TPart>(this IContentManager manager)
where TPart : ContentPart {
return manager.Query().ForPart<TPart>();
@@ -69,6 +95,7 @@ namespace Orchard.Models {
}
/* Aggregate item/part type casting extension methods */
public static bool Is<T>(this IContent content) {
return content == null ? false : content.ContentItem.Has(typeof(T));

View File

@@ -136,13 +136,9 @@ namespace Orchard.Models {
return context.Metadata;
}
public ItemDisplayModel<TContentPart> BuildDisplayModel<TContentPart>(TContentPart content, string groupName, string displayType) where TContentPart : IContent {
return BuildDisplayModel(content, groupName, displayType, null);
}
public ItemDisplayModel<TContent> BuildDisplayModel<TContent>(TContent content, string groupName, string displayType, string templatePath) where TContent : IContent {
var itemView = new ItemDisplayModel<TContent> { Item = content, Displays = Enumerable.Empty<TemplateViewModel>() };
var context = new BuildDisplayModelContext(itemView, groupName, displayType, templatePath);
public ItemDisplayModel<TContentPart> BuildDisplayModel<TContentPart>(TContentPart content, string displayType) where TContentPart : IContent {
var itemView = new ItemDisplayModel<TContentPart> {Item = content, Displays = Enumerable.Empty<TemplateViewModel>()};
var context = new BuildDisplayModelContext(itemView, displayType);
foreach (var handler in Handlers) {
handler.BuildDisplayModel(context);
}
@@ -150,13 +146,9 @@ namespace Orchard.Models {
return itemView;
}
public ItemEditorModel<TContent> BuildEditorModel<TContent>(TContent content, string groupName) where TContent : IContent {
return BuildEditorModel(content, groupName, null);
}
public ItemEditorModel<TContent> BuildEditorModel<TContent>(TContent content, string groupName, string templatePath) where TContent : IContent {
var itemView = new ItemEditorModel<TContent> { Item = content, Editors = Enumerable.Empty<TemplateViewModel>() };
var context = new BuildEditorModelContext(itemView, groupName, templatePath);
public ItemEditorModel<TContentPart> BuildEditorModel<TContentPart>(TContentPart content) where TContentPart : IContent {
var itemView = new ItemEditorModel<TContentPart> { Item = content, Editors = Enumerable.Empty<TemplateViewModel>() };
var context = new BuildEditorModelContext(itemView);
foreach (var handler in Handlers) {
handler.BuildEditorModel(context);
}
@@ -164,13 +156,10 @@ namespace Orchard.Models {
return itemView;
}
public ItemEditorModel<TContent> UpdateEditorModel<TContent>(TContent content, string groupName, IUpdateModel updater) where TContent : IContent {
return UpdateEditorModel(content, groupName, updater, null);
}
public ItemEditorModel<TContentPart> UpdateEditorModel<TContentPart>(TContentPart content, IUpdateModel updater) where TContentPart : IContent {
var itemView = new ItemEditorModel<TContentPart> { Item = content, Editors = Enumerable.Empty<TemplateViewModel>() };
public ItemEditorModel<TContent> UpdateEditorModel<TContent>(TContent content, string groupName, IUpdateModel updater, string templatePath) where TContent : IContent {
var itemView = new ItemEditorModel<TContent> { Item = content, Editors = Enumerable.Empty<TemplateViewModel>() };
var context = new UpdateEditorModelContext(itemView, groupName, updater, templatePath);
var context = new UpdateEditorModelContext(itemView, updater);
foreach (var handler in Handlers) {
handler.UpdateEditorModel(context);
}

View File

@@ -3,19 +3,15 @@ using Orchard.Models.ViewModels;
namespace Orchard.Models.Driver {
public class BuildDisplayModelContext {
public BuildDisplayModelContext(ItemDisplayModel displayModel, string groupName, string displayType, string templatePath) {
ContentItem = displayModel.Item;
GroupName = groupName;
public BuildDisplayModelContext(ItemDisplayModel displayModel, string displayType) {
ContentItem = displayModel.Item;
DisplayType = displayType;
DisplayModel = displayModel;
TemplatePath = templatePath;
}
public ContentItem ContentItem { get; private set; }
public string GroupName { get; private set; }
public string DisplayType { get; private set; }
public ItemDisplayModel DisplayModel { get; private set; }
public string TemplatePath { get; private set; }
public void AddDisplay(TemplateViewModel display) {
DisplayModel.Displays = DisplayModel.Displays.Concat(new[] { display });

View File

@@ -3,17 +3,13 @@ using Orchard.Models.ViewModels;
namespace Orchard.Models.Driver {
public class BuildEditorModelContext {
public BuildEditorModelContext(ItemEditorModel editorModel, string groupName, string templatePath) {
ContentItem = editorModel.Item;
GroupName = groupName;
public BuildEditorModelContext(ItemEditorModel editorModel) {
ContentItem = editorModel.Item;
EditorModel = editorModel;
TemplatePath = templatePath;
}
public ContentItem ContentItem { get; private set; }
public string GroupName { get; private set; }
public ItemEditorModel EditorModel { get; private set; }
public string TemplatePath { get; private set; }
public ContentItem ContentItem { get; set; }
public ItemEditorModel EditorModel { get; set; }
public void AddEditor(TemplateViewModel editor) {
EditorModel.Editors = EditorModel.Editors.Concat(new[] { editor });

View File

@@ -5,19 +5,29 @@ using Orchard.Models.ViewModels;
namespace Orchard.Models.Driver {
public class ContentItemTemplates<TContent> : TemplateFilterBase<TContent> where TContent : class, IContent {
private readonly string _templateName;
// todo: (heskew) use _prefix?
private readonly string _prefix;
private readonly string[] _displayTypes;
private Action<UpdateEditorModelContext, ItemEditorModel<TContent>> _updater;
public ContentItemTemplates(params string[] displayTypes) {
_displayTypes = displayTypes;
public ContentItemTemplates(string templateName)
: this(templateName, "") {
}
public ContentItemTemplates(string templateName, string displayTypes) {
_templateName = templateName;
_displayTypes = (displayTypes ?? "").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
_updater = (context, viewModel) => context.Updater.TryUpdateModel(viewModel, "", null, null);
}
protected override void BuildDisplayModel(BuildDisplayModelContext context, TContent instance) {
context.DisplayModel.TemplateName = _templateName;
var longestMatch = LongestMatch(context.DisplayType);
context.DisplayModel.TemplateName = (!string.IsNullOrEmpty(context.TemplatePath) ? context.TemplatePath : typeof(TContent).Name) + "/" + longestMatch;
if (!string.IsNullOrEmpty(longestMatch))
context.DisplayModel.TemplateName += "." + longestMatch;
context.DisplayModel.Prefix = _prefix;
if (context.DisplayModel.GetType() != typeof(ItemDisplayModel<TContent>)) {
@@ -45,7 +55,7 @@ namespace Orchard.Models.Driver {
}
protected override void BuildEditorModel(BuildEditorModelContext context, TContent instance) {
context.EditorModel.TemplateName = (!string.IsNullOrEmpty(context.TemplatePath) ? context.TemplatePath : typeof(TContent).Name) + "/Detail";
context.EditorModel.TemplateName = _templateName;
context.EditorModel.Prefix = _prefix;
if (context.EditorModel.GetType() != typeof(ItemEditorModel<TContent>)) {
context.EditorModel.Adaptor = (html, viewModel) => {
@@ -62,7 +72,7 @@ namespace Orchard.Models.Driver {
_updater(context, (ItemEditorModel<TContent>)context.EditorModel);
else
_updater(context, new ItemEditorModel<TContent>(context.EditorModel));
context.EditorModel.TemplateName = (!string.IsNullOrEmpty(context.TemplatePath) ? context.TemplatePath : typeof(TContent).Name) + "/Detail";
context.EditorModel.TemplateName = _templateName;
context.EditorModel.Prefix = _prefix;
}

View File

@@ -2,8 +2,8 @@ using Orchard.Models.ViewModels;
namespace Orchard.Models.Driver {
public class UpdateEditorModelContext : BuildEditorModelContext {
public UpdateEditorModelContext(ItemEditorModel editorModel, string groupName, IUpdateModel updater, string templatePath)
: base(editorModel, groupName, templatePath) {
public UpdateEditorModelContext(ItemEditorModel editorModel, IUpdateModel updater)
: base(editorModel) {
Updater = updater;
}

View File

@@ -15,11 +15,8 @@ namespace Orchard.Models {
ContentItemMetadata GetItemMetadata(IContent contentItem);
ItemDisplayModel<TContent> BuildDisplayModel<TContent>(TContent content, string groupName, string displayType) where TContent : IContent;
ItemDisplayModel<TContent> BuildDisplayModel<TContent>(TContent content, string groupName, string displayType, string templatePath) where TContent : IContent;
ItemEditorModel<TContent> BuildEditorModel<TContent>(TContent content, string groupName) where TContent : IContent;
ItemEditorModel<TContent> BuildEditorModel<TContent>(TContent content, string groupName, string templatePath) where TContent : IContent;
ItemEditorModel<TContent> UpdateEditorModel<TContent>(TContent content, string groupName, IUpdateModel updater) where TContent : IContent;
ItemEditorModel<TContent> UpdateEditorModel<TContent>(TContent content, string groupName, IUpdateModel updater, string templatePath) where TContent : IContent;
ItemDisplayModel<TContent> BuildDisplayModel<TContent>(TContent content, string displayType) where TContent : IContent;
ItemEditorModel<TContent> BuildEditorModel<TContent>(TContent content) where TContent : IContent;
ItemEditorModel<TContent> UpdateEditorModel<TContent>(TContent content, IUpdateModel updater) where TContent : IContent;
}
}

View File

@@ -17,28 +17,28 @@ namespace Orchard.Models {
public abstract class PartDriver<TPart> : IPartDriver where TPart : class, IContent {
DriverResult IPartDriver.BuildDisplayModel(BuildDisplayModelContext context) {
var part = context.ContentItem.As<TPart>();
return part == null ? null : Display(part, context.GroupName, context.DisplayType);
return part == null ? null : Display(part, context.DisplayType);
}
DriverResult IPartDriver.BuildEditorModel(BuildEditorModelContext context) {
var part = context.ContentItem.As<TPart>();
return part == null ? null : Editor(part, context.GroupName);
return part == null ? null : Editor(part);
}
DriverResult IPartDriver.UpdateEditorModel(UpdateEditorModelContext context) {
var part = context.ContentItem.As<TPart>();
return part == null ? null : Editor(part, context.GroupName, context.Updater);
return part == null ? null : Editor(part, context.Updater);
}
protected virtual DriverResult Display(TPart part, string groupName, string displayType) {
protected virtual DriverResult Display(TPart part, string displayType) {
return null;
}
protected virtual DriverResult Editor(TPart part, string groupName) {
protected virtual DriverResult Editor(TPart part) {
return null;
}
protected virtual DriverResult Editor(TPart part, string groupName, IUpdateModel updater) {
protected virtual DriverResult Editor(TPart part, IUpdateModel updater) {
return null;
}
@@ -62,13 +62,13 @@ namespace Orchard.Models {
return (typeof (TPart).Name);
}
}
protected override DriverResult Display(TPart part, string groupName, string displayType) {
protected override DriverResult Display(TPart part, string displayType) {
return PartialView(part);
}
protected override DriverResult Editor(TPart part, string groupName) {
protected override DriverResult Editor(TPart part) {
return PartialView(part);
}
protected override DriverResult Editor(TPart part, string groupName, IUpdateModel updater) {
protected override DriverResult Editor(TPart part, IUpdateModel updater) {
updater.TryUpdateModel(part, Prefix, null, null);
return PartialView(part);
}

View File

@@ -8,13 +8,13 @@ using Orchard.Models.ViewModels;
namespace Orchard.Mvc.Html {
public static class ItemDisplayExtensions {
public static MvcHtmlString DisplayForItem<TModel, TItemViewModel>(this HtmlHelper<TModel> html, TItemViewModel itemViewModel) where TItemViewModel : ItemDisplayModel {
return html.DisplayForItem(x => itemViewModel);
public static MvcHtmlString DisplayForItem<TModel, TItemModel>(this HtmlHelper<TModel> html, TItemModel item) where TItemModel : ItemDisplayModel {
return html.DisplayForItem(x => item);
}
public static MvcHtmlString DisplayForItem<TModel, TItemViewModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, TItemViewModel>> expression) where TItemViewModel : ItemDisplayModel {
public static MvcHtmlString DisplayForItem<TModel, TItemModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, TItemModel>> expression) where TItemModel : ItemDisplayModel {
var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
var model = (TItemViewModel)metadata.Model;
var model = (TItemModel)metadata.Model;
if (model.Adaptor != null) {
return model.Adaptor(html, model).DisplayForModel(model.TemplateName, model.Prefix ?? "");

View File

@@ -8,15 +8,18 @@ using Orchard.Models.ViewModels;
namespace Orchard.Mvc.Html {
public static class ItemEditorExtensions {
public static MvcHtmlString EditorForItem<TModel, TItemViewModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, TItemViewModel>> expression) where TItemViewModel : ItemEditorModel {
public static MvcHtmlString EditorForItem<TModel, TItemModel>(this HtmlHelper<TModel> html, TItemModel item) where TItemModel : ItemEditorModel {
return html.EditorForItem(x => item);
}
public static MvcHtmlString EditorForItem<TModel, TItemModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, TItemModel>> expression) where TItemModel : ItemEditorModel {
var metadata = ModelMetadata.FromLambdaExpression(expression, html.ViewData);
var model = (TItemViewModel)metadata.Model;
var model = (TItemModel)metadata.Model;
if (model.Adaptor != null) {
return model.Adaptor(html, model).EditorForModel(model.TemplateName, model.Prefix ?? "");
}
return html.EditorFor(expression, model.TemplateName, model.Prefix ?? "");
}

View File

@@ -7,26 +7,29 @@ using System.Web.Mvc;
namespace Orchard.Mvc.ViewEngines {
public class LayoutView : IView {
private readonly LayoutViewEngine _viewEngine;
private ViewEngineResult[] _viewEngineResults;
public LayoutView(ViewEngineResult[] views) {
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);
var layoutViewContext = LayoutViewContext.From(viewContext);
for (var index = 0; index != _viewEngineResults.Length; ++index) {
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 childWriter = new StringWriter();
viewEngineResult.View.Render(viewContext, childWriter);
layoutViewContext.BodyContent = childWriter.ToString();
for (var index = 0; index != _viewEngineResults.Length; ++index) {
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 childWriter = new StringWriter();
viewEngineResult.View.Render(viewContext, childWriter);
layoutViewContext.BodyContent = childWriter.ToString();
}
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Web.Mvc;
using Orchard.Mvc.ViewModels;
@@ -11,6 +12,11 @@ namespace Orchard.Mvc.ViewEngines {
}
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache) {
var scope = Scope.From(controllerContext);
if (scope != null && scope.LayoutViewEngine != null) {
return scope.LayoutViewEngine._viewEngines.FindPartialView(controllerContext, partialViewName);
}
return new ViewEngineResult(Enumerable.Empty<string>());
}
@@ -20,15 +26,17 @@ namespace Orchard.Mvc.ViewEngines {
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)
|| !(controllerContext.Controller.ViewData.Model is BaseViewModel))
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)
return new ViewEngineResult(Enumerable.Empty<string>());
var bodyView = _viewEngines.FindPartialView(controllerContext, viewName);
var layoutView = _viewEngines.FindPartialView(controllerContext, "layout");
var documentView = _viewEngines.FindPartialView(controllerContext, "document");
@@ -36,7 +44,7 @@ namespace Orchard.Mvc.ViewEngines {
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>()))
@@ -46,7 +54,7 @@ namespace Orchard.Mvc.ViewEngines {
return missingTemplatesResult;
}
var view = new LayoutView(new[] {
var view = new LayoutView(this, new[] {
bodyView,
layoutView,
documentView,
@@ -56,9 +64,34 @@ namespace Orchard.Mvc.ViewEngines {
}
public void ReleaseView(ControllerContext controllerContext, IView view) {
var layoutView = (LayoutView) view;
var layoutView = (LayoutView)view;
layoutView.ReleaseViews(controllerContext);
}
public IDisposable CreateScope(ViewContext context) {
return new Scope(context) { LayoutViewEngine = this };
}
class Scope : IDisposable {
private readonly ControllerContext _context;
private readonly Scope _prior;
public Scope(ControllerContext context) {
_context = context;
_prior = From(context);
context.HttpContext.Items[typeof(Scope)] = this;
}
public LayoutViewEngine LayoutViewEngine { get; set; }
public void Dispose() {
_context.HttpContext.Items[typeof(Scope)] = _prior;
}
public static Scope From(ControllerContext context) {
return (Scope)context.HttpContext.Items[typeof(Scope)];
}
}
}

View File

@@ -57,12 +57,11 @@ namespace Orchard.Mvc.ViewEngines {
var requestViewEngines = new ViewEngineCollection(
themeViewEngines
.Concat(packageViewEngines)
.Concat(_viewEngines)
.ToArray());
var layoutViewEngine = new LayoutViewEngine(requestViewEngines);
viewResultBase.ViewEngineCollection = new ViewEngineCollection(_viewEngines.ToList());
viewResultBase.ViewEngineCollection = new ViewEngineCollection();
viewResultBase.ViewEngineCollection.Insert(0, layoutViewEngine);
}

View File

@@ -23,14 +23,15 @@ namespace Orchard.Mvc.ViewEngines {
ViewLocationFormats = DisabledFormats,
AreaMasterLocationFormats = DisabledFormats,
AreaViewLocationFormats = DisabledFormats,
AreaPartialViewLocationFormats=DisabledFormats,
};
// enable /Views/Shared/{partialName}
// enable /Views/Shared/"DisplayTemplates/"+{templateName}
// enable /Views/Shared/"EditorTemplates/+{templateName}
// enable /Views/{partialName}
// enable /Views/"DisplayTemplates/"+{templateName}
// enable /Views/"EditorTemplates/+{templateName}
viewEngine.PartialViewLocationFormats = new[] {
parameters.VirtualPath + "/Views/Shared/{0}.ascx",
parameters.VirtualPath + "/Views/Shared/{0}.aspx",
parameters.VirtualPath + "/Views/{0}.ascx",
parameters.VirtualPath + "/Views/{0}.aspx",
};
// for "routed" request views...
@@ -44,19 +45,29 @@ namespace Orchard.Mvc.ViewEngines {
}
public IViewEngine CreatePackagesViewEngine(CreatePackagesViewEngineParams parameters) {
var areaFormats = new[] {
"~/Core/{2}/Views/{1}/{0}.ascx",
"~/Core/{2}/Views/{1}/{0}.aspx",
"~/Packages/{2}/Views/{1}/{0}.ascx",
"~/Packages/{2}/Views/{1}/{0}.aspx",
};
var universalFormats = parameters.VirtualPaths
.SelectMany(x => new[] {
x + "/Views/{0}.ascx",
x + "/Views/{0}.aspx",
})
.ToArray();
var viewEngine = new WebFormViewEngine {
MasterLocationFormats = DisabledFormats,
ViewLocationFormats = DisabledFormats,
ViewLocationFormats = universalFormats,
PartialViewLocationFormats = universalFormats,
AreaMasterLocationFormats = DisabledFormats,
AreaViewLocationFormats = DisabledFormats,
AreaPartialViewLocationFormats = DisabledFormats,
AreaViewLocationFormats = areaFormats,
AreaPartialViewLocationFormats = areaFormats,
};
viewEngine.PartialViewLocationFormats = parameters.VirtualPaths
.Select(x => x + "/Views/Shared/{0}.ascx")
.Concat(parameters.VirtualPaths.Select(s => s + "/Views/Shared/{0}.aspx"))
.ToArray();
return viewEngine;
}
}

View File

@@ -66,6 +66,7 @@
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Transactions" />
<Reference Include="System.Web" />
<Reference Include="System.Web.Abstractions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
@@ -122,10 +123,13 @@
<Compile Include="Controllers\HomeController.cs" />
<Compile Include="Data\Conventions\AttributeCollectionConvention.cs" />
<Compile Include="Data\Conventions\CascadeAllDeleteOrphanAttribute.cs" />
<Compile Include="Data\TransactionManager.cs" />
<Compile Include="Environment\IOrchardShellEvents.cs" />
<Compile Include="Environment\OrchardServices.cs" />
<Compile Include="Extensions\ExtensionDescriptor.cs" />
<Compile Include="Extensions\ExtensionEntry.cs" />
<Compile Include="Mvc\Filters\AdminFilter.cs" />
<Compile Include="IOrchardServices.cs" />
<Compile Include="Mvc\Html\FileRegistrationContext.cs" />
<Compile Include="Themes\ExtensionManagerExtensions.cs" />
<Compile Include="Extensions\Helpers\PathHelpers.cs" />