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

书接上文,我们有了Show.aspx和Edit.aspx页面,现在应该开发历史记录功能了。

  不过,在做这个之前,我们先加入一个Default.aspx,用来转向到有参数的Show.aspx页面,省得每次要自己输入title参数:

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

<script runat="server">
    protected 
void Page_Load(object sender, EventArgs e)
    {
        Response.Redirect(
new UrlBuilder("Show.aspx").Add("title""Home").ToString());
    }
</script>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
</asp:Content>

  现在,我们来考虑历史记录问题。一般来说,我们只工作在最新的Wiki页之上,所以,我们需要另一个表来保存历史数据,就叫ArticleHistory吧,它和Article应该是一对多关系,隶属于Article,而且,它的Init方法应该接受一个Article作为参数,所以,代码如下:

代码
namespace VisualWiki.Models
{
    
public abstract class ArticleHistory : LinqObjectModel<ArticleHistory>
    {
        
public abstract string Content { getset; }

        [Index(ASC 
= false)]
        
public abstract DateTime CreatedOn { getset; }

        [BelongsTo]
        
public abstract Article Article { getset; }

        
public ArticleHistory Init(Article article)
        {
            Content 
= article.Content;
            CreatedOn 
= article.SavedOn;
            
return this;
        }
    }
}


  Article类也需要相应的修改,应该增加HasMany的ArticleHistory列表:

[HasMany(OrderBy = "CreatedOn DESC, Id DESC")]
public abstract IList<ArticleHistory> History { getset; }


  然后,在SaveArticle函数里,应该同时保存历史数据,既然SaveArticle函数需要修改,我们还是先来修改单元测试吧:

代码
[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);
    Assert.AreEqual(
0, o1.History.Count);

    Article.SaveArticle(
"title""hello, I'm coming");
    var o2 
= Article.FindByTitle("title");
    Assert.IsNotNull(o2);
    Assert.AreEqual(
"hello, I'm coming", o2.Content);
    Assert.AreEqual(
1, o2.History.Count);
    Assert.AreEqual(
"whatever it is", o2.History[0].Content);
}


  现在运行单元测试,显示失败,我们修改SaveArticle函数如下:

代码
public static void SaveArticle(string title, string content)
{
    var article 
= FindByTitle(title);
    
if(article == null)
    {
        article 
= New.Init(title, content);
    }
    
else
    {
        article.History.Add(ArticleHistory.New.Init(article));
        article.Content 
= content;
    }
    article.Save();
}

  再次运行单元测试,显示成功,业务逻辑正确。现在我们需要一个页面来显示历史,这个历史页面,同样接受一个title参数,而且使用GridView来显示其创建时间,并给出一个链接,用以阅读历史页面,Show页面就很好,只要多接受一个版本参数就可以了。说到GridView,我们首先需要使用DbEntryDataSource,先在VisualWiki.Models里建立一个DataSources目录,然后创建ArticleHistoryDataSource:

namespace VisualWiki.Models.DataSources
{
    
public class ArticleHistoryDataSource : DbEntryDataSource<ArticleHistory>
    {
    }
}

  然后在VisualWiki项目下创建History.aspx页面,修改其代码如下:

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

<script runat="server">
    [HttpParameter] public string title;
    
    protected 
void Page_Load(object sender, EventArgs e)
    {
        
var article = Article.FindByTitle(title);
        
if(article != null)
        {
            ArticleHistoryDataSource1.AddAndCondition(p 
=> p.Article.Id == article.Id);
        }
        
        
var hlf = (HyperLinkField) HistoryList.Columns[HistoryList.Columns.Count - 1];
        hlf.DataNavigateUrlFormatString 
= new UrlBuilder("~/Show.aspx").Add("title", title) + "&HistoryID={0}";
    }
</script>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    
<asp:GridView ID="HistoryList" runat="server" AllowPaging="True"
        AutoGenerateColumns
="False" BackColor="White" BorderColor="#E7E7FF"
        BorderStyle
="None" BorderWidth="1px" CellPadding="3" DataKeyNames="Id"
        DataSourceID
="ArticleHistoryDataSource1" GridLines="Horizontal"
        EmptyDataText
="Can't find any items.">
        
<RowStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" />
        
<Columns>
            
<asp:BoundField DataField="CreatedOn" HeaderText="Created On"
                SortExpression
="CreatedOn" />
            
<asp:HyperLinkField Text="Show" DataNavigateUrlFields="Id"
                DataNavigateUrlFormatString
="~/Show.aspx?HistoryID={0}" >
            
</asp:HyperLinkField>
        
</Columns>
        
<FooterStyle BackColor="#B5C7DE" ForeColor="#4A3C8C" />
        
<PagerStyle BackColor="#E7E7FF" ForeColor="#4A3C8C" HorizontalAlign="Right" />
        
<SelectedRowStyle BackColor="#738A9C" Font-Bold="True" ForeColor="#F7F7F7" />
        
<HeaderStyle BackColor="#4A3C8C" Font-Bold="True" ForeColor="#F7F7F7" />
        
<AlternatingRowStyle BackColor="#F7F7F7" />
    
</asp:GridView>
    
    
<biz:ArticleHistoryDataSource ID="ArticleHistoryDataSource1" runat="server" DefaultOrderBy="CreatedOn DESC, Id DESC" />
</asp:Content>

  运行程序,编辑Home页面几次,然后,将url里的Show修改为History,回车,就看到了我们的编辑历史了。当然,现在点击GridView里的Show链接,显示的仍然是最新的Wiki页面,所以,我们来修改一下Show.aspx,增加HistoryID参数:

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

<script runat="server">
    [HttpParameter(AllowEmpty 
= true)] public long? HistoryID;
    [HttpParameter] public string title;

    protected 
void Page_Load(object sender, EventArgs e)
    {
        
if (HistoryID == null)
        {
            
var article = Article.FindByTitle(title);
            ContextHolder.Text
                
= article != null
                
? article.Content
                : 
"The wiki page does not exist.  The page will be created the first time you edit it. ";
        }
        
else
        {
            
var h = ArticleHistory.FindById(HistoryID.Value);
            
if(h != null)
            {
                ContextHolder.Text 
= h.Content;
            }
        }
    }
</script>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    
<asp:Label ID="ContextHolder" runat="server" Text=""></asp:Label>
</asp:Content>

  现在,重新运行程序,确认Show页面已经可以按照HistoryID正确的显示历史数据。恩,总是修改url也不是办法,我们还是修改一下Main.master,加入Histroy链接吧:

代码
<%@ 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">
    [HttpParameter] public 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();
        }
        
if(pageName == "history.aspx")
        {
            History.Enabled 
= false;
        }
        
else
        {
            History.Enabled 
= true;
            History.NavigateUrl 
= new UrlBuilder("History.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> |
        
<asp:HyperLink ID="History" runat="server">History</asp:HyperLink>
        
<br /><hr />
        
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
        
</asp:ContentPlaceHolder>
    
</div>
    
</form>
</body>
</html>

  咳咳,我们在写重复的代码了,看来需要小小的重构一下,不过在那之前,先把修改提交到SVN吧。目前的源代码可以在这里下载:VisualWiki3.7z

  未完待续……
posted @ 2009-12-02 20:18  梁利锋  阅读(1650)  评论(9编辑  收藏  举报