本文通过创建一个产品模块进一步的讲解Orchard模块开发的相关知识。本文部分内容参见了官网文档《Creating a Module Using a Text Editor》中的一些介绍。
首先我们先明确一下本示例所要实现的需求:在Orchard建立一个产品模块可实现管理和显示产品的功能。产品需要包括以下字段:标题、价格、品牌,描述。通过前几篇文章介绍的关于内容部件的概念,我们可以通过创建一个产品部件和其余几个现有的部件组合形成一个新的产品类型来实现产品的功能。
第1步我们还是通过以前多次介绍过的命令行工具来创建一个模块代码的模板。
codegen module MyCompany.Products
第2步我们需要为产品部件来创建一个数据模型,用于存储产品特有的数据。本例我们就只需要两个字段:价格和品牌。在模块目录下的Models目录中,添加一个ProductRecord.cs文件,输入以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.ContentManagement.Records;
using Orchard.Data.Conventions;
namespace MyCompany.Products.Models
{
public class ProductRecord : ContentPartRecord
{
public virtual double Price { get ; set ; }
public virtual string Brand { get ; set ; }
}
}
在Orchard中如果需要实现内容部件的功能,相应的数据模型需要继承于ContentPartRecord类,这样Orchard框架就可以根据Content Id来将相关的内容组织在一起。另外在数据模型中的所有属性都必须加入virtual关键字,这应该是数据访问和OR映射的需要吧。
第3步我们就需要创建这个产品的Part了。如果说Model数据数据实体,那么Part我们可以理解为业务实体。还是在模块目录下的Models目录中,添加一个ProductPart.cs文件,输入以下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Orchard.ContentManagement;
using System.ComponentModel.DataAnnotations;
using Orchard.Core.Routable.Models;
namespace MyCompany.Products.Models
{
public class ProductPart : ContentPart < ProductRecord >
{
[Required]
public double Price
{
get { return Record.Price; }
set { Record.Price = value; }
}
[Required]
public string Brand
{
get { return Record.Brand; }
set { Record.Brand = value; }
}
}
}
要实现内容部件的功能,相应的Part类同样需要继承于ContentPart<ProductRecord>,这里ContentPart指定了泛型参数ProductRecord。就可以表明此ProductPart的数据是来自ProductRecord的。同时我们也可以将一些UI层上的验证加在这个Part类上面,如价格和品牌属性都加上了必填的要求。
第4步我们就需要创建在数据库中保存产品数据的表了。在我前面的内容中已经介绍过,Orchard中创建数据表的工作不是通过直接执行sql来实现的。而是通过在模块中创建一个Migrations.cs文件,用代码来定义其数据结构。我们还是可以利用命令行工具,来生成Migrations文件的模板。输入以下命令:
codegen datamigration MyCompany.Products
修改代码如下:
using System;
using System.Collections.Generic;
using System.Data;
using Orchard.ContentManagement.Drivers;
using Orchard.ContentManagement.MetaData;
using Orchard.ContentManagement.MetaData.Builders;
using Orchard.Core.Contents.Extensions;
using Orchard.Data.Migration;
using MyCompany.Products.Models;
namespace MyCompany.Products
{
public class Migrations : DataMigrationImpl
{
public int Create()
{
// 创建产品特有属性数据表 ProductRecord
SchemaBuilder.CreateTable( " ProductRecord " , table => table
.ContentPartRecord() // 产品Id,这个字段其实是和系统核心的Content表关联的
.Column < double > ( " Price " ) // 产品价格
.Column < string > ( " Brand " , column => column.WithLength( 200 )) // 产品品牌
);
// 定义ProductPart
ContentDefinitionManager.AlterPartDefinition( typeof (ProductPart).Name, cfg => cfg.Attachable());
// 定义ProductType
ContentDefinitionManager.AlterTypeDefinition( " Product " ,
cfg => cfg.WithPart( " ProductPart " ) // 包含产品部件
.WithPart( " RoutePart " ) // 路由部件
.WithPart( " BodyPart " ) // 文本部件
);
return 1 ;
}
}
}
第5步我们需要创建这个产品部件的处理器和驱动器,用于描述这个产品部件如何显示,如何操作数据。在《Orchard中的内容部件(Content Part)是如何工作的》一文中我已经描述了Handler和Driver的作用,其中的示例代码可直接用于此模块,此处不再赘述。
第6步我们需要对这个产品部件在内容中的显示位置以及显示方式进行定义。这个定义文件在模块的根目录下。具体介绍可先参见官网的这篇文档《Understanding the placement.info File》,以后我也会对这篇文档做深入的学习,这里先按照官网示例中的描述,在模块根目录下创建这个文件,并输入以下代码:
< Placement >
< Place Parts_Product ="Content:10" />
< Place Parts_Product_Edit ="Content:7.5" />
</ Placement >
第7步我们就需要创建这个模块UI层的东西了。如果说内容部件的驱动器(Driver)相当于MVC中Controller,那么内容部件的模板就相当于内容部件的View。根据本示例Driver中的定义,我们需要创建两个模板,一个用于显示画面,一个用于编辑画面。我们可以根据Orchard中查找模板的规则,在模块的View目录下分别创建一个Parts目录和一个EditorTemplates目录。并在Parts目录中创建一个Product.cshtml文件用于显示画面。这里我们就只用展现两个产品的两个属性即可,输入以下代码:
@using MyCompany.Products.Extensions;
@using MyCompany.Products.Models;
@using Orchard.ContentManagement;
@using Orchard.Utility.Extensions;
Price:
@Model.Price
< br />
Brand:
@Model.Brand
然后我们在EditorTemplates目录下再创建一个Parts目录并创建一个Product.cshtml文件用于编辑画面,输入以下代码:
@model MyCompany.Products.Models.ProductPart
< fieldset >
@Html.LabelFor(m => m.Price, T("Price"))
@Html.TextBoxFor(m => m.Price, new { @class = "textMedium" })
@Html.ValidationMessageFor(m => m.Price, "*")
</ fieldset >
< fieldset >
@Html.LabelFor(m => m.Brand, T("Brand"))
@Html.TextBoxFor(m => m.Brand, new { @class = "textMedium" })
@Html.ValidationMessageFor(m => m.Brand, "*")
</ fieldset >
官网示例到这里就结束了,因为IC报价网一个产品部件已经创建好了,我们只用在Orchard后台的类型管理中创建一个产品类型,然后在内容管理中找到我们所定义的产品类型来添加和管理产品就可以了。这样其实我们只是定义了一个产品部件,而不是一个真正意义上的产品模块。因为这个产品的显示界面和管理界面,都只是利用了Orchard内容管理的功能去实现。为了让产品模块看来更像一个模块,我们还需要做以下工作。
这个步骤其实在我们以前的学习过程中已经先预热过了。和《在Orchard中升级HelloWorld模块》一文中描述的一样,我们需要先IC报价网创建一个后台管理菜单文件AdminMenu.cs,其次我们需要添加一个AdminController来实现其后台界面的相关操作,最后我们还需要定义相应后台界面视图。此部分的代码较多可以在本文后面下载本示例源代码查看。
这个步骤我们以前也同样预热过,也和《在Orchard中创建一个HelloWorld模块》一文中所描述的一样,要实现一个前台的显示画面我就需要定义Routes,实现相应画面的Controller,以及创建画面所对应的视图。关于显示视图方面的内容涉及到了Orchard中的视图引擎机制,具体原理还得深入学习,在这里我们先模仿其他Orchard模块中的方法来实现这部分的内容,这部分的代码也可下载本示例源代码查看。