Initial check in of some code that shows a list of blogs, a blog details page and can create a blog.

--HG--
extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4041601
This commit is contained in:
ErikPorter
2009-11-20 23:31:49 +00:00
parent 30800e7a02
commit 9ff20d7945
21 changed files with 318 additions and 20 deletions

View File

@@ -1,12 +1,29 @@
using System.Web.Mvc;
using Orchard.Mvc.ViewModels;
using Orchard.Blogs.Extensions;
using Orchard.Blogs.Models;
using Orchard.Blogs.Services;
using Orchard.Blogs.ViewModels;
namespace Orchard.Blogs.Controllers
{
public class AdminController : Controller
{
public ActionResult Index() {
return View(new AdminViewModel());
namespace Orchard.Blogs.Controllers {
public class AdminController : Controller {
private readonly IBlogService _blogService;
public AdminController(IBlogService blogService) {
_blogService = blogService;
}
public ActionResult Create() {
return View(new CreateBlogViewModel());
}
[HttpPost]
public ActionResult Create(CreateBlogViewModel model) {
if (!ModelState.IsValid)
return View(model);
Blog blog = _blogService.CreateBlog(model.ToCreateBlogParams());
return RedirectToAction("edit", new { blog.Record.Id });
}
}
}

View File

@@ -0,0 +1,28 @@
using System.Web.Mvc;
using Orchard.Blogs.Models;
using Orchard.Blogs.Services;
using Orchard.Mvc.Results;
namespace Orchard.Blogs.Controllers {
public class BlogController : Controller {
private readonly IBlogService _blogService;
public BlogController(IBlogService blogService) {
_blogService = blogService;
}
public ActionResult List() {
return View(_blogService.Get());
}
//TODO: (erikpo) Should think about moving the slug parameter and get call and null check up into a model binder or action filter
public ActionResult Item(string slug) {
Blog blog = _blogService.Get(slug);
if (blog == null)
return new NotFoundResult();
return View(blog);
}
}
}

View File

@@ -0,0 +1,10 @@
using Orchard.Blogs.Services;
using Orchard.Blogs.ViewModels;
namespace Orchard.Blogs.Extensions {
public static class BlogCreateViewModelExtensions {
public static CreateBlogParams ToCreateBlogParams(this CreateBlogViewModel viewModel) {
return new CreateBlogParams() {Name = viewModel.Name, Slug = viewModel.Slug, Enabled = viewModel.Enabled};
}
}
}

View File

@@ -0,0 +1,9 @@
using Orchard.Models;
namespace Orchard.Blogs.Models {
public class Blog : ContentPartForRecord<BlogRecord> {
public string Name { get { return Record.Name; } }
public string Slug { get { return Record.Slug; } }
public bool Enabled { get { return Record.Enabled; } }
}
}

View File

@@ -0,0 +1,11 @@
using Orchard.Data;
using Orchard.Models.Driver;
namespace Orchard.Blogs.Models {
public class BlogHandler : ContentHandler {
public BlogHandler(IRepository<BlogRecord> repository) {
Filters.Add(new ActivatingFilter<Blog>("blog"));
Filters.Add(new StorageFilterForRecord<BlogRecord>(repository));
}
}
}

View File

@@ -0,0 +1,7 @@
using Orchard.Models;
namespace Orchard.Blogs.Models {
public class BlogPost : ContentPartForRecord<BlogPostRecord> {
}
}

View File

@@ -0,0 +1,11 @@
using Orchard.Data;
using Orchard.Models.Driver;
namespace Orchard.Blogs.Models {
public class BlogPostHandler : ContentHandler {
public BlogPostHandler(IRepository<BlogPostRecord> repository) {
Filters.Add(new ActivatingFilter<BlogPost>("blogpost"));
Filters.Add(new StorageFilterForRecord<BlogPostRecord>(repository));
}
}
}

View File

@@ -0,0 +1,8 @@
using Orchard.Models.Records;
namespace Orchard.Blogs.Models {
public class BlogPostRecord : ContentPartRecord {
public virtual BlogRecord Blog { get; set; }
public virtual string Slug { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
using Orchard.Models.Records;
namespace Orchard.Blogs.Models {
public class BlogRecord : ContentPartRecord {
public virtual IEnumerable<BlogPostRecord> Posts { get; set; }
public virtual string Name { get; set; }
public virtual string Slug { get; set; }
public virtual bool Enabled { get; set; }
}
}

View File

@@ -61,12 +61,28 @@
<Reference Include="System.Web.Mobile" />
</ItemGroup>
<ItemGroup>
<Compile Include="Extensions\BlogCreateViewModelExtensions.cs" />
<Compile Include="Services\BlogService.cs" />
<Compile Include="Controllers\AdminController.cs" />
<Compile Include="Controllers\BlogController.cs" />
<Compile Include="Models\Blog.cs" />
<Compile Include="Models\BlogHandler.cs" />
<Compile Include="Models\BlogPost.cs" />
<Compile Include="Models\BlogPostHandler.cs" />
<Compile Include="Models\BlogPostRecord.cs" />
<Compile Include="Models\BlogRecord.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Routes.cs" />
<Compile Include="Services\CreateBlogParams.cs" />
<Compile Include="Services\IBlogService.cs" />
<Compile Include="ViewModels\CreateBlogViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Package.txt" />
<Content Include="Views\Admin\Create.aspx" />
<Content Include="Views\Admin\Index.aspx" />
<Content Include="Views\Blog\Item.aspx" />
<Content Include="Views\Blog\List.aspx" />
<Content Include="Web.config" />
<Content Include="Views\Web.config" />
</ItemGroup>
@@ -76,9 +92,6 @@
<Name>Orchard</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -99,8 +112,9 @@
<IISUrl>
</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>True</UseCustomServer>
<CustomServerUrl>http://orchard.codeplex.com</CustomServerUrl>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Routing;
using Orchard.Mvc.Routes;
namespace Orchard.Blogs {
//public class Routes : IRouteProvider {
// public void GetRoutes(ICollection<RouteDescriptor> routes) {
// foreach (var routeDescriptor in GetRoutes())
// routes.Add(routeDescriptor);
// }
// public IEnumerable<RouteDescriptor> GetRoutes() {
// return new[] {
// new RouteDescriptor {
// Route = new Route(
// "{*slug}",
// new RouteValueDictionary {
// {"area", "Orchard.CmsPages"},
// {"controller", "templates"},
// {"action", "show"}
// },
// new RouteValueDictionary {
// {"slug", ""}
// },
// new RouteValueDictionary {
// {"area", "Orchard.CmsPages"}
// },
// new MvcRouteHandler())
// }
// };
// }
//}
}

View File

@@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Linq;
using Orchard.Blogs.Models;
using Orchard.Data;
using Orchard.Models;
namespace Orchard.Blogs.Services {
public class BlogService : IBlogService {
private readonly IContentManager _contentManager;
private readonly IRepository<BlogRecord> _repository;
public BlogService(IContentManager contentManager, IRepository<BlogRecord> blogPostRepository) {
_contentManager = contentManager;
_repository = blogPostRepository;
}
public Blog Get(string slug) {
BlogRecord record = _repository.Get(br => br.Slug == slug);
ContentItem item = _contentManager.Get(record.Id);
return item != null ? item.As<Blog>() : null;
}
public IEnumerable<Blog> Get() {
IEnumerable<BlogRecord> blogs =_repository.Fetch(br => br.Enabled, bpr => bpr.Asc(bpr2 => bpr2.Name));
return blogs.Select(br => _contentManager.Get(br.Id).As<Blog>());
}
public Blog CreateBlog(CreateBlogParams parameters) {
BlogRecord record = new BlogRecord()
{Name = parameters.Name, Slug = parameters.Slug, Enabled = parameters.Enabled};
//TODO: (erikpo) Need an extension method or something for this default behavior
ContentItem contentItem = _contentManager.New("blog");
contentItem.As<Blog>().Record = record;
_contentManager.Create(contentItem);
return contentItem.As<Blog>();
}
}
}

View File

@@ -0,0 +1,7 @@
namespace Orchard.Blogs.Services {
public class CreateBlogParams {
public string Name { get; set; }
public string Slug { get; set; }
public bool Enabled { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
using Orchard.Blogs.Models;
namespace Orchard.Blogs.Services {
public interface IBlogService : IDependency {
Blog Get(string slug);
IEnumerable<Blog> Get();
Blog CreateBlog(CreateBlogParams parameters);
}
}

View File

@@ -0,0 +1,16 @@
using System.ComponentModel.DataAnnotations;
using Orchard.Mvc.ViewModels;
namespace Orchard.Blogs.ViewModels {
public class CreateBlogViewModel : AdminViewModel {
[Required]
public string Name { get; set; }
//TODO: (erikpo) Need a data type for slug
[Required]
public string Slug { get; set; }
[Required]
public bool Enabled { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Orchard.Blogs.ViewModels.CreateBlogViewModel>" %>
<%@ Import Namespace="Orchard.Security" %>
<%@ Import Namespace="Orchard.Mvc.Html" %>
<% Html.Include("Header"); %>
<div class="yui-u">
<h2 class="separator">
Add a new Blog</h2>
</div>
<div class="yui-u">
<%using (Html.BeginForm()) { %>
<ol>
<%= Html.ValidationSummary() %>
<%= Html.EditorForModel() %>
<li class="clearLayout">
<input class="button" type="submit" value="Create" />
<%=Html.ActionLink("Cancel", "Index", new{}, new{@class="button"}) %></li>
</ol>
<%}/*EndForm*/%>
</div>
<% Html.Include("Footer"); %>

View File

@@ -0,0 +1,10 @@
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Blog>" %>
<%@ Import Namespace="Orchard.Blogs.Models"%>
<%@ Import Namespace="Orchard.Mvc.Html"%>
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
<% Html.Include("Header"); %>
<div class="yui-g">
<h2>Blog</h2>
<div><%=Html.Encode(Model.Slug) %></div>
</div>
<% Html.Include("Footer"); %>

View File

@@ -0,0 +1,17 @@
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Blog>>" %>
<%@ Import Namespace="Orchard.Blogs.Models"%>
<%@ Import Namespace="Orchard.Mvc.Html"%>
<%@ Import Namespace="Orchard.Mvc.ViewModels"%>
<% Html.Include("Header"); %>
<div class="yui-g">
<h2>Blogs</h2><%
//TODO: (erikpo) Replace this with an Html extension method of some sort (ListForModel?)
if (Model.Count() > 0) { %>
<ul><%
foreach (Blog blog in Model) { %>
<li><a href="<%=Url.Action("Item", "Blog", new {slug = blog.Slug}) %>"><%=Html.Encode(blog.Name) %></a></li><%
} %>
</ul><%
} %>
</div>
<% Html.Include("Footer"); %>

View File

@@ -1,12 +1,9 @@
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<div id="menucontainer">
<ul id="menu">
<li>
<%= Html.ActionLink("Home", "Index", "Home", new{Area=""}, new{ })%></li>
<li>
<%= Html.ActionLink("About", "About", "Home", new { Area = "" }, new{})%></li>
<li>
<%= Html.ActionLink("Admin", "Index", new{Area="Orchard.Media", Controller="Admin"})%></li>
<li><%= Html.ActionLink("Home", "Index", "Home", new {Area = ""}, new {})%></li>
<li><%= Html.ActionLink("Blogs", "List", new {Area="Orchard.Blogs", Controller = "Blog"})%>
<li><%= Html.ActionLink("About", "About", "Home", new {Area = ""}, new {})%></li>
<li><%= Html.ActionLink("Admin", "Index", new {Area = "Orchard.Media", Controller = "Admin"})%></li>
</ul>
</div>

View File

@@ -0,0 +1,17 @@
using System.Web.Mvc;
namespace Orchard.Mvc.Results {
public class NotFoundResult : ViewResult {
public override void ExecuteResult(ControllerContext context) {
ViewName = "NotFound";
ViewData = context.Controller.ViewData;
TempData = context.Controller.TempData;
base.ExecuteResult(context);
context.HttpContext.Response.StatusDescription = "File Not Found";
context.HttpContext.Response.StatusCode = 404;
}
}
}

View File

@@ -107,7 +107,7 @@
<Compile Include="Data\Repository.cs" />
<Compile Include="Environment\DefaultCompositionStrategy.cs" />
<Compile Include="Environment\DefaultOrchardHost.cs" />
<Compile Include="Mvc\MvcModule.cs" />
<Compile Include="Mvc\Results\MvcModule.cs" />
<Compile Include="Mvc\OrchardControllerFactory.cs" />
<Compile Include="Environment\HostContext.cs" />
<Compile Include="Environment\IOrchardHost.cs" />
@@ -171,6 +171,7 @@
<Compile Include="Mvc\ModelBinders\IModelBinderPublisher.cs" />
<Compile Include="Mvc\ModelBinders\KeyedListModelBinder.cs" />
<Compile Include="Mvc\ModelBinders\ModelBinderDescriptor.cs" />
<Compile Include="Mvc\NotFoundResult.cs" />
<Compile Include="Mvc\OrchardControllerIdentificationStrategy.cs" />
<Compile Include="Mvc\Routes\RouteExtensions.cs" />
<Compile Include="Mvc\ViewModels\AdminViewModel.cs" />