Orchard入门:如何创建一个完整Module
这是一个Orchard-Modules的入门教程。在这个教程里,我们将开发两个功能页面分别用于数据录入与数据展示。
完成上述简单功能开发,我们一共需要6个步骤。分别为:
上面6个步骤可能不太好理解。在这里,我们把他们转换从MVC中的概念让我们更好理解。
|
Module |
项目模块 |
|
Model |
实体层 |
|
Controller、View |
Controller、View |
|
Route |
Route |
|
Services |
服务层 |
|
Admin Menu |
后台管理 |
有点概念后,我们就开始吧!
创建Module
第一步我们需要利用Orchard的代码生成工具Code Generation 来生成Module项目文件。如果对这个命令还不是很熟悉,我们可以在这里先进行了解。
创建:
|
codegen module XiaoGuang.HelloWorld |
使用上述就完成了一个HelloWorld Module的创建。
*关于Module的名称,建议使用系统模块.功能名来命名。


修改清单文件Module.txt:
这个文件用于描述Module信息与依赖关系。因为本次只是一个简单示例,不深入讲解。
|
Name: XiaoGuang.HelloWorld AntiForgery: enabled Author: 互联网新手 Website: http://curd.cnblogs.com Version: 1.0 OrchardVersion: 1.0 Description: XiaoGuang.HelloWorld演示模块。 Features: XiaoGuang.HelloWorld: Description: XiaoGuang.HelloWorld演示模块。 |
启用:
管理后台->Modules->找到[XiaoGuang.HelloWorld]->点击Enable 或 命令行:feature enable XiaoGuang.HelloWorld
不少朋友开发完Module后,输入了注册路由的地址。发现始终无法看到效果。实际上是Module默认为非启用状态导致。
创建Model
Models目录下新增TestRecord.cs 文件。新增,代码如下:
|
namespace XiaoGuang.HelloWorld.Models { public class TestRecord { public virtual int Id { get; set; } public virtual string Content { get; set; } } } |
注:如果后续运行提示没有持久化的问题。是因为实体类必须放在命名空间为Models或Records结尾下。
这属于Orchard默认规范,详见:https://orchard.codeplex.com/discussions/267968
|
codegen datamigration XiaoGuang.HelloWorld |
上述语句创建一个实体迁移。并生成如下代码,完成Record对应表创建过程。
|
public class Migrations : DataMigrationImpl { public int Create() { // Creating table TestRecord SchemaBuilder.CreateTable("TestRecord", table => table .Column("Id", DbType.Int32, column => column.PrimaryKey().Identity()) .Column("Content", DbType.String) ); return 1; } } |
创建Services
新建文件:

ITestService:
|
public interface ITestService :Orchard.IDependency { TestRecord GetTest(); TestRecord UpdateTest(string content); } |
TestService:
|
public class TestService : ITestService { private readonly IRepository<TestRecord> _testRepository; public TestService(IRepository<TestRecord> testRepository) { _testRepository = testRepository; } public TestRecord GetTest() { return _testRepository.Table.FirstOrDefault(); } public TestRecord UpdateTest(string content) { var result = GetTest(); if (result == null) { result = new TestRecord {Content = content}; _testRepository.Create(result); } else { result.Content = content; _testRepository.Update(result); } return result; } } |
上面的代码的重点是IRepository ,由Orchard封装。实现了实体的增、删、改、查功能。
创建Controller、View

Controller:
|
public class AdminController : Controller { public IOrchardServices Services { get; set; } public ITestService TestService { get; set; } public AdminController(IOrchardServices services, ITestService testService) { Services = services; T = NullLocalizer.Instance; TestService = testService; } public Localizer T { get; set; } public ActionResult Update(string content) { TestService.UpdateTest(content); return RedirectToAction("Index", "Home"); } } |
这里充分体现了依赖注入的好处。只需要构造函数传递接口就可以了。框架自动实例。也易于单测。
View:

|
@model XiaoGuang.HelloWorld.Models.TestRecord @{ Layout.Title = T("TestUpdate").ToString(); } @using (Html.BeginFormAntiForgeryPost(Url.Action("Update", "Admin"))) { @Html.AntiForgeryToken() <div class="form-horizontal"> @Html.ValidationSummary(true, "", new {@class = "text-danger"}) <div class="form-group"> @Html.LabelFor(model => model.Content, htmlAttributes: new {@class = "control-label col-md-2"}) <div class="col-md-10"> @Html.EditorFor(model => model.Content, new {htmlAttributes = new {@class = "form-control"}}) @Html.ValidationMessageFor(model => model.Content, "", new {@class = "text-danger"}) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Create" class="btn btn-default"/> </div> </div> </div> } |
创建Route
新增Routes.cs文件。返回指定的路由。
|
public class Routes :IRouteProvider { public IEnumerable<RouteDescriptor> GetRoutes() { yield return new RouteDescriptor { Route = new Route("MyHelloWorld", new RouteValueDictionary { {"area", "XiaoGuang.HelloWorld"}, {"action", "Index"}, {"controller", "Home"} }, new RouteValueDictionary(), new RouteValueDictionary { {"area", "XiaoGuang.HelloWorld"} }, new MvcRouteHandler()) }; yield return new RouteDescriptor { Route = new Route("admin/XiaoGuang.HelloWorld/Update", new RouteValueDictionary { {"area", "XiaoGuang.HelloWorld"}, {"action", "Update"}, {"controller", "Admin"} }, new RouteValueDictionary(), new RouteValueDictionary { {"area", "XiaoGuang.HelloWorld"} }, new MvcRouteHandler()) }; } public void GetRoutes(ICollection<RouteDescriptor> routes) { foreach (var route in GetRoutes()) { routes.Add(route); } } } |
创建Admin Menu
该功能用于产生一个后台导航菜单,定位到管理页面。相信代码直接读就可以理解。需要继承于INavigationProvider。
|
public class AdminMenu : INavigationProvider { public string MenuName => "admin"; public Localizer T { get; set; } public void GetNavigation(NavigationBuilder builder) { builder.AddImageSet("helloworld").Add(T("HelloWorld"), "5", item => { item.Action("Index", "Admin", new {area = "XiaoGuang.HelloWorld"}); }); } } |
需要特殊说明一下。public string MenuName => "admin";
这段代码是固定值,注意指的大小写。具体原因搜索下INavigationProvider相关引用就知道了。我可是不只一次入坑了。
Orchard入门:如何创建一个完整Module的更多相关文章
- CXF 入门:创建一个基于WS-Security标准的安全验证(CXF回调函数使用,)
http://jyao.iteye.com/blog/1346547 注意:以下客户端调用代码中获取服务端ws实例,都是通过CXF 入门: 远程接口调用方式实现 直入正题! 以下是服务端配置 ==== ...
- SpringMVC基础入门,创建一个HelloWorld程序
ref:http://www.admin10000.com/document/6436.html 一.SpringMVC基础入门,创建一个HelloWorld程序 1.首先,导入SpringMVC需要 ...
- 3dmax实例教程-使用3ds Max 创建一个完整的场景
本篇教程讲述了利用3ds max创建一个完整的场景. 灵感来源:当我在遇到一些事情睡不着觉的时候我便在努力想象一些别的事情,于是我便想到了这个场景,其实对于我的这个角色我即没有参考图也没有草稿图,有的 ...
- SQL Server Database 维护计划创建一个完整的备份策略
SQL Server维护计划Maintenance Plan这是一个非常有用的维护工具,能够完成大部分的数据库维护任务,通过这些功能包.您可以省略大量的编码时间. 介绍的不是非常多,特此补上一篇 ...
- 【翻译】Sencha Touch 2入门:创建一个实用的天气应用程序之三
原文:Getting Started with Sencha Touch 2: Build a Weather Utility App (Part 3) 作者:Lee BoonstraLee is a ...
- Angular2快速入门-2.创建一个新闻列表
背景: 我们想通过一个例子,展示下Angular2 怎么绑定页面,怎么创建Component, 例子:我们创建一个新闻列表,当点击新闻列表中某一条新闻的时候,展示出该条新闻的详细信息, 在详细信息中可 ...
- WCF入门, 到创建一个简单的WCF应用程序
什么是WCF? WCF, 英文全称(windows Communication Foundation) , 即为windows通讯平台. windows想到这里大家都知道了 , WCF也正是由微软公 ...
- 简单创建一个完整的struts2框架小程序
要完成一个struts2框架的搭建, 1.首先应该从官网上下载最新的jar包,网络连接:http://struts.apache.org/download.cgi#struts2514.1,选择下载F ...
- CXF 入门:创建一个基于SOAPHeader的安全验证(CXF拦截器使用)
CXF拦截器使用,创建一个使用SOAPHeader的安全验证xml格式: <soap:Header> <auth:authentication xmlns:auth="ht ...
随机推荐
- Nodejs基础中间件
Nodejs基础中间件Connect http://www.tuicool.com/articles/emeuie 关于作者 张丹(Conan), 程序员Java,R,PHP,Javascript ...
- NSDate和NSDateFormatter 相关应用代码示例
此方法用来计算当前时间与目标时间的先后顺序: -(NSDate *)calculateTimeWithCurrentTime:(NSDate *)currentDate{ //将当前时间转为本地时区 ...
- [转]Part1: Understanding !PTE , Part 1: Let’s get physical
http://blogs.msdn.com/b/ntdebugging/archive/2010/02/05/understanding-pte-part-1-let-s-get-physical.a ...
- 关于sqlserver 2008 无法远程连接的问题
Sqlserver 2008 无法远程连接,原因无非如下: 1. Sql未配置为允许TCP/IP登录: 2. 防火墙未允许端口1433(或者其他在SQL配置中指定的端口): 3. 命名实例导致的无法连 ...
- hive的使用01
1.安装mysql数据库 1.1 查看本机是否安装了mysql数据库(rpm -qa | grep mysql)
- onSaveInstanceState的执行时机
当某个activity变得"容易"被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK ...
- inline-boock的默认间距
1 2 3 4 div{width:900px;} div li{ display:inline-block; width:300px;} <ul> <li></ ...
- T-SQL编程练习(带注释)
use test; GO /*创建自定义函数的格式: * create function 函数名(参数 数据类型) * returns 返回数据类型 as * begin * 代码 * end */ ...
- InfoPackage的更新模式
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...
- 自定义一个类似UIAlertView的弹出框
这个是和UIAlertView类似,但是可以自定义view的样式废话不多说,上代码: 首先第一步:创建一个继承自View的类如: #import <UIKit/UIKit.h> @clas ...