在Umbraco ASP.NET/IApplicationEventHander与ApplicationEventHandler与RouteConfig.cs,RenderMvcController等路由到控制器的正确方法

Cha*_*ams 2 c# model-view-controller asp.net-mvc umbraco umbraco7

我有一个像这样的解决方案结构:

MyApp.Core
--Properties
--References
--bin
--Events
  |EventHandlers.cs
--Directory
  --Controllers
    |DirectoryController.cs
  --Helpers
    |ContextHelpers.cs
  --Models
    |DirectoryModel.cs
--AnotherSite
  --Controllers
  --Helpers
  --Models
  --Services
--Shared
  --Controllers
    |HomePageController.cs
  --Helpers
    |Extensions.cs
|app.config
|packages.config

MyApp.Umbraco
--Properties
--References
--bin
etc........
--Views
  --Directory
    --Partials
      |DirectoryFilters.cshtml
    |DirectoryBase.cshtml
    |DirectoryHome.cshtml
    |FDirectory.cshtml
    |SDirectory.cshtml
  --Partials
  --Shared
  |Base.cshtml
  |Web.config
etc........
Run Code Online (Sandbox Code Playgroud)

我的Umbraco实例使用我的"Core"项目中的模型和控制器.存在嵌套目录结构,因为一个安装中的多个网站,"Core"中以及Umbraco实例中的"Views"目录中.

我仍然相当熟悉.NET MVC,我理解路由劫持,但Umbraco路由的文档很小.我有以下内容:

EventHandlers.cs

namespace MyApp.Core.Events
{
    /// <summary>
    /// Registers site specific Umbraco application event handlers
    /// </summary>
    public class MyAppStartupHandler : IApplicationEventHandler
    {
        public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {

        }

        public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {
            RegisterCustomRoutes();
        }

        public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
        {

        }

        private static void RegisterCustomRoutes()
        {
            // Custom Routes
            RouteTable.Routes.MapUmbracoRoute(
                "FDirectory",
                "fdirectory/{id}",
                new
                {
                    controller = "Directory",
                    action = "FDirectory",
                    id = UrlParameter.Optional
                },
                new PublishedPageRouteHandler(1000));

            RouteTable.Routes.MapUmbracoRoute(
                "SDirectory",
                "sdirectory/{id}",
                new
                {
                    controller = "Directory",
                    action = "SDirectory",
                    id = UrlParameter.Optional
                },
                new PublishedPageRouteHandler(1001));

            RouteTable.Routes.MapUmbracoRoute(
                "HomePage",
                "",
                new
                {
                    controller = "HomePage",
                    action = "Index",
                    id = UrlParameter.Optional
                },
                new PublishedPageRouteHandler(1002));
        }
    }

    public class PublishedPageRouteHandler : UmbracoVirtualNodeRouteHandler
    {
        private readonly int _pageId;

        public PublishedPageRouteHandler(int pageId)
        {
            _pageId = pageId;
        }

        protected override IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext)
        {
            if (umbracoContext != null)
            {
                umbracoContext = ContextHelpers.EnsureUmbracoContext();
            }

            var helper = new UmbracoHelper(UmbracoContext.Current);

            return helper.TypedContent(_pageId);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

DirectoryController.cs

namespace MyApp.Core.Directory.Controllers
{
    public class DirectoryController : RenderMvcController
    {
        public DirectoryController() : this(UmbracoContext.Current) { }
        public DirectoryController(UmbracoContext umbracoContext) : base(umbracoContext) { }

        public ActionResult FDirectory(RenderModel model)
        {
            return CurrentTemplate(new DirectoryModel(model.Content));
        }

        public ActionResult SDirectory(RenderModel model)
        {
            return CurrentTemplate(new DirectoryModel(model.Content));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

因此Umbraco不会安装App_Start文件夹.我想知道Umbraco多站点安装的最佳方法是注册到控制器的路由.我的实现工作,但似乎我不应该为每个控制器中的站点,每个页面创建操作.我知道Umbraco有自己的路由,所以使用Umbraco概念,ASP.NET MVC概念以及其他任何可用的东西,实现这种类型的解决方案结构的最佳方法是什么?我是否应该担心使用RouteConfig.cs并创建App_Start目录?或者我正在做的最好的方法是什么?我应该使用IApplicationEventHandler还是ApplicationEventHandler?

此外,我必须硬编码节点ID.我读过有动态的方法吗?这样的例子会很棒.

实现结构化多站点Umbraco MVC解决方案的最佳方式的示例是我想要的,关于路由控制器,一些细节或链接到强大的示例.我已经进行了搜索和研究,并且有一些零碎的东西,但不是一个很好的例子,就像我正在使用的那样.我将不得不为此时创建的每个页面创建一个RouteMap,我不知道这是否是最有效的方法.我甚至尝试过实现一个DefaultController,但是当你的解决方案有多个控制器时,我没有看到这一点.

小智 5

我不完全确定你想用这个来实现什么,但我会尝试解释它是如何工作的,也许你可以事后澄清.

我假设您已经了解了Umbraco的基础知识(根据文档类型创建文档类型+文档).这就是Umbraco通常使用的方式,它将自动为您在站点中创建的每个"内容节点"(文档)进行路由.

因此,创建一个名为的文档document1,它将在您的站点中自动路由到URL:http:// localhost/document1.默认情况下,此文档将通过默认的MVC控制器提供,它将在幕后进行,无需您执行任何操作.

路由劫持允许您覆盖此默认行为并"推入"控制器,使您可以干扰请求的处理方式.要使用劫持RenderMvcController,请使用文档类型的别名创建.那可能是HomePageController : RenderMvcController.

此控制器应具有以下签名的操作:

public override ActionResult Index(RenderModel model)
Run Code Online (Sandbox Code Playgroud)

在此操作中,您可以以任何您喜欢的方式修改发送到视图的模型.这可能是 - 将一些外部数据添加到模型中或触发某些逻辑或任何您需要做的事情.

这一切都是通过命名约定自动连接的,您无需手动注册任何路由即可使用.

您可以创建的另一种类型的Umbraco MVC控制器是SurfaceController.这个通常用于处理子动作的渲染和表单提交(HttpPost).该SurfaceController也自动一把umbraco路由,将被定位于"不那么漂亮"的网址.但是,由于它通常不会用于渲染子操作和提交表单提交的任何内容,因此它所在的URL并不重要.

除了这些自动路由控制器,您当然可以像在任何标准MVC网站中一样注册您自己的MVC控制器.但不同的是,与普通的ASP.NET MVC网站不同,Umbraco站点没有控制器的自动默认注册,允许路由在创建新控制器时"正常工作".

因此,如果您希望在Umbraco站点中有一个普通的旧MVC控制器渲染而不与Umbraco中的文档/节点相关,则必须像在任何其他MVC站点中那样为其注册路由.最好的方法是使用ApplicationEventHandler类挂钩并将其添加到路径中.这将在应用程序启动期间自动触发 - 基本上允许您执行通常的操作App_Start.

但需要明确的是 - 如果您计划使用Umbraco的数据,则不应使用普通的MVC控制器,也不应要求进行任何手动路由注册.您通常希望在Umbraco中创建的文档/节点的上下文中呈现模板/视图(您可以在其中修改文档的数据/属性),然后路由劫持即可.


从它看起来,看起来你正在尝试做的正确方法似乎是简单地创建两种文档类型:

FDirectorySDirectory

你点击允许这两种在根目录中创建,然后创建文件名为FDirectorySDirectory和,他们将这些网址被自动路由.创建一个RenderMvcController被调用的FDirectoryController : RenderMvcController将确保它被用于在请求该页面时劫持路由.

如果您只是尝试设置多站点解决方案,我建议您Website在Umbraco内容树的根目录中创建文档类型并为所需的每个站点创建一个节点.右键单击每个节点,然后将主机名编辑为您需要的任何节点.这也可能是一些"子URL",/fdirectory或者/sdirectory如果你需要在localhost上测试它而不使用多个主机名.

希望这能为你提供所需的指针,否则试着解释你想要做什么,我会看看我是否可以稍微改进我的答案!