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:
Louis DeJardin
2010-06-08 10:50:08 -07:00
parent 3c4a2097cf
commit abf8357f1b
24 changed files with 490 additions and 6 deletions

View File

@@ -1,7 +1,8 @@
using Orchard.ContentManagement; using Orchard.ContentManagement;
using Orchard.ContentManagement.Aspects;
namespace Orchard.Core.Common.Models { namespace Orchard.Core.Common.Models {
public class RoutableAspect : ContentPart<RoutableRecord> { public class RoutableAspect : ContentPart<RoutableRecord>, IRoutableAspect {
public string ContentItemBasePath { get; set; } public string ContentItemBasePath { get; set; }
public string Title { public string Title {
@@ -14,4 +15,4 @@ namespace Orchard.Core.Common.Models {
set { Record.Slug = value; } set { Record.Slug = value; }
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations; using System;
using System.ComponentModel.DataAnnotations;
using Orchard.ContentManagement.Records; using Orchard.ContentManagement.Records;
namespace Orchard.Core.Common.Models { namespace Orchard.Core.Common.Models {
@@ -7,5 +8,8 @@ namespace Orchard.Core.Common.Models {
public virtual string Title { get; set; } public virtual string Title { get; set; }
public virtual string Slug { get; set; } public virtual string Slug { get; set; }
[StringLength(2048)]
public virtual string Path { get; set; }
} }
} }

View 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";
}
}
}
}

View File

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

View File

@@ -5,4 +5,7 @@ namespace Orchard.Core.Contents.ViewModels {
public int Id { get; set; } public int Id { get; set; }
public ContentItemViewModel Content { get; set; } public ContentItemViewModel Content { get; set; }
} }
public class DisplayItemViewModel : BaseViewModel {
public ContentItemViewModel Content { get; set; }
}
} }

View File

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

View 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>

View File

@@ -0,0 +1,3 @@
<%@ Page Language="C#" Inherits="Orchard.Mvc.ViewPage<Orchard.Core.Contents.ViewModels.DisplayItemViewModel>" %>
<%=Html.DisplayForItem(m=>m.Content) %>

View File

@@ -68,6 +68,13 @@
<Compile Include="Common\Drivers\RoutableDriver.cs" /> <Compile Include="Common\Drivers\RoutableDriver.cs" />
<Compile Include="Common\Controllers\RoutableController.cs" /> <Compile Include="Common\Controllers\RoutableController.cs" />
<Compile Include="Common\Handlers\RoutableAspectHandler.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\Permissions.cs" />
<Compile Include="Common\Models\CommonVersionRecord.cs" /> <Compile Include="Common\Models\CommonVersionRecord.cs" />
<Compile Include="Common\Routes.cs" /> <Compile Include="Common\Routes.cs" />
@@ -145,6 +152,10 @@
<Compile Include="Navigation\ViewModels\MenuItemEntry.cs" /> <Compile Include="Navigation\ViewModels\MenuItemEntry.cs" />
<Compile Include="Navigation\ViewModels\NavigationManagementViewModel.cs" /> <Compile Include="Navigation\ViewModels\NavigationManagementViewModel.cs" />
<Compile Include="Properties\AssemblyInfo.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\Models\ScheduledTaskRecord.cs" />
<Compile Include="Scheduling\Services\PublishingTaskHandler.cs" /> <Compile Include="Scheduling\Services\PublishingTaskHandler.cs" />
<Compile Include="Scheduling\Services\PublishingTaskManager.cs" /> <Compile Include="Scheduling\Services\PublishingTaskManager.cs" />
@@ -194,9 +205,14 @@
<Content Include="Contents\Views\Admin\Edit.aspx" /> <Content Include="Contents\Views\Admin\Edit.aspx" />
<Content Include="Contents\Views\Admin\CreatableTypeList.aspx" /> <Content Include="Contents\Views\Admin\CreatableTypeList.aspx" />
<Content Include="Contents\Views\Admin\Create.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\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="Indexing\Module.txt" />
<Content Include="Localization\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\Module.txt" />
<Content Include="Settings\Views\Admin\Index.ascx" /> <Content Include="Settings\Views\Admin\Index.ascx" />
<Content Include="Web.config" /> <Content Include="Web.config" />
@@ -249,6 +265,7 @@
<None Include="App_Data\Localization\en-US\orchard.core.po" /> <None Include="App_Data\Localization\en-US\orchard.core.po" />
<None Include="App_Data\Localization\fr-FR\orchard.core.po" /> <None Include="App_Data\Localization\fr-FR\orchard.core.po" />
<Content Include="Contents\Views\Web.config" /> <Content Include="Contents\Views\Web.config" />
<Content Include="Routable\Views\Web.config" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /> <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

View 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";
}
}
}
}

View 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");
//}
}
}

View 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}
};
}
}
}
}

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

View 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; }
}
}
}

View 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

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

View File

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

View File

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

View File

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

View 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) %>

View 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>

View File

@@ -0,0 +1,6 @@
namespace Orchard.ContentManagement.Aspects {
public interface IRoutableAspect : IContent {
string Title { get; set; }
string Slug { get; set; }
}
}

View File

@@ -48,7 +48,7 @@ namespace Orchard.Mvc.ViewEngines {
themeViewEngines = _viewEngineProviders themeViewEngines = _viewEngineProviders
.Select(x => x.CreateThemeViewEngine(new CreateThemeViewEngineParams { VirtualPath = themeLocation })); .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 moduleLocations = modules.Select(x => Path.Combine(x.Location, x.Name));
var moduleViewEngines = _viewEngineProviders var moduleViewEngines = _viewEngineProviders
.Select(x => x.CreateModulesViewEngine(new CreateModulesViewEngineParams { VirtualPaths = moduleLocations })); .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( var requestViewEngines = new ViewEngineCollection(
themeViewEngines themeViewEngines

View File

@@ -135,6 +135,7 @@
<Compile Include="ContentManagement\Aspects\ICommonAspect.cs"> <Compile Include="ContentManagement\Aspects\ICommonAspect.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="ContentManagement\Aspects\IRoutableAspect.cs" />
<Compile Include="ContentManagement\ContentExtensions.cs"> <Compile Include="ContentManagement\ContentExtensions.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>