Fix container routing

--HG--
branch : autoroute
This commit is contained in:
randompete
2011-12-07 23:32:23 +00:00
parent 7e6d8d81f1
commit 97c3356edf
6 changed files with 22 additions and 155 deletions

View File

@@ -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 }));
}
}
}

View File

@@ -13,56 +13,44 @@ using Orchard.Mvc;
using Orchard.Themes;
using Orchard.UI.Navigation;
using Orchard.Settings;
using Orchard.Localization;
namespace Orchard.Core.Containers.Controllers {
public class ItemController : Controller {
private readonly IContentManager _contentManager;
private readonly IContainersPathConstraint _containersPathConstraint;
private readonly ISiteService _siteService;
private readonly IFeedManager _feedManager;
public ItemController(
IContentManager contentManager,
IContainersPathConstraint containersPathConstraint,
IShapeFactory shapeFactory,
ISiteService siteService,
IFeedManager feedManager) {
_contentManager = contentManager;
_containersPathConstraint = containersPathConstraint;
_siteService = siteService;
_feedManager = feedManager;
Shape = shapeFactory;
T = NullLocalizer.Instance;
}
dynamic Shape { get; set; }
public Localizer T { get; set; }
[Themed]
public ActionResult Display(string path, PagerParameters pagerParameters) {
var matchedPath = _containersPathConstraint.FindPath(path);
if (string.IsNullOrEmpty(matchedPath)) {
throw new ApplicationException("404 - should not have passed path constraint");
}
public ActionResult Display(int id, PagerParameters pagerParameters) {
var hits = _contentManager
.Query<RoutePart, RoutePartRecord>(VersionOptions.Published)
.Where(r => r.Path == matchedPath)
.Slice(0, 2);
var container = _contentManager.Get(id).As<ContainerPart>();
if (container==null)
return HttpNotFound(T("Container not found").Text);
if (hits.Count() == 0) {
throw new ApplicationException("404 - should not have passed path constraint");
}
if (hits.Count() != 1) {
throw new ApplicationException("Ambiguous content");
}
var container = _contentManager.Get(hits.Single().Id);
container.As<ContainerPart>().PagerParameters = pagerParameters;
// TODO: (PH) Find a way to apply PagerParameters via a driver so we can lose this controller
container.PagerParameters = pagerParameters;
var model = _contentManager.BuildDisplay(container, "Detail");
return new ShapeResult(this, model);
}
}
}

View File

@@ -17,6 +17,7 @@ using System.Web.Routing;
using Orchard.Settings;
using Orchard.Core.Feeds;
using Orchard.UI.Navigation;
using Orchard.ContentManagement.Aspects;
namespace Orchard.Core.Containers.Drivers {
public class ContainerPartDriver : ContentPartDriver<ContainerPart> {
@@ -60,8 +61,9 @@ namespace Orchard.Core.Containers.Drivers {
var descendingOrder = part.OrderByDirection == (int)OrderByDirection.Descending;
query = query.OrderBy(part.OrderByProperty, descendingOrder);
_feedManager.Register(container.As<RoutePart>().Title, "rss", new RouteValueDictionary { { "containerid", container.Id } });
var metadata = container.ContentManager.GetItemMetadata(container);
if (metadata!=null)
_feedManager.Register(metadata.DisplayText, "rss", new RouteValueDictionary { { "containerid", container.Id } });
var pager = new Pager(_siteService.GetSiteSettings(), part.PagerParameters);
pager.PageSize = part.PagerParameters.PageSize != null && part.Paginated

View File

@@ -9,6 +9,7 @@ using Orchard.Core.Common.Models;
using Orchard.Data;
using Orchard.Core.Containers.Extensions;
using Orchard.ContentManagement;
using System.Web.Routing;
namespace Orchard.Core.Containers.Handlers {
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.OrderByDirection = (int)OrderByDirection.Descending;
});
OnGetContentItemMetadata<ContainerPart>((context, part) => {
context.Metadata.DisplayRouteValues = new RouteValueDictionary {
{"Area", "Containers"},
{"Controller", "Item"},
{"Action", "Display"},
{"id", context.ContentItem.Id}
};});
}
}
}

View File

@@ -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())
}
};
}
}
}

View File

@@ -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.");
}
}
}
}