前两篇,我介绍了 Orchard 项目的概况和安装与部署 和 Orchard 开发环境过程中需要注意的点。从这篇开始,我们真正进入Orchard 模块开发的工作。

再一次,我需要强调的是,请确定您正在准备 Orchard 模块开发。因为如果您只是需要使用 Orchard 来创建一个功能齐全的网站,或者正在计划使用您的设计才能为 Orchard 生态系统贡献您的设计作品,请您寻找其他资料。

 

Orchard 模块

Orchard 模块是为 Orchard 提供功能的基本方式,开发新模块、而不是修改现有代码作为自定义 Orchard 的行为的方式之一,也是社区推荐的方式。在形式上,一个模块类似于一个典型的常见的 ASP.NET MVC 项目,而 Orchard CMS 则为所有这些模块提供基础服务。这样所有模块不但可以专注于自己的业务逻辑,甚至借助 CMS 中提供的便利的特性,模块之间还可以相互影响。这样通过模块,我们不仅能够扩展 CMS 的功能,还能修改目前已有的行为。

通过查看源代码的结构,我们可以看到,Orchard 解决方案里有 60+ 的项目,其中除了 Framework 和少量的测试项目之外,大多数都是模块。即使 Orchard 项目的核心功能(如设置、内容、管理控制台等)也都是使用类似于模块的方式组织起来的,可见模块并非 Orchard 为扩展专门提供的某一种类似于“插件”的机制,而是由项目内建并直接作为提供系统所有功能的基础机制。

 

使用传统的方式创建 Orchard 模块

创建 Orchard 模块是一件简单的工作。使用 Visual Studio 打开项目之后,您可以直接在 Modules 解决方案目录上右击,并添加新的项目。

image

在弹出的对话框中选择项目类型为 ASP.NET MVC3 Web 应用程序,就可以利用 VS 的项目模块自动添加 System.Web 等必要的引用。如果您的“添加项目”对话框中还没有 ASP.NET MVC3 Web 应用程序这一项可选,那你还没有安装好 MVC3,请参照其他教程完成安装。

稍需要注意的是,按照 Orchard 的惯例,您也可以将自己的模块命名为以 Orchard. 开头,这里我将新的模块命名为 Orchard.News,因为我将添加一个全新的新闻管理模块。此外,Orchard 的模块的文件都存放在源代码的 src\Orchard\Orchard.Web\Modules\ 目录中,因此,在创建项目时,最好将项目的位置也放在这里。

image

点击确定后,继续完成 MVC Web 应用程序的创建,此时新的项目就被添加到了 Orchard 解决方案中,而且我们新添加的项目即将成为新的 Orchard 模块——虽然目前还不是。

需要注意的是,Orchard 项目在开发之初,已经考虑部署环境对 MVC 的支持情况,为了不遗留不必要的麻烦,我们从线上下载的 Orchard 解决方案包中已经附带 MVC 的程序集。因此,我们在 VS 中对新创建的项目的引用进行整理:
除了 System、System.Web 和 System.Web.Abstration、System.ComponentModel.DataAnnotations、Microsoft.CSharp 等少数几个必要的和 System.Xml 和 System.Xml.Linq 等可能用到的程序集之外,都予以删除。
同时,我们需要引用项目本身的 Orchard.Framework 和 Orchard.Core;添加随项目一起发行(在源码文件夹的 lib\aspnetmvc目录中)的 MVC 的程序集的副本 System.Web.Mvc。最终我们项目的引用情况如下:

image

在后面的开发工作中,如果遇到另外需要的程序集,届时再添加引用。之所以要处理好引用关系,是因为在部署时,不当的引用可能会带来额外的麻烦,由于不同的程序集版本带来的意外的运行结果也不符合预期。

另外,VS 在创建项目的同时,也同时创建了一系列示例文件。这些文件对我们的开发工作并没有帮助,因此可以将这些已建的文件夹都清空。甚至,Global.ascx 对于模块来说也是多余的,因为最终在运行时,模块会成为 CMS 的一部分一同加载到顶级 Web 项目中,因此模板中的 Global.ascx 是没有用处的。
其余 App_Data 等原生 ASP.NET 文件夹,在后面您可以看到,您不需要使用文件系统来存取文件,因此这些文件夹是不必的; 至于 Web.Config,要说清楚的话可能得花一整天的版面,最简单的办法就是从其他模块,比如 Orchard.Blogs 复制一份过来在新的模块中用。

好吧,我骗了您,似乎上面的过程也不太简单。Smile 不过,我们的确快要成功了!

最后一个步骤——完成这个步骤,您肯定就成功了!
在新的模块根目录创建一个 Module.txt,用它来描述一下我们要创建的新模块,这样 Orchard 在启动时就知道有新的模块,而且能够加载我们指定的元信息。对于这个文件的格式,我们暂时不熟悉的话,也可以先从其他模块复制一个过来,我从 Orchard.Blogs 复制,稍作修改,就成了我自己的 Module 元文件了。

1
2
3
4
5
6
7
8
9
Name: News
AntiForgery: enabled
Author: ciznx chan
Website: http://blog.jijiechen.com
Version: 1.0
OrchardVersion: 1.5
Description: News provides publishing and managing news for Orchard
Dependencies: Shapes, Common, Orchard.jQuery, Orchard.PublishLater
Category: Content

完成这一切之后,我们回到 Orchard 的管理面板(Dashboard)中,发现 Modules 中已经列出了我们刚刚创建的 News 模块,甚至我们可以立即启用它,尽管它目前还没有任何功能。

image

 

使用 Code Genarator  生成的方式创建模块

有一种更简便的方法创建新的 Orchard 模块,比上面所述要简单10好几倍。(不过,如果您已经使用上面的方法创建了模块,那这个部分,您就等下次需要用的时候再详细斟酌吧,今天先阅览一下。)
就在这个管理面板的 Modules 页,在 Filter 中输入 “Code” 您可以看到被筛选出来的 Code Generation 模块,这是 Orchard 项目内置的一个供开发人员使用的生成代码的命令行工具模块。有了它,我们今后的工作就简单得多了。
现在,启用它!

然后找到 Orchard 项目的磁盘目录的 src\Orchard.Web\bin 中找到 Orchard.exe,双击运行。
过了一小段时间的初始化过程之后,我们可以看到一个命令行工作台,我们输入命令

1
codegen module Orchard.News

image

从控制台,我们可以很直观地看到工具已经为我们创建了新的模块。这时,我们回到 VS 解决方案,已经收到提示解决方案已修改,并提示我们重新加载。使用代码生成工具得到的项目的结构与上文中我们手动创建得到的类似,嗯,与前述方法类似,您也需要完成 Module.txt 文件中的内容,不过这次,工具已经为我们生成好了格式。

image

显而易见,与之前的方式相比,使用 Code Generator 的方式更文艺,也为我所喜欢和推荐;之所以还要赘述之前的内容,是想籍此向您展示 Orchard 模块项目的本质,相信您已理解一个 Orchard 模块就是一个 CSharp 项目,而且一般是 Web 项目,它具有典型的 ASP.NET MVC 项目的结构,却有着自己的既定格式。

 

Orchard 模块项目结构

由于我们刚刚创建的项目的结构还有些过于简单,作为一个模块,其常见的结构还没有得到体现,因此不足以讲解整个模块的结构。系统内置的 Orchard.Blogs 与我们创建的 Orchrad.News 的功能类似,都是提供独立的内容功能;因此,我截取它的项目结构作为典型范例予以介绍。

image

右图是 Orchard.Blogs 的项目结构,其中根目录的文件分别是:

AdminMenu.cs 用于在管理面板添加必要的功能菜单;

Migration.cs 在安装和升级模块时,提供数据库结构的构建和更新功能;

Module.txt 描述当前模块的元信息(名称、作者和版本等信息)的文本文件;

Permissions.cs 当前模块所需要使用的专有权限体系;

Placement.info 描述当前模块中所提供的 部件(Part) 应该在文档中所处的位置定义的 XML 文件;

ResourceManifest.cs 定义当前模块向系统声明以供公共使用的静态资源;

Route.cs 定义当前模块需要特意指定的路由规则;

web.config 用于支持模块开发和运行的 ASP.NET 配置文件。

 

除根目录的文件之外,我们所见到的文件夹,及其典型用途如下:

Content 放置当前模块需要用于的静态资源,如图片、静态HTML片断等。在该目录中默认放有将该目录及其子目录中的资源设置为静态资源的配置,因此请勿将任何代码文件置于该目录;

Controllers 存储当前模块需要用于处理客户端请求的 ASP.NET MVC 控制器。作为 ASP.NET MVC 中“约定胜于配置”的重要内容,控制器类应该继承自 System.Web.Mvc.Controller,命名应该是[ XXXXController **] **其控制器名称是前面的部分 XXXX ;

Drivers 放置用于指示如何显示和编辑当前模块中特有的 内容部分ContentPart)的驱动程序。这些类继承自Orchard.ContentManagement.Drivers.ContentPartDriver<TContent> 泛型抽象基类,其命名规则通常是 内容部分 的名称加 Driver,如 BlogPostPartDriver

Extensions 当前模块中需要对系统部分功能添加的必要的扩展方法的类;

Handlers 存放当前模块特有的内容部分的数据相关的处理(如数据存取、索引和与其他内容部分的相关性等)程序。如果你需要为你的领域模型提供数据库存取能力、在内容的创建、编辑和删除,以及索引前后,订阅这些过程的事件并尝试进一步处理,就需要创建这些继承自 Orchard.ContentManagement.Handlers.ContentHandler 的处理程序;

Models 当前模块中所提供的独有的内容部分的领域模型类和对应的数据记录类。这与传统的 ASP.NET MVC 项目的 Models 文件夹的含义并无二致,但在 Orchard 模块开发中,我们可以使用系统提供的 ContentPart 基础设施轻松建立起与 CMS 处理管线高度集成的自己的 内容部分

Scripts 当前模块的视图文件中可能用到或用于公开为公共使用的的脚本资源的文件。与 Content  目录类似,这是个特别的目录,它也被配置为静态资源存放位置,而且约定为专门存放脚本。在视图文件中,我们可以直接使用 Script.Include 来插入该目录中的脚本,而无需指定相对于应用程序的路径,也不用指定绝对的 URL;

Services 用于为控制器提供数据和其他领域模型间的逻辑操作的服务程序;

Styles 当前模块的视图文件中可能用到或用于公开为公共使用的的样式资源的文件;与 Scripts 目录类似,这是个约定为放置样式的静态资源存放目录。在视图文件中可以使用 Style.Include 来插入该目录中的样式文件;

ViewModels 供 MVC 视图使用的视图模型类;

Views 用于呈现的 MVC 视图文件(.cshtml 和 .vbhtml 文件存放位置)。该目录存放用于 Controllers 目录中的控制器使用的视图文件,以及当前模块独有模块的 内容部分 的显示和编辑的部件,也可用于存放供其他任何用于显示的文档片断。作为 ASP.NET 中“约定胜于配置”理念的内容之一,Views 目录结构应为 控制器名 \ Action名,即,在Views 目录下有一个子目录 Admin 用于存储 AdminController 中所有 Action 对应的视图,且这些视图的文件名称与 Action 的名称一致。

Orchard.Blogs 还包括了平时可能用的并不是很多的一些文件夹:

Command 指示并为当前模块可以提供给 Orchard 命令行的功能命令提供程序支持;

Routing 定义当前模块需要特意指定的路由规则的补充策略;

**Security **模块为安全处理过程提供的扩展机制;

在后面的文章中,我们将随着 Orchard.News 接触上述大部分常用的文件夹,并向其中添加我们需要的程序和数据。届时,我将继续详细讲述。