DbEntry 开发实践:Wiki 系统(二)

书接上文,我们有了一个非常简单的Show.aspx,现在我们需要一个Edit.aspx页面来进行Wiki的编辑。

  新增一个Edit.aspx文件,这个页面同样接受一个title参数,这个页面上主要就是FckEditor,并且保存事件也由FckEditor提供(为了某些方便性,我修改了一些FckEditor控件的源代码,这个修改的细节就不详细说了,所以在这里请使用我提供的FckEditor控件),在这里,我们要使用这个Edit.aspx页面提供新增和修改两项功能,所以先给Article类增加一个函数SaveArticle用来处理这两种情况,不过,让我们先来写个单元测试吧。

using NUnit.Framework;
using VisualWiki.Models;

namespace VisualWiki.UnitTests
{
    [TestFixture]
    
public class TestArticle
    {
        [Test]
        
public void TestSaveArticle()
        {
            Article.SaveArticle(
"title""whatever it is");
            var o1 
= Article.FindByTitle("title");
            Assert.IsNotNull(o1);
            Assert.AreEqual(
"whatever it is", o1.Content);

            Article.SaveArticle(
"title""hello, I'm coming");
            var o2 
= Article.FindByTitle("title");
            Assert.IsNotNull(o2);
            Assert.AreEqual(
"hello, I'm coming", o2.Content);
        }
    }
}

  写单元测试,可以帮助我们测试我们的实现,帮助阅读代码,协助重构等;而先写单元测试,可以在我们考虑其实现方式之前,先考虑其用法,所以可以帮助我们实现更好用的库。我这里仍然使用的是NUnit,而不是VS自带的单元测试库,因为我发现,(至少早期来说)VS的单元测试库对于数组的比较需要自己用foreach,而NUnit可以直接用AreEqual。所以我还是用NUnit,反正只需要带一个十几K的DLL就可以了……

  恩,现在,我们有了单元测试,不过,我们还没有实现这个函数,现在我们就来实现它。如果你安装了Resharper,可以让它从单元测试的代码里,帮你建立这个函数的原型。我们实现的SaveArticle函数如下:

public static void SaveArticle(string title, string content)
{
    var o 
= FindByTitle(title);
    
if(o == null)
    {
        New.Init(title, content).Save();
    }
    
else
    {
        o.Content 
= content;
        o.Save();
    }
}

  然后,我们运行单元测试,失败了,异常信息是:Lephone.Data.DbEntry的类型初始值设定项引发异常。恩,确实,我们的单元测试还没有配置数据源呢。

  在VisualWiki.UnitTests中加入一个xml文件VisualWiki.config.xml,这个配置文件的配置项,基本上和VisualWiki中的Web.config一样,只是我这一次希望,其生成的SQL显示在单元测试的输出面板,而单元测试的输出面板直接接收Console的输出,另外,我希望Sqlite的数据库生成在系统的Temp目录下,修改后的VisualWiki.config.xml如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  
<configSections>
    
<section name="Lephone.Settings" type="Lephone.Util.Setting.NameValueSectionHandler, Lephone.Util" />
  
</configSections>
  
<Lephone.Settings>
    
<add key="SqlLogRecorder" value="Lephone.Util.Logging.ConsoleMessageRecorder, Lephone.Util" />
    
<add key="NameMapper" value="Lephone.Util.Text.InflectionNameMapper, Lephone.Util" />
    
<!-- database defination -->
    
<add key="AutoCreateTable" value="true" />
    
<add key="DataBase" value="@SQLite : @{TempDirectory}UnitTest.db"/>
    
<add key="DbProviderFactory" value="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.60.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139"/>
  
</Lephone.Settings>
</configuration>

  然后将VisualWiki.config.xml的编译方式设置为内嵌的资源,另外,我们也希望单元测试完成时删除数据库文件,所以修改TestArticle加入处理函数:

private static readonly string TestFilePath = SystemHelper.TempDirectory + "UnitTest.db";

[TearDown]
public void TearDown()
{
    File.Delete(TestFilePath);
}

  好,现在,运行单元测试,显示成功,点选单元测试项,我们还能在它的面板里看到在这个测试运行时,所生成的所有SQL语句。其实,使用Sqlite,还可以使用内存数据库来做单元测试,不过,内存数据库是连接型数据库,连接结束后,数据也就抛弃了,所以,需要我们让这个测试函数内的所有调用,都在一个连接里完成,在DbEntry里,可以用DbEntry.Context.UsingConnection来做,使用方法和UsingTransation类似。我以前以为内存数据库的速度更快,不过考虑后,我觉得,如果用于测试的数据库需要预先有N个表,每个表里还有一些测试数据的话,使用文件数据库,直接复制的方式,速度反而可能更快,DbEntry 500多个测试,有一半左右需要准备数据库,使用文件型数据库,所有单元测试运行完,只需要10秒左右。

  现在,我们已经实现了SaveArticle函数,所以我们开始编写Edit.aspx页面,除了保存Wiki内容之外,我们还希望保存之后,直接返回Show.aspx页面,所以,修改好的Edit.aspx如下:

<%@ Page Title="" Language="C#" MasterPageFile="~/Main.master" %>

<script runat="server">
    [
HttpParameterpublic string title;

    
protected void Page_Load(object sender, EventArgs e)
    {
        
if (!IsPostBack)
        {
            
var article = Article.FindByTitle(title);
            
if (article != null)
            {
                Editor.Value 
= article.Content;
            }
        }
    }

    
protected void Editor_SaveClick(object sender, EventArgs e)
    {
        Article.SaveArticle(title, Editor.Value);
        Response.Redirect(
new UrlBuilder("Show.aspx").Add("title", title).ToString());
    }
</script>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    
<fck:FCKeditor ID="Editor" runat="server" CssClass="editor" BasePath="~/fckeditor/"
        Height
="100%" onsaveclick="Editor_SaveClick">
    
</fck:FCKeditor>
</asp:Content>

  然后我们在VisualWiki的目录下建立fckeditor目录,把FckEditor的相关文件复制到这个目录下,现在,从Edit.aspx运行程序,显示一个异常:The Parameter title can't be empty。恩,在url后加上参数?title=test,然后回车,显示出FckEditor的编辑界面,只是高度有点儿小,随便输入一些内容,点击FckEditor上的保存按钮,页面返回Show.aspx,并且显示了刚才我们编辑的内容。把url中的Show修改为Edit,然后回车,我们又进入了编辑界面,这一次,编辑框里已经有了我们刚才编辑的内容,修改一下,再点击保存按钮,我们回到了Show页面,它也显示出了我们编辑后的内容。

  现在,我们来编辑一下Main.master,用以提供一个Edit链接。母板页也需要title参数,所以先设置它从Lephone.Web.SmartMasterPageBase继承,以便使用HttpParameter,然后添加一个Edit的HyperLink控件,在Page_Load里对这个链接控件进行一些设置,修改后的Main.master如下:

<%@ Master Language="C#" Inherits="Lephone.Web.SmartMasterPageBase" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    [
HttpParameterpublic string title;
    
    
protected void Page_Load(object sender, EventArgs e)
    {
        
var pageName = Request.Url.Segments[2].ToLower();
        
if(pageName == "edit.aspx")
        {
            Edit.Enabled 
= false;
        }
        
else
        {
            Edit.Enabled 
= true;
            Edit.NavigateUrl 
= new UrlBuilder("Edit.aspx").Add("title", title).ToString();
        }
    }
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    
<title></title>
    
<asp:ContentPlaceHolder id="head" runat="server">
    
</asp:ContentPlaceHolder>
</head>
<body>
    
<form id="form1" runat="server">
    
<div>
        
<asp:HyperLink ID="Edit" runat="server">Edit</asp:HyperLink>
        
<br /><hr />
        
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
        
</asp:ContentPlaceHolder>
    
</div>
    
</form>
</body>
</html>

  再次从Show.aspx运行程序,添加参数?title=test,页面显示文章test,点击顶部的Edit链接,进入编辑页面,编辑之后,点击保存,回到显示页。

  至此,VisualWiki项目已经可以进行可视化的新建、编辑操作,我们还需要进行很多的工作以便让它完成所有需求。不过现在,把它提交到SVN库里先。目前的源代码可以在这里下载:VisualWiki2.7z

  未完待续……
posted @ 2009-12-01 20:32  梁利锋  阅读(2139)  评论(11编辑  收藏  举报