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相關引用就知道了。我可是不只一次入坑了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM