一:生成新项目

首先,要启动 Code Generation,参考《Orchard之生成新模板》。

其次,进入命令行,输入:

codegen module Tminji.Requirement

这会在解决方案中生成一个新项目,如下:

二:路由匹配

在新项目中创建 Routes.CS 文件,编码如下:

public class Routes : IRouteProvider {
    #region IRouteProvider 成员

public IEnumerable<RouteDescriptor> GetRoutes() {
        return new[] {
            new RouteDescriptor {
                Priority = 5,
                Route = new Route
                    (
                    "Requirement/{controller}/{action}/",
                    new RouteValueDictionary
                    {
                        {"area", "Tminji.Requirement"},
                        {"controller", "Home"},
                        {"action", "Index"}
                    },
                    new RouteValueDictionary(),
                    new RouteValueDictionary {{"area", "Tminji.Requirement"}},
                    new MvcRouteHandler()
                    )
            }
        };
    }

public void GetRoutes(ICollection<RouteDescriptor> routes) {
        foreach (var routeDescriptor in GetRoutes()) {
            routes.Add(routeDescriptor);
        }
    }

#endregion
}

三:新建控制器吧

接下来,就跟我们熟悉的 MVC 开发一样了,新建控制器,类似如下,可以创建视图,也可以没有视图,总之,输入 URL ,就会执行控制器代码了:

public class HomeController : Controller {
    public IOrchardServices Services { get; set; }

public HomeController(IOrchardServices services) {
        Services = services;
        T = NullLocalizer.Instance;
    }

public Localizer T { get; set; }

public ActionResult Index()
    {
        string model = "Hello World!"; 
        return View((object)model);    
    }
    public string About()
    {
        return "About me";
    }

}

四:在后台启用之

如下:

五:实效

或:

六:操作数据库

如果上面显式的文本我们要存储在数据库,那么,怎么实现?

1:创建数据库表

我们可以有两种方式来创建数据库表,一种是通过 Module 的 Update,我们需要在项目的根目录下创建一个文件 Migrations.CS,内容大致如下:

public class Migrations : DataMigrationImpl
{
    public int Create()
    {
        return 1;
    }

public int UpdateFrom1()
    {
        SchemaBuilder.CreateTable("RequirementRecord", table => table
            .ContentPartVersionRecord()
            .Column<int>("Id", column => column.PrimaryKey().Identity())
            .Column<string>("Content", column => column.WithLength(200))
        );
        ContentDefinitionManager.AlterPartDefinition("Tminji.Requirement",
            builder => builder.Attachable());
        return 2;
    }
}

这样,在我们下次登录后台的时候,就会在 Module 旁边,看到 Update,然后点击后,就会执行上述代码。

还有一种,当然是手动创建数据库表,这没有什么影响。数据库表是这样的:

2:实现后台管理这个 Content 的值

首先,我们得在 根目录下创建AdminMenu类型(备注:ORCHARD下很多命名都是固定死的,不能自己改变),如下:

public class AdminMenu : INavigationProvider {
    public Localizer T { get; set; }

#region INavigationProvider 成员

/* 指定这个菜单是一个管理菜单
     */
    public string MenuName {
        get { return "admin"; }
    }

public void GetNavigation(NavigationBuilder builder) {
        builder
            .AddImageSet("Requirement") //设置菜单图标(Orchard中默认约定调用Styles目录下的menu.xxxxxx-admin.css样式文件来显示菜单前面的图标)
            .Add(
                T("Requirement"), //菜单文本
                "5", //菜单位置(Orchard会根据这个值对菜单进行排序)
                menu => menu.Action(new RouteValueDictionary
                    {
                        {"area", "Tminji.Requirement"},
                        {"controller", "Admin"},
                        {"action", "Index"}
                    })
            );
    }
    #endregion
}

其次,我们创建 AdminController(固定死),编码如下:

public class AdminController : Controller
{
    // GET: Admin
    private readonly IRequirementService _textService;

public AdminController(IRequirementService textService)
    {
        _textService = textService;
    }

public ActionResult Index()
    {
        var viewModel = new RequirementPart();
        var textRecord = _textService.GetText();

if (textRecord != null)
        {
            viewModel.Content = textRecord.Content;
        }

return View(viewModel);
    }

[HttpPost, ActionName("Index")]
    [FormValueRequired("submit.Save")]
    public ActionResult IndexPost()
    {
        var viewModel = new RequirementPart();

if (!TryUpdateModel(viewModel))
        {
            return Index();
        }

//更新数据
        _textService.UpdateText(viewModel.Content);

return RedirectToAction("Index");
    }
}

前台代码如下:

Admin下的 index.cshtml:

@using Tminji.Requirement.Models
@model RequirementPart

<!--设置标题-->
@{ Layout.Title = T("Manage Hello World Text").ToString(); }

@Html.ValidationSummary()

@using (Html.BeginFormAntiForgeryPost())
{
    <fieldset>
        @Html.LabelFor(m => m.Content)
        @Html.TextBoxFor(m => m.Content, new { @class = "text" })
    </fieldset>
    <fieldset>
        <button class="primaryAction" type="submit" name="submit.Save" value="yes">@T("Save")</button>
    </fieldset>
}

3:数据访问层

orchard 的数据访问层是使用 nhibernate 实现的,我们同样可以把其换成 ADO.NET 的,注意上面的控制器中,存在 IRequirementService,以及隐藏存在的这个接口的一个实现类(ORCHARD)自动会为我们找到它并注入到控制器中,在这里,我们可以这样实现:

public interface IRequirementService : IDependency
{
    RequirementPart GetText();

RequirementPart UpdateText(string content);
}

[UsedImplicitly]
public class RequirementService : IRequirementService
{
    private readonly IRepository<Requirement> _textRepository;

public RequirementPartService(IRepository<Requirement> textRepository)
    {
        _textRepository = textRepository;
    }

#region ITextService 成员

public Requirement GetText()
    {
        var conn = @"Data Source=xxx;Initial Catalog=OrchardOk1;Persist Security Info=True;User ID=sa;Password=xxx";
        var sql = @"SELECT * FROM RequirementRecord";
        var ds = SqlHelper.ExecuteDataset(conn, CommandType.Text, sql, null);
        if (ds.Tables[0].Rows.Count == 0)
            return null;
        return new Requirement()
        {
            Id = (int)ds.Tables[0].Rows[0][0],
            Content = (string)ds.Tables[0].Rows[0][1]
        };
    }

public Requirement UpdateText(string content)
    {
        var conn = @"Data Source=xxx;Initial Catalog=OrchardOk1;Persist Security Info=True;User ID=sa;Password=xxx";
        string sql = "";
        var m = GetText();
        if (m == null)
        {
            sql = "INSERT INTO RequirementRecord (ID, [CONTENT]) VALUES (1, @CONTENT)";
        }
        else
        {
            sql = @"UPDATE RequirementRecord SET [CONTENT]=@CONTENT";
        }

var pms = new SqlParameter[] {
            new SqlParameter("@CONTENT", content)
        };
        SqlHelper.ExecuteNonQuery(conn, CommandType.Text, sql, pms);
        return new Requirement()
        {
            Id = 1,
            Content = content,
        };
    }

#endregion
}

至于 home/index 这里,同理,就不在赘述了。

后台管理的实效如下:

Orchard之Module开发的更多相关文章

  1. Xposed Module开发教程1

    看了一下文档,发现Xposed这货实在太强大了,它直接对Zygote做了一些手脚,简直是无所不能.缺点就是需要安装一下框架.基本原理就是把Android 系统的app_process给替换了,然后启动 ...

  2. Android Studio多Module开发需要注意的问题

    多module开发,其中的一个为入口module,其他module为独立的“应用”(library) 1.在原有的项目导入另外个项目的module为主项目的次module,即在A项目中添加一个启动B项 ...

  3. Eclipse创建Maven多模块工程Module开发(图文教程)

    自己研究了下Eclipse用Maven多模块工程Module开发,跟大家分享一下! 功能模块来分Module,跟java的package类似,一般是按照的功能模块分module,比如:sso/cas/ ...

  4. Orchard之模版开发

    生成新模版之后(参看:Orchard之生成新模板),紧接着就是模版开发了. 一:开发必备之 Shape Tracing 到了这一步,非常依赖一个工具,当然,它也是 Orchard 项目本身的一个 Mo ...

  5. 【小结】IIS7下的Http Native Module开发

    今天接到Product Manager的通知,Exchange 2007环境下的Native Module不再需要开发(详情可见上篇),但最近几天一直在做Prototype,那就做一下小结吧,总结一下 ...

  6. Orchard之Module升级

    在上一篇中,我们提到了 Migrations,这一篇稍微衍生一下. 1:Migrations 是什么 Orchard 提供了模块升级的功能,即,如果我们模块发布后,需要进行升级,我们可以通过编码来实现 ...

  7. maven module开发 自动打包

    http://blog.csdn.net/u011113713/article/details/52413903 http://blog.csdn.net/sisyphus_z/article/det ...

  8. Orchard模块开发全接触1:起步

    在<http://www.cnblogs.com/luminji/p/3831281.html>中简单介绍了 Orchard 的模块开发,接下来,我们需要做个更复杂的例子,Orchard ...

  9. Orchard模块开发全接触2:新建 ProductPart

    一:创建 Part 1:项目引用 Orchard.Framework: 2:创建 Models 文件夹: 3:在 Models 文件夹下创建类 ProductPartRecord,如下: public ...

随机推荐

  1. [转]抛弃jQuery,使用原生JavaScript

    原文链接 Document Ready 事件 在jQuery中,document.ready可以让代码在整个文档加载完毕之后执行: $(document).ready(function() { // ...

  2. SSL介绍(Secure socket Layer & Security Socket Layer)

    一个应用程序的安全需求在很大程度上依赖于将如何使用该应用程序和该应用程序将要保护什么.不过,用现有技术实现强大的. 一般用途的安全通常是可能的.认证就是一个很好的示例. 当顾客想从 Web 站点购买某 ...

  3. C++11中的右值引用及move语义编程

    C++0x中加入了右值引用,和move函数.右值引用出现之前我们只能用const引用来关联临时对象(右值)(造孽的VS可以用非const引用关联临时对象,请忽略VS),所以我们不能修临时对象的内容,右 ...

  4. Nginx 功能模块

    一.Nginx 核心功能模块 Nginx 核心功能模块负责 Nginx 的全局应用,主要对应主配置文件的 Main 区块和 Events 区块,这里有很多 Nginx 必须的全局参数配置. Nginx ...

  5. maven项目中利用jmeter-maven-plugin插件直接执行jmeter jmx脚本

    jmeter脚本需要执行脚本,先得下载jmeter并解压jmeter.如想在maven项目中通过mvn install 直接执行jmx文件,这样就能在测试服务器上通过一个命令就能执行下性能测试了,给自 ...

  6. curl 伪装来路(referer)

    curl -e http://vip.hihi.com http://test.image.ok.com/parcel/201704/1491035345125_971038.jpg 1xx.8x.3 ...

  7. Android反编译和二次打包

    参考:APK反编译 一.工具介绍: 1.解压工具 2.JDK 3.apktool: aapt.exe,apktool.bat,apktool.jar;三个在同一目录结合使用,用来反编译apk,反编译生 ...

  8. Mac下不显示设备

    使用命令行adb devices 试了下,没设备列表. 第一步: 查看usb设备信息 在 终端输入:system_profiler SPUSBDataType     可以查看连接的usb设备的信息 ...

  9. [译]Godot 引擎 GDNative 架构初探

    GDNative的架构从最早叫"DLScript"的时候到目前为止已经发生了很大的变化.随着Godot 3.0版本接近最终发布以及API越来越稳定,是时候对GDNative目前的形 ...

  10. Python 的 Magic Methods 指南(转)

    介绍 本指南是数月博客的总结.主题是魔术方法. 什么是魔术方法呢?它们是面向对象Python语言中的一切.它们是你可以自定义并添加“魔法”到类中的特殊方法.它们被双下划线环绕(比如__init__或_ ...