Orchard编写网上商店模块1

站在巨人的肩膀上,可以看的更高。
这里就先学习一下前人是怎么来进行开发的吧。
参考地址:
http://skywalkersoftwaredevelopment.net/blog/writing-an-orchard-webshop-module-from-scratch-part-1

1.介绍
虽然Orchard是一个了不起CMS(内容管理系统),有着强大的功能和令人振奋的架构,可以无限的扩展,但它可能需要花费一定时间,以充分了解它的架构,并能够定制您自己的主题的各个方面或甚至创造整个模块来集成Orchard所有的可扩展性点。 你会看到Orchard及其架构之美。它不仅只是在简单或高级的网站和博客方面表现很出色,同时它也是一个非常基础的平台,用于创建各种基于Web的应用,如电子商务后端, CRM的投票系统,项目管理,社区网站,学习管理系统等等。基本上你打算从头创建的任何应用都应考虑使用Orchard创建。Orchard实际上是一个可扩展的框架,它不仅仅“只是”一个CMS。你可以通过插件方式做任何常规ASP.NET MVC应用可以做的事,同时Orchard还拥有一套丰富的功能和兼容概念,你可以获得额外的好处。
网上商店功能
我们的网上商店模块将启用以下功能:
管理员将能够将任意ContentType(内容类型)通过附加到ProductPart上,从而把它变成产品。
网站访客(顾客)将能够把产品添加到购物篮,通过网站注册,并成为注册用户。
用户将能够进行结算和通过在线支付服务提供商(PSP)支付(在我们的演示,我们将使用Ogone模拟PSP)选定的产品。
在客户被重定向到PSP之前,系统将创建一个Order(订单)记录,及其OrderDetail (订单明细)记录。
在客户支付订单后,我们需要处理的产品交付。在实物产品的情况下,我们可能要通知一些航运伙伴。在虚拟产品的情况下,我们可能要产生类似于票据,或其他近似的产品。为了这种灵活性,我们将实现某种接口IShippingProvider,我们将创建两个简单的实现:一个是发送电子邮件通知托运人,另一个会产生票据。
管理后台,使管理员能够管理客户以及订单。

2.配置开发环境
当创建Orchard模块时,建议您下载完整的源代码,让我们从Orchard项目的首页:http://orchardproject.net/下载
我下载的是1.8.1的版本
下载后,vs打开,运行,配置数据库。
启动成功后,会出现开始页面。
如果出现错误,请百度解决。

3.创建Orchard.Webshop模块项目
可以使用命令行工具来创建模块,也可以手工。
打开Orchard命令行工具(在你的站点下面的bin或者debug中有一个orchard.exe文件),输入命令(创建HelloWorld Module) codegen module HelloWorld
修改Manifest文件,主要是开启该Module,告诉调用者一些基本信息。

这里我进行手工创建:
在Modules文件夹下新建一个类库项目
创建模块的manifest文件:Module.txt
Name: Orchard.WebShop
AntiForgery: enabled
Author: Sipke Schoorstra
Website: http://skywalkersoftwaredevelopment.net
Version: 1.0
OrchardVersion: 1.3.10
Description: Orchard Webshop Module Demo
Category: Webshop
启动网站,控制面板,然后启用新的Module

4.定义一个Content Part,ProductPart
创建一个ProductPart,从而可以存储数据到数据库中,我们需要创建ProductRecord,并继承自Orchard.ContentManagement.Records.ContentPartRecord。
Orchard使用后缀“Record”作为规范,使用NHibernate ORM持久化。
1. 添加对Orchard.Framework项目的引用,以便能够从Orchard.ContentManagement.Records.ContentPartRecord上继承。
2. 添加新文件夹命名为”Models”
3. 在”Models”文件夹中,创建一个新的类命名为ProductRecord。
4. 在”Models”文件夹中,创建一个新的类命名为ProductPart,并从ContentPart 继承。
5. ProductPart将有以下属性:Price(价格)和SKU。

namespace Orchard.Webshop.Models
{
public class ProductRecord : ContentPartRecord
{
public virtual decimal Price { get; set; }
public virtual string Sku { get; set; }
}
}

namespace Orchard.Webshop.Models
{
public class ProductPart : ContentPart
{
public decimal Price
{
get { return Record.Price; }
set { Record.Price = value; }
}
public string Sku
{
get { return Record.Sku; }
set { Record.Sku = value; }
}
}
}

在Orchard可以映射,加载和保存ProductRecord对象的实例到数据库之前,我们需要告诉它数据库表结构是什么样子。
我们通过创建一个叫Migration的类,一个继承自
Orchard.Data.Migration.DataMigrationImpl,并调用一些方法来定义数据库结构(schema)的类。
在Migration里,我们告诉Orchard哪些表要创建和哪些ContenteTypes 和 ContentParts要创建。

在你的模块的跟目录下,创建一个名为Migrations.cs的新类,并敲入如下代码:
namespace Orchard.Webshop
{
public class Migrations : DataMigrationImpl
{

public int Create()
    {
        SchemaBuilder.CreateTable("ProductRecord", table => table
            .ContentPartRecord()
            .Column<decimal>("Price")
            .Column<string>("Sku", column => column.WithLength(50))
            );

        return 1;
    }
}

}

“Create”是Orchard使用一个规范,在启用模块时,它将为调用。
ContentPartRecord方法是一种简便的方法,用于创建一个ID列,并设置为主键:
///
/// Defines a primary column as for content parts
///
public CreateTableCommand ContentPartRecord()
{
Column(“Id”, column => column.PrimaryKey().NotNull());
return this;
}
在我们的例子中,我们已经启用了模块。但果Orchard很聪明,它检测到现有一个DataMigration可用, 然后它会检查当前存储的Migration版本号,我们的模块启用时,没有Migration可运行,所以在Orchard_Framework_DataMigrationRecord表也找不相应的版本号
当您刷新Orchard Admin页面,Orchard将显示一个通知,显示需要升级一些功能
点击Orchard.Webshop链接,您将直接调转到模块页面,并显示Orchard.Webshop功能
当您单击“Upgrade”,Orchard将调用我们的Migrations类的Create方法,从而创建名为Orchard_Webshop_ProductRecord表
正如你可以看到,Orchard也在Migrations表插入一个新的记录,其中包含了我们的Migration类的类名和它返回的最后一个版本号。
Create方法返回值1。
现在我们创建了一个表,可以存储的产品信息,但是这还不够,我们需要告诉Orchard ProductPart是“可以被附加的(attachable)”:这是组合ContentTypes的关键,从而使用例子的“书”可以变成商品。
要做到这一点,我们要在Migration类中添加一个名为UpdateFrom1的方法,使ProductPart成为attachable

为了能够使用AlterPartDefinition方法和Attachable方法,我们需要导入的命名空间和引用Orchard.Core项目。
小提示:ReSharper的会告诉你哪些程序集要引用和命名空间要引用,在大量的项目中,这还是真挺有帮助的。
完整的migration,现在看起来像这样:
using Orchard.Data.Migration;
using Orchard.Data.Migration.Schema;
using Orchard.ContentManagement.MetaData;
using Orchard.Core.Contents.Extensions;
using Orchard.Webshop.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Orchard.Webshop
{
public class Migrations : DataMigrationImpl
{

public int Create()
    {
        SchemaBuilder.CreateTable("ProductRecord", table => table
            .ContentPartRecord()
            .Column<decimal>("Price")
            .Column<string>("Sku", column => column.WithLength(50))
            );

        return 1;
    }
    public int UpdateFrom1()
    {
        ContentDefinitionManager.AlterPartDefinition(typeof(ProductPart).Name, part => part
            .Attachable()
            );

        return 2;
    }
}

}
当你修改了你的模块,就像我们只是刚刚作的,你只需要保存文件:当你刷新页面,Orchard将重新编译模块。
当你刷新管理页面,Orchard将再次显示一个通知说,一些功能需要进行升级
我们将继续并更新功能。这样做将导致migration记录的版本号被更新为2,并且使ProductPart成为了attachable:它将在Settings_ContentPartDefinitionRecord表创建一条新的记录,并设置为true
为了验证,我们有一个ProductPart可用,我们导航到Content -> Content Parts,很神奇,我们干了这么多工作

很好!现在,让我们继续前进,创建一个新的ContentType,就叫“书”,并给它附上ProductPart:
创建一个新的内容类型:
1. 转到Content -> Content Type,并点击”Create new Type”按钮;
2. 输入“Book”作为显示名称和内容类型ID(这个会为你自动完成),然后按“Create”按钮;
3. 这个叫”Book”的内容类型已经创建好了。现在,我们要真正定义这个书的类型,(说到底,任何内容类型都是一组ContentParts的集合), 所以我们的挑选的以下部分,作为书的类型,使它更一个书的商品:Body, Comments, Containable, Product, Route和Tags, 然后点击“保存”。

现在我们有一个书的Content Type,这也是一种商品类型。我们还附加了Containable Part,这样我们可以把Book添加列表或其他包含Container Part的Content Tyeps中。
由于我们还附上了Route,我们还有了书的标题和URL。Comments让网站的访问者对本书发表评论和Tags Part,允许管理员给书添加标签。

然而,当我们试图建立一个实际的书,我们看到各种输入字段,但是还没有Price和SKU字段
这是怎么回事?Orchard的工作方式是这样的,为了呈现任何内容,Orchard调用每个ContentPart为Driver。一个Driver很类似与一个MVC Controller,但它只负责处理Part的内容,而不是整个HTTP请求本身。

Driver通常有3个操作方法:一个用于网站的前端显示部分,一个用于该网站的后端显示编辑模式,还有一个处理当管理员保存内容项时的回发(Postback)。

Driver通常返回的ActionResult是一个ShapeResult。ShapeResult告诉Orchard使用Razor模板呈现这个Part,还包含了动态对象将作为的Razor模板的模型。这种模型被称为Shape(形状),是一个动态”粘土”对象。

因此,一个模板可以被看作是“皮肤”的形状,使用Rqazor视图(.cshtml)作为实现。形状本身则是Razor视图模型。
在编辑模板的情况下,该模板将包含特定部分内容的编辑字段。

这种Shapes和Drivers的概念可能是Orchard的最强大的功能之一,也是最具挑战性的概念,真正挑战你的大脑。
但实际上,当一旦你看到它是如何工作的,它还是很简单的,让我们继续。
让我们为我们的ProductPart创建Driver程序:
1. 建一个新的文件夹,起名叫Drivers
2. 在该文件夹内,创建一个新类名为ProductDriver

namespace Orchard.Webshop.Drivers
{
public class ProductDriver : ContentPartDriver
{
protected override DriverResult Editor(ProductPart part, dynamic shapeHelper)
{
return ContentShape(“Parts_Product_Edit”, () => shapeHelper.EditorTemplate(TemplateName: “Parts/Product”, Model: part, Prefix: Prefix));
}

protected override DriverResult Editor(ProductPart part, IUpdateModel updater, dynamic shapeHelper)
    {
        updater.TryUpdateModel(part, Prefix, null, null);
        return Editor(part, shapeHelper);
    }
}

}
Driver程序类,目前有两种方法:编辑(Edit)和处理回发的重载方法。现在我跳过了显示(Display)方法,但我们会稍后补上。
当Orchard想要显示ProductPart的编辑页面进,它调用Driver程序的Edit(编辑)方法。当管理员提交的编辑结果时,重载的Editor(编辑)方法(带IUpdateModel参数)将被调用。

在ContentShape方法被定义在ContentPartDriver的基类中,并从MVC ActionResult类继承。一个ContentShape实例告诉Orchard Shape的名称以及这个Shape(形状)看起来像什么:这个Shape有一个TempateName属性,一个Model属性和一个Prefix属性。Orchard要用到这些属性,因此它可以计算出实际使用哪个模板来呈现的形状,并给你一个机会,为要使用的模板提供Model(模型)。

在我们的例子中,我们的形状的名称是“Parts_Product_Edit”,它的模板放在“Parts/Product”下就可以被找得到。因为我们在谈论的编辑一个Content Part, Orchard 将在路上加上前缀“~//Orchard.Webshop/Views/EditorTemplates”,所以完整的路径将是:“~/ Orchard.Webshop /Views/EditorTemplates /Parts/Product.cshtml”。

然后我们就在那里创建Razor模板文件,它看起来像这样:
@using Orchard.Utility.Extensions
@model Orchard.Webshop.Models.ProductPart

Product Fields
@Html.LabelFor(x => x.Sku)
@Html.EditorFor(x => x.Sku) @Html.ValidationMessageFor(x => x.Sku)
@Html.LabelFor(x => x.Price)
@Html.EditorFor(x => x.Price) @Html.ValidationMessageFor(x => x.Price)

如果有错误,就添加web相关的dll引用
在Orchard调用Editor方法返回并实际呈现形状之前,我们需要定义形状的位置。

Placement是一个可以帮助确定在什么位置,和在什么区域(Zone) (其实它也是一个形状) 呈现一定的形状的系统。
我们可以通过在我们的模块项目的根目录下创建一个名为”Placement.info”的文本文件, 来 定义我们的“Parts_Product_Edit”(记住,我们在ProductDriver的编辑方法定义的形状的名称),它看起来像这样:


这是告诉Orchard把任何名为“Parts_Product_Edit”的形状放置在第二的位置上被称为“内容”区域中的(第一的位置从0开始,由RoutablePart占用。尝试不同的位置,找一种你认为最好的样子)。 为了提高Razor模板的IntelliSense(智能感知),我们现在应该添加一个web.config项目,以及引用System.Web.Mvc组件(在Orchard源码在lib文件夹下)。 web.config看起来像这样:

相关文章
相关标签/搜索