mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-09-19 18:27:55 +08:00
Starting point of standard content/routable controllers
Contents/Item/Display/{Id} to show published Contents/Item/Preview/{Id} to show latest (draft or published) Contents/Item/Preview/{Id}?Version= to particular numbered version {*Path} in Routable/ItemController.Display to show published where {Path}=RoutableRecord.Path --HG-- branch : dev
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
|
||||
namespace Orchard.Core.Common.Models {
|
||||
public class RoutableAspect : ContentPart<RoutableRecord> {
|
||||
public class RoutableAspect : ContentPart<RoutableRecord>, IRoutableAspect {
|
||||
public string ContentItemBasePath { get; set; }
|
||||
|
||||
public string Title {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Orchard.ContentManagement.Records;
|
||||
|
||||
namespace Orchard.Core.Common.Models {
|
||||
@@ -7,5 +8,8 @@ namespace Orchard.Core.Common.Models {
|
||||
public virtual string Title { get; set; }
|
||||
|
||||
public virtual string Slug { get; set; }
|
||||
|
||||
[StringLength(2048)]
|
||||
public virtual string Path { get; set; }
|
||||
}
|
||||
}
|
49
src/Orchard.Web/Core/Contents/Controllers/ItemController.cs
Normal file
49
src/Orchard.Web/Core/Contents/Controllers/ItemController.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Contents.ViewModels;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
|
||||
namespace Orchard.Core.Contents.Controllers {
|
||||
public class ItemController : Controller {
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public ItemController(IContentManager contentManager) {
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
public ActionResult Display(int id) {
|
||||
var contentItem = _contentManager.Get(id, VersionOptions.Published);
|
||||
|
||||
var model = new DisplayItemViewModel {
|
||||
Content = _contentManager.BuildDisplayModel(contentItem, "Detail")
|
||||
};
|
||||
PrepareDisplayViewModel(model.Content);
|
||||
return View("Display", model);
|
||||
}
|
||||
|
||||
public ActionResult Preview(int id, int? version) {
|
||||
var versionOptions = VersionOptions.Latest;
|
||||
if (version != null) {
|
||||
versionOptions = VersionOptions.Number((int)version);
|
||||
}
|
||||
|
||||
var contentItem = _contentManager.Get(id, versionOptions);
|
||||
|
||||
var model = new DisplayItemViewModel {
|
||||
Content = _contentManager.BuildDisplayModel(contentItem, "Detail")
|
||||
};
|
||||
PrepareDisplayViewModel(model.Content);
|
||||
return View("Preview", model);
|
||||
}
|
||||
|
||||
private static void PrepareDisplayViewModel(ContentItemViewModel itemViewModel) {
|
||||
if (string.IsNullOrEmpty(itemViewModel.TemplateName)) {
|
||||
itemViewModel.TemplateName = "Items/Contents.Item";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
|
||||
namespace Orchard.Core.Contents.Handlers {
|
||||
public class ContentsModuleHandler : ContentHandlerBase {
|
||||
public override void GetContentItemMetadata(GetContentItemMetadataContext context) {
|
||||
if (context.Metadata.EditorRouteValues == null) {
|
||||
context.Metadata.EditorRouteValues = new RouteValueDictionary {
|
||||
{"Area", "Contents"},
|
||||
{"Controller", "Admin"},
|
||||
{"Action", "Edit"},
|
||||
{"Id", context.ContentItem.Id}
|
||||
};
|
||||
}
|
||||
if (context.Metadata.DisplayRouteValues == null) {
|
||||
context.Metadata.DisplayRouteValues = new RouteValueDictionary {
|
||||
{"Area", "Contents"},
|
||||
{"Controller", "Item"},
|
||||
{"Action", "Display"},
|
||||
{"Id", context.ContentItem.Id}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,4 +5,7 @@ namespace Orchard.Core.Contents.ViewModels {
|
||||
public int Id { get; set; }
|
||||
public ContentItemViewModel Content { get; set; }
|
||||
}
|
||||
public class DisplayItemViewModel : BaseViewModel {
|
||||
public ContentItemViewModel Content { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
<%@ Control Language="C#" Inherits="Orchard.Mvc.ViewUserControl<ContentItemViewModel>" %>
|
||||
<%@ Import Namespace="Orchard.Mvc.ViewModels" %>
|
||||
<%@ Import Namespace="Orchard.ContentManagement.Aspects" %>
|
||||
<%@ Import Namespace="Orchard.ContentManagement" %>
|
||||
<%var routable = Model.Item.As<IRoutableAspect>();
|
||||
if (routable != null && !string.IsNullOrEmpty(routable.Title)) {%>
|
||||
<h1>
|
||||
<%:routable.Title%></h1>
|
||||
<%} %>
|
||||
<% Html.Zone("primary", ":manage :metadata");
|
||||
Html.ZonesAny(); %>
|
5
src/Orchard.Web/Core/Contents/Views/Item/Display.aspx
Normal file
5
src/Orchard.Web/Core/Contents/Views/Item/Display.aspx
Normal file
@@ -0,0 +1,5 @@
|
||||
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<Orchard.Core.Contents.ViewModels.DisplayItemViewModel>" %>
|
||||
|
||||
<div class="preview">
|
||||
<%=Html.DisplayForItem(m=>m.Content) %>
|
||||
</div>
|
3
src/Orchard.Web/Core/Contents/Views/Item/Preview.aspx
Normal file
3
src/Orchard.Web/Core/Contents/Views/Item/Preview.aspx
Normal file
@@ -0,0 +1,3 @@
|
||||
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<Orchard.Core.Contents.ViewModels.DisplayItemViewModel>" %>
|
||||
|
||||
<%=Html.DisplayForItem(m=>m.Content) %>
|
@@ -68,6 +68,13 @@
|
||||
<Compile Include="Common\Drivers\RoutableDriver.cs" />
|
||||
<Compile Include="Common\Controllers\RoutableController.cs" />
|
||||
<Compile Include="Common\Handlers\RoutableAspectHandler.cs" />
|
||||
<Compile Include="Contents\Controllers\ItemController.cs" />
|
||||
<Compile Include="Contents\Handlers\ContentsModuleHandler.cs" />
|
||||
<Compile Include="Routable\Controllers\ItemController.cs" />
|
||||
<Compile Include="Routable\Drivers\RoutableDriver.cs" />
|
||||
<Compile Include="Routable\Handlers\RoutableHandler.cs" />
|
||||
<Compile Include="Routable\IRoutablePathConstraint.cs" />
|
||||
<Compile Include="Routable\Models\IsRoutable.cs" />
|
||||
<Compile Include="Common\Permissions.cs" />
|
||||
<Compile Include="Common\Models\CommonVersionRecord.cs" />
|
||||
<Compile Include="Common\Routes.cs" />
|
||||
@@ -145,6 +152,10 @@
|
||||
<Compile Include="Navigation\ViewModels\MenuItemEntry.cs" />
|
||||
<Compile Include="Navigation\ViewModels\NavigationManagementViewModel.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Routable\Routes.cs" />
|
||||
<Compile Include="Routable\Services\RoutablePathConstraint.cs" />
|
||||
<Compile Include="Routable\Services\RoutablePathConstraintUpdator.cs" />
|
||||
<Compile Include="Routable\ViewModels\RoutableDisplayViewModel.cs" />
|
||||
<Compile Include="Scheduling\Models\ScheduledTaskRecord.cs" />
|
||||
<Compile Include="Scheduling\Services\PublishingTaskHandler.cs" />
|
||||
<Compile Include="Scheduling\Services\PublishingTaskManager.cs" />
|
||||
@@ -194,9 +205,14 @@
|
||||
<Content Include="Contents\Views\Admin\Edit.aspx" />
|
||||
<Content Include="Contents\Views\Admin\CreatableTypeList.aspx" />
|
||||
<Content Include="Contents\Views\Admin\Create.aspx" />
|
||||
<Content Include="Contents\Views\DisplayTemplates\Items\Contents.Item.ascx" />
|
||||
<Content Include="Contents\Views\EditorTemplates\Items\Contents.Item.ascx" />
|
||||
<Content Include="Contents\Views\Item\Preview.aspx" />
|
||||
<Content Include="Contents\Views\Item\Display.aspx" />
|
||||
<Content Include="Indexing\Module.txt" />
|
||||
<Content Include="Localization\Module.txt" />
|
||||
<Content Include="Routable\Module.txt" />
|
||||
<Content Include="Routable\Views\Item\Display.aspx" />
|
||||
<Content Include="Settings\Module.txt" />
|
||||
<Content Include="Settings\Views\Admin\Index.ascx" />
|
||||
<Content Include="Web.config" />
|
||||
@@ -249,6 +265,7 @@
|
||||
<None Include="App_Data\Localization\en-US\orchard.core.po" />
|
||||
<None Include="App_Data\Localization\fr-FR\orchard.core.po" />
|
||||
<Content Include="Contents\Views\Web.config" />
|
||||
<Content Include="Routable\Views\Web.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
|
||||
|
44
src/Orchard.Web/Core/Routable/Controllers/ItemController.cs
Normal file
44
src/Orchard.Web/Core/Routable/Controllers/ItemController.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.Core.Routable.Models;
|
||||
using Orchard.Core.Routable.ViewModels;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
|
||||
namespace Orchard.Core.Routable.Controllers {
|
||||
[ValidateInput(false)]
|
||||
public class ItemController : Controller {
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public ItemController(IContentManager contentManager) {
|
||||
_contentManager = contentManager;
|
||||
}
|
||||
|
||||
public ActionResult Display(string path) {
|
||||
var hits = _contentManager
|
||||
.Query<IsRoutable, RoutableRecord>(VersionOptions.Published)
|
||||
.Where(r => r.Path == path)
|
||||
.Slice(0, 2);
|
||||
if (hits.Count() == 0) {
|
||||
throw new ApplicationException("404 - should not have passed path constraint");
|
||||
}
|
||||
if (hits.Count() != 1) {
|
||||
throw new ApplicationException("Ambiguous content");
|
||||
}
|
||||
var model = new RoutableDisplayViewModel {
|
||||
Routable = _contentManager.BuildDisplayModel<IRoutableAspect>(hits.Single(), "Detail")
|
||||
};
|
||||
PrepareDisplayViewModel(model.Routable);
|
||||
return View("Display", model);
|
||||
}
|
||||
|
||||
private void PrepareDisplayViewModel(ContentItemViewModel<IRoutableAspect> itemViewModel) {
|
||||
if (string.IsNullOrEmpty(itemViewModel.TemplateName)) {
|
||||
itemViewModel.TemplateName = "Items/Contents.Item";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
60
src/Orchard.Web/Core/Routable/Drivers/RoutableDriver.cs
Normal file
60
src/Orchard.Web/Core/Routable/Drivers/RoutableDriver.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.Core.Common.ViewModels;
|
||||
using Orchard.Core.Common.Services;
|
||||
using Orchard.Core.Routable.Models;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Notify;
|
||||
|
||||
namespace Orchard.Core.Routable.Drivers {
|
||||
public class RoutableDriver : ContentPartDriver<IsRoutable> {
|
||||
protected override DriverResult Editor(IsRoutable part, IUpdateModel updater) {
|
||||
part.Record.Title = "Routable #" + part.ContentItem.Id;
|
||||
part.Record.Slug = "routable" + part.ContentItem.Id;
|
||||
part.Record.Path = "routable" + part.ContentItem.Id;
|
||||
return base.Editor(part, updater);
|
||||
}
|
||||
//private const string TemplateName = "Parts/Common.Routable";
|
||||
|
||||
//private readonly IOrchardServices _services;
|
||||
//private readonly IRoutableService _routableService;
|
||||
//public Localizer T { get; set; }
|
||||
|
||||
//protected override string Prefix {
|
||||
// get { return "Routable"; }
|
||||
//}
|
||||
|
||||
//public Routable(IOrchardServices services, IRoutableService routableService)
|
||||
//{
|
||||
// _services = services;
|
||||
// _routableService = routableService;
|
||||
|
||||
// T = NullLocalizer.Instance;
|
||||
//}
|
||||
|
||||
//protected override DriverResult Editor(RoutableAspect part) {
|
||||
// var model = new RoutableEditorViewModel { Prefix = Prefix, RoutableAspect = part };
|
||||
// return ContentPartTemplate(model, TemplateName, Prefix).Location("primary", "before.5");
|
||||
//}
|
||||
|
||||
//protected override DriverResult Editor(RoutableAspect part, IUpdateModel updater) {
|
||||
// var model = new RoutableEditorViewModel { Prefix = Prefix, RoutableAspect = part };
|
||||
// updater.TryUpdateModel(model, Prefix, null, null);
|
||||
|
||||
// if (!_routableService.IsSlugValid(part.Slug)){
|
||||
// updater.AddModelError("Routable.Slug", T("Please do not use any of the following characters in your slugs: \"/\", \":\", \"?\", \"#\", \"[\", \"]\", \"@\", \"!\", \"$\", \"&\", \"'\", \"(\", \")\", \"*\", \"+\", \",\", \";\", \"=\". No spaces are allowed (please use dashes or underscores instead).").ToString());
|
||||
// }
|
||||
|
||||
// string originalSlug = part.Slug;
|
||||
// if(!_routableService.ProcessSlug(part)) {
|
||||
// _services.Notifier.Warning(T("Slugs in conflict. \"{0}\" is already set for a previously created {2} so now it has the slug \"{1}\"",
|
||||
// originalSlug, part.Slug, part.ContentItem.ContentType));
|
||||
// }
|
||||
|
||||
// return ContentPartTemplate(model, TemplateName, Prefix).Location("primary", "before.5");
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
20
src/Orchard.Web/Core/Routable/Handlers/RoutableHandler.cs
Normal file
20
src/Orchard.Web/Core/Routable/Handlers/RoutableHandler.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System.Web.Routing;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Core.Routable.Models;
|
||||
|
||||
namespace Orchard.Core.Routable.Handlers {
|
||||
public class RoutableHandler : ContentHandlerBase {
|
||||
public override void GetContentItemMetadata(GetContentItemMetadataContext context) {
|
||||
var routable = context.ContentItem.As<IsRoutable>();
|
||||
if (routable != null) {
|
||||
context.Metadata.DisplayRouteValues = new RouteValueDictionary {
|
||||
{"Area", "Routable"},
|
||||
{"Controller", "Item"},
|
||||
{"Action", "Display"},
|
||||
{"Path", context.ContentItem.As<IsRoutable>().Record.Path}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
src/Orchard.Web/Core/Routable/IRoutablePathConstraint.cs
Normal file
11
src/Orchard.Web/Core/Routable/IRoutablePathConstraint.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace Orchard.Core.Routable {
|
||||
public interface IRoutablePathConstraint : IRouteConstraint, ISingletonDependency {
|
||||
void SetSlugs(IEnumerable<string> slugs);
|
||||
string FindSlug(string slug);
|
||||
void AddSlug(string slug);
|
||||
void RemoveSlug(string slug);
|
||||
}
|
||||
}
|
18
src/Orchard.Web/Core/Routable/Models/IsRoutable.cs
Normal file
18
src/Orchard.Web/Core/Routable/Models/IsRoutable.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Core.Common.Models;
|
||||
|
||||
namespace Orchard.Core.Routable.Models {
|
||||
public class IsRoutable : ContentPart<RoutableRecord>, IRoutableAspect {
|
||||
public string Title {
|
||||
get { return Record.Title; }
|
||||
set { Record.Title = value; }
|
||||
}
|
||||
|
||||
public string Slug {
|
||||
get { return Record.Slug; }
|
||||
set { Record.Slug = value; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
11
src/Orchard.Web/Core/Routable/Module.txt
Normal file
11
src/Orchard.Web/Core/Routable/Module.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
Name: Routable
|
||||
antiforgery: enabled
|
||||
author: The Orchard Team
|
||||
website: http://orchardproject.net
|
||||
version: 0.1
|
||||
orchardversion: 0.1.2010.0312
|
||||
description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas consectetur consequat risus, vel blandit arcu tincidunt eget. Nam rutrum nulla vestibulum dolor dapibus sagittis. Vivamus convallis faucibus accumsan. Suspendisse sapien enim, cursus at dignissim a, sollicitudin sit amet est. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Donec sed urna magna, in luctus nulla. Pellentesque erat ipsum, convallis sed molestie tempus, mattis vel leo metus.
|
||||
features:
|
||||
Routable:
|
||||
Description: Routable content part.
|
||||
Category: Core2
|
42
src/Orchard.Web/Core/Routable/Routes.cs
Normal file
42
src/Orchard.Web/Core/Routable/Routes.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Orchard.Mvc.Routes;
|
||||
|
||||
namespace Orchard.Core.Routable {
|
||||
public class Routes : IRouteProvider {
|
||||
private readonly IRoutablePathConstraint _routablePathConstraint;
|
||||
|
||||
public Routes(IRoutablePathConstraint routablePathConstraint) {
|
||||
_routablePathConstraint = routablePathConstraint;
|
||||
}
|
||||
|
||||
public void GetRoutes(ICollection<RouteDescriptor> routes) {
|
||||
foreach (var routeDescriptor in GetRoutes())
|
||||
routes.Add(routeDescriptor);
|
||||
}
|
||||
|
||||
public IEnumerable<RouteDescriptor> GetRoutes() {
|
||||
return new[] {
|
||||
new RouteDescriptor {
|
||||
Priority = 10,
|
||||
Route = new Route(
|
||||
"{*path}",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Routable"},
|
||||
{"controller", "Item"},
|
||||
{"action", "Display"}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"path", _routablePathConstraint}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"area", "Routable"}
|
||||
},
|
||||
new MvcRouteHandler())
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Routing;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Core.Routable.Services {
|
||||
[UsedImplicitly]
|
||||
public class RoutablePathConstraint : IRoutablePathConstraint {
|
||||
/// <summary>
|
||||
/// Singleton object, per Orchard Shell instance. We need to protect concurrent access to the dictionary.
|
||||
/// </summary>
|
||||
private readonly object _syncLock = new object();
|
||||
private IDictionary<string, string> _slugs = new Dictionary<string, string>();
|
||||
|
||||
public RoutablePathConstraint() {
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public void SetSlugs(IEnumerable<string> slugs) {
|
||||
// Make a copy to avoid performing potential lazy computation inside the lock
|
||||
var slugsArray = slugs.ToArray();
|
||||
|
||||
lock (_syncLock) {
|
||||
_slugs = slugsArray.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(value => value, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
public string FindSlug(string slug) {
|
||||
lock (_syncLock) {
|
||||
string actual;
|
||||
return _slugs.TryGetValue(slug, out actual) ? actual : slug;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSlug(string slug) {
|
||||
lock (_syncLock) {
|
||||
_slugs[slug] = slug;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveSlug(string slug) {
|
||||
lock (_syncLock) {
|
||||
_slugs.Remove(slug);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection) {
|
||||
if (routeDirection == RouteDirection.UrlGeneration)
|
||||
return true;
|
||||
|
||||
object value;
|
||||
if (values.TryGetValue(parameterName, out value)) {
|
||||
var parameterValue = Convert.ToString(value);
|
||||
|
||||
lock (_syncLock) {
|
||||
return _slugs.ContainsKey(parameterValue);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.Data;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Tasks;
|
||||
|
||||
namespace Orchard.Core.Routable.Services {
|
||||
[UsedImplicitly]
|
||||
public class RoutablePathConstraintUpdator : IOrchardShellEvents, IBackgroundTask {
|
||||
private readonly IRoutablePathConstraint _pageSlugConstraint;
|
||||
private readonly IRepository<RoutableRecord> _repository;
|
||||
|
||||
public RoutablePathConstraintUpdator(IRoutablePathConstraint pageSlugConstraint, IRepository<RoutableRecord> repository) {
|
||||
_pageSlugConstraint = pageSlugConstraint;
|
||||
_repository = repository;
|
||||
}
|
||||
|
||||
void IOrchardShellEvents.Activated() {
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void IOrchardShellEvents.Terminating() {
|
||||
}
|
||||
|
||||
void IBackgroundTask.Sweep() {
|
||||
Refresh();
|
||||
}
|
||||
|
||||
private void Refresh() {
|
||||
var slugs = _repository.Fetch(r => r.ContentItemVersionRecord.Published && r.Path != "" && r.Path != null).Select(r => r.Path);
|
||||
|
||||
_pageSlugConstraint.SetSlugs(slugs);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
using Orchard.ContentManagement.Aspects;
|
||||
using Orchard.Mvc.ViewModels;
|
||||
|
||||
namespace Orchard.Core.Routable.ViewModels {
|
||||
public class RoutableDisplayViewModel : BaseViewModel {
|
||||
public ContentItemViewModel<IRoutableAspect> Routable {get;set;}
|
||||
}
|
||||
}
|
3
src/Orchard.Web/Core/Routable/Views/Item/Display.aspx
Normal file
3
src/Orchard.Web/Core/Routable/Views/Item/Display.aspx
Normal file
@@ -0,0 +1,3 @@
|
||||
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<Orchard.Core.Routable.ViewModels.RoutableDisplayViewModel>" %>
|
||||
<% Html.AddTitleParts(Model.Routable.Item.Title); %>
|
||||
<%=Html.DisplayForItem(m=>m.Routable) %>
|
34
src/Orchard.Web/Core/Routable/Views/Web.config
Normal file
34
src/Orchard.Web/Core/Routable/Views/Web.config
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration>
|
||||
<system.web>
|
||||
<httpHandlers>
|
||||
<add path="*" verb="*"
|
||||
type="System.Web.HttpNotFoundHandler"/>
|
||||
</httpHandlers>
|
||||
|
||||
<!--
|
||||
Enabling request validation in view pages would cause validation to occur
|
||||
after the input has already been processed by the controller. By default
|
||||
MVC performs request validation before a controller processes the input.
|
||||
To change this behavior apply the ValidateInputAttribute to a
|
||||
controller or action.
|
||||
-->
|
||||
<pages
|
||||
validateRequest="false"
|
||||
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
|
||||
<controls>
|
||||
<add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
|
||||
</controls>
|
||||
</pages>
|
||||
</system.web>
|
||||
|
||||
<system.webServer>
|
||||
<validation validateIntegratedModeConfiguration="false"/>
|
||||
<handlers>
|
||||
<remove name="BlockViewHandler"/>
|
||||
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler"/>
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
</configuration>
|
6
src/Orchard/ContentManagement/Aspects/IRoutableAspect.cs
Normal file
6
src/Orchard/ContentManagement/Aspects/IRoutableAspect.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace Orchard.ContentManagement.Aspects {
|
||||
public interface IRoutableAspect : IContent {
|
||||
string Title { get; set; }
|
||||
string Slug { get; set; }
|
||||
}
|
||||
}
|
@@ -48,7 +48,7 @@ namespace Orchard.Mvc.ViewEngines {
|
||||
|
||||
themeViewEngines = _viewEngineProviders
|
||||
.Select(x => x.CreateThemeViewEngine(new CreateThemeViewEngineParams { VirtualPath = themeLocation }));
|
||||
Logger.Debug("Theme location:\r\n\t-{0}", themeLocation);
|
||||
//Logger.Debug("Theme location:\r\n\t-{0}", themeLocation);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Orchard.Mvc.ViewEngines {
|
||||
var moduleLocations = modules.Select(x => Path.Combine(x.Location, x.Name));
|
||||
var moduleViewEngines = _viewEngineProviders
|
||||
.Select(x => x.CreateModulesViewEngine(new CreateModulesViewEngineParams { VirtualPaths = moduleLocations }));
|
||||
Logger.Debug("Module locations:\r\n\t-{0}", string.Join("\r\n\t-", moduleLocations.ToArray()));
|
||||
//Logger.Debug("Module locations:\r\n\t-{0}", string.Join("\r\n\t-", moduleLocations.ToArray()));
|
||||
|
||||
var requestViewEngines = new ViewEngineCollection(
|
||||
themeViewEngines
|
||||
|
@@ -135,6 +135,7 @@
|
||||
<Compile Include="ContentManagement\Aspects\ICommonAspect.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="ContentManagement\Aspects\IRoutableAspect.cs" />
|
||||
<Compile Include="ContentManagement\ContentExtensions.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
Reference in New Issue
Block a user