zoukankan      html  css  js  c++  java
  • 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相关引用就知道了。我可是不只一次入坑了。

    关于我:
    _____________________________________________________________________
    覃晓光
    期待能与大家一起沟通成长。
    QQ:293656 & 微信:ChinaMobile

  • 相关阅读:
    day10 文件内指针移动 小练习 函数的基本使用 函数定义与调用的各三种形式 函数返回值 函数参数的使用
    day09 文件基本操作 上下文管理 文件的打开模式 文件修改的两种模式 今日作业
    day07 列表类型 练习题 元祖类型 元祖vs列表 字典类型 集合类型
    java笔试之参数解析(正则匹配)
    java笔试之提取不重复的整数
    java笔试之自守数
    java笔试之尼科彻斯定理
    java笔试之简单密码
    java笔试之求最大连续bit数
    java笔试之放苹果
  • 原文地址:https://www.cnblogs.com/curd/p/5186336.html
Copyright © 2011-2022 走看看