mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-20 19:03:25 +08:00
Fix container routing
--HG-- branch : autoroute
This commit is contained in:
@@ -1,45 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Web;
|
|
||||||
using System.Web.Routing;
|
|
||||||
|
|
||||||
namespace Orchard.Core.Containers {
|
|
||||||
public interface IContainersPathConstraint : IRouteConstraint, ISingletonDependency {
|
|
||||||
void SetPaths(IEnumerable<string> paths);
|
|
||||||
string FindPath(string path);
|
|
||||||
void AddPath(string path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ContainersPathConstraint : IContainersPathConstraint {
|
|
||||||
private IDictionary<string, string> _paths = new Dictionary<string, string>();
|
|
||||||
|
|
||||||
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);
|
|
||||||
return _paths.ContainsKey(parameterValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetPaths(IEnumerable<string> paths) {
|
|
||||||
// Note: this does not need to be synchronized as long as the dictionary itself is treated as immutable.
|
|
||||||
// do not add or remove to the dictionary instance once created. recreate and reassign instead.
|
|
||||||
_paths = paths.Distinct().ToDictionary(path => path, StringComparer.OrdinalIgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string FindPath(string path) {
|
|
||||||
string actual;
|
|
||||||
return _paths.TryGetValue(path, out actual) ? actual : path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddPath(string path) {
|
|
||||||
SetPaths(_paths.Keys.Concat(new[] { path }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -13,56 +13,44 @@ using Orchard.Mvc;
|
|||||||
using Orchard.Themes;
|
using Orchard.Themes;
|
||||||
using Orchard.UI.Navigation;
|
using Orchard.UI.Navigation;
|
||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
|
using Orchard.Localization;
|
||||||
|
|
||||||
namespace Orchard.Core.Containers.Controllers {
|
namespace Orchard.Core.Containers.Controllers {
|
||||||
|
|
||||||
public class ItemController : Controller {
|
public class ItemController : Controller {
|
||||||
private readonly IContentManager _contentManager;
|
private readonly IContentManager _contentManager;
|
||||||
private readonly IContainersPathConstraint _containersPathConstraint;
|
|
||||||
private readonly ISiteService _siteService;
|
private readonly ISiteService _siteService;
|
||||||
private readonly IFeedManager _feedManager;
|
private readonly IFeedManager _feedManager;
|
||||||
|
|
||||||
public ItemController(
|
public ItemController(
|
||||||
IContentManager contentManager,
|
IContentManager contentManager,
|
||||||
IContainersPathConstraint containersPathConstraint,
|
|
||||||
IShapeFactory shapeFactory,
|
IShapeFactory shapeFactory,
|
||||||
ISiteService siteService,
|
ISiteService siteService,
|
||||||
IFeedManager feedManager) {
|
IFeedManager feedManager) {
|
||||||
|
|
||||||
_contentManager = contentManager;
|
_contentManager = contentManager;
|
||||||
_containersPathConstraint = containersPathConstraint;
|
|
||||||
_siteService = siteService;
|
_siteService = siteService;
|
||||||
_feedManager = feedManager;
|
_feedManager = feedManager;
|
||||||
Shape = shapeFactory;
|
Shape = shapeFactory;
|
||||||
|
T = NullLocalizer.Instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic Shape { get; set; }
|
dynamic Shape { get; set; }
|
||||||
|
|
||||||
|
public Localizer T { get; set; }
|
||||||
[Themed]
|
[Themed]
|
||||||
public ActionResult Display(string path, PagerParameters pagerParameters) {
|
public ActionResult Display(int id, PagerParameters pagerParameters) {
|
||||||
var matchedPath = _containersPathConstraint.FindPath(path);
|
|
||||||
if (string.IsNullOrEmpty(matchedPath)) {
|
|
||||||
throw new ApplicationException("404 - should not have passed path constraint");
|
|
||||||
}
|
|
||||||
|
|
||||||
var hits = _contentManager
|
var container = _contentManager.Get(id).As<ContainerPart>();
|
||||||
.Query<RoutePart, RoutePartRecord>(VersionOptions.Published)
|
if (container==null)
|
||||||
.Where(r => r.Path == matchedPath)
|
return HttpNotFound(T("Container not found").Text);
|
||||||
.Slice(0, 2);
|
|
||||||
|
|
||||||
if (hits.Count() == 0) {
|
// TODO: (PH) Find a way to apply PagerParameters via a driver so we can lose this controller
|
||||||
throw new ApplicationException("404 - should not have passed path constraint");
|
container.PagerParameters = pagerParameters;
|
||||||
}
|
|
||||||
|
|
||||||
if (hits.Count() != 1) {
|
|
||||||
throw new ApplicationException("Ambiguous content");
|
|
||||||
}
|
|
||||||
|
|
||||||
var container = _contentManager.Get(hits.Single().Id);
|
|
||||||
container.As<ContainerPart>().PagerParameters = pagerParameters;
|
|
||||||
var model = _contentManager.BuildDisplay(container, "Detail");
|
var model = _contentManager.BuildDisplay(container, "Detail");
|
||||||
|
|
||||||
return new ShapeResult(this, model);
|
return new ShapeResult(this, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -17,6 +17,7 @@ using System.Web.Routing;
|
|||||||
using Orchard.Settings;
|
using Orchard.Settings;
|
||||||
using Orchard.Core.Feeds;
|
using Orchard.Core.Feeds;
|
||||||
using Orchard.UI.Navigation;
|
using Orchard.UI.Navigation;
|
||||||
|
using Orchard.ContentManagement.Aspects;
|
||||||
|
|
||||||
namespace Orchard.Core.Containers.Drivers {
|
namespace Orchard.Core.Containers.Drivers {
|
||||||
public class ContainerPartDriver : ContentPartDriver<ContainerPart> {
|
public class ContainerPartDriver : ContentPartDriver<ContainerPart> {
|
||||||
@@ -60,8 +61,9 @@ namespace Orchard.Core.Containers.Drivers {
|
|||||||
|
|
||||||
var descendingOrder = part.OrderByDirection == (int)OrderByDirection.Descending;
|
var descendingOrder = part.OrderByDirection == (int)OrderByDirection.Descending;
|
||||||
query = query.OrderBy(part.OrderByProperty, descendingOrder);
|
query = query.OrderBy(part.OrderByProperty, descendingOrder);
|
||||||
|
var metadata = container.ContentManager.GetItemMetadata(container);
|
||||||
_feedManager.Register(container.As<RoutePart>().Title, "rss", new RouteValueDictionary { { "containerid", container.Id } });
|
if (metadata!=null)
|
||||||
|
_feedManager.Register(metadata.DisplayText, "rss", new RouteValueDictionary { { "containerid", container.Id } });
|
||||||
|
|
||||||
var pager = new Pager(_siteService.GetSiteSettings(), part.PagerParameters);
|
var pager = new Pager(_siteService.GetSiteSettings(), part.PagerParameters);
|
||||||
pager.PageSize = part.PagerParameters.PageSize != null && part.Paginated
|
pager.PageSize = part.PagerParameters.PageSize != null && part.Paginated
|
||||||
|
@@ -9,6 +9,7 @@ using Orchard.Core.Common.Models;
|
|||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
using Orchard.Core.Containers.Extensions;
|
using Orchard.Core.Containers.Extensions;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
|
using System.Web.Routing;
|
||||||
|
|
||||||
namespace Orchard.Core.Containers.Handlers {
|
namespace Orchard.Core.Containers.Handlers {
|
||||||
public class ContainerPartHandler : ContentHandler {
|
public class ContainerPartHandler : ContentHandler {
|
||||||
@@ -25,6 +26,13 @@ namespace Orchard.Core.Containers.Handlers {
|
|||||||
part.Record.OrderByProperty = part.Is<CommonPart>() ? "CommonPart.CreatedUtc" : string.Empty;
|
part.Record.OrderByProperty = part.Is<CommonPart>() ? "CommonPart.CreatedUtc" : string.Empty;
|
||||||
part.Record.OrderByDirection = (int)OrderByDirection.Descending;
|
part.Record.OrderByDirection = (int)OrderByDirection.Descending;
|
||||||
});
|
});
|
||||||
|
OnGetContentItemMetadata<ContainerPart>((context, part) => {
|
||||||
|
context.Metadata.DisplayRouteValues = new RouteValueDictionary {
|
||||||
|
{"Area", "Containers"},
|
||||||
|
{"Controller", "Item"},
|
||||||
|
{"Action", "Display"},
|
||||||
|
{"id", context.ContentItem.Id}
|
||||||
|
};});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,42 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Web.Mvc;
|
|
||||||
using System.Web.Routing;
|
|
||||||
using Orchard.Mvc.Routes;
|
|
||||||
|
|
||||||
namespace Orchard.Core.Containers {
|
|
||||||
public class Routes : IRouteProvider {
|
|
||||||
private readonly IContainersPathConstraint _containersPathConstraint;
|
|
||||||
|
|
||||||
public Routes(IContainersPathConstraint containersPathConstraint) {
|
|
||||||
_containersPathConstraint = containersPathConstraint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetRoutes(ICollection<RouteDescriptor> routes) {
|
|
||||||
foreach (var routeDescriptor in GetRoutes())
|
|
||||||
routes.Add(routeDescriptor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<RouteDescriptor> GetRoutes() {
|
|
||||||
return new[] {
|
|
||||||
new RouteDescriptor {
|
|
||||||
Priority = 15,
|
|
||||||
Route = new Route(
|
|
||||||
"{*path}",
|
|
||||||
new RouteValueDictionary {
|
|
||||||
{"area", "Containers"},
|
|
||||||
{"controller", "Item"},
|
|
||||||
{"action", "Display"}
|
|
||||||
},
|
|
||||||
new RouteValueDictionary {
|
|
||||||
{"path", _containersPathConstraint}
|
|
||||||
},
|
|
||||||
new RouteValueDictionary {
|
|
||||||
{"area", "Containers"}
|
|
||||||
},
|
|
||||||
new MvcRouteHandler())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,44 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using Orchard.ContentManagement;
|
|
||||||
using Orchard.Core.Containers.Models;
|
|
||||||
using Orchard.Core.Routable.Models;
|
|
||||||
using Orchard.Environment;
|
|
||||||
using Orchard.Logging;
|
|
||||||
using Orchard.Tasks;
|
|
||||||
|
|
||||||
namespace Orchard.Core.Containers.Services {
|
|
||||||
public class ContainersPathConstraintUpdater : IOrchardShellEvents, IBackgroundTask {
|
|
||||||
private readonly IContainersPathConstraint _containersPathConstraint;
|
|
||||||
private readonly IContentManager _contentManager;
|
|
||||||
|
|
||||||
public ContainersPathConstraintUpdater(IContainersPathConstraint containersPathConstraint, IContentManager contentManager) {
|
|
||||||
_containersPathConstraint = containersPathConstraint;
|
|
||||||
_contentManager = contentManager;
|
|
||||||
Logger = NullLogger.Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ILogger Logger { get; set; }
|
|
||||||
|
|
||||||
void IOrchardShellEvents.Activated() {
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
void IOrchardShellEvents.Terminating() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void IBackgroundTask.Sweep() {
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Refresh() {
|
|
||||||
try {
|
|
||||||
var routeParts = _contentManager.Query<RoutePart, RoutePartRecord>().Join<ContainerPartRecord>().List();
|
|
||||||
_containersPathConstraint.SetPaths(routeParts.Select(x => x.Path));
|
|
||||||
}
|
|
||||||
catch (Exception ex) {
|
|
||||||
Logger.Error(ex, "Error while setting path constraints for containers.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user