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

上回书说到,VisualWiki系统已经基本可以运行,我们现在来考虑给他加个路径功能。举例来说,我们从Home页,点击Hello链接,进入Hello页,这时,我们希望有Home和Hello两个链接在Wiki页顶端。再点击Hello页中的Next链接,进入Next页,这时,我们希望有Home、Hello、Next三个链接在Wiki页顶端。

  需求就是这样,不过,如何实现呢?应该可以对Article设置对自己的一对多关系,那么在数据库中它们的父子关系就是确定的。不过,我却不太希望这样,对于Wiki来说,Wiki页都是独立的似乎更符合常规,那么这个路径怎么生成呢?

  考虑之后,其实这个路径信息不必保存在数据库内,而只需要在url里面就足够了。具体就是增加一个path参数,用来解析路径信息,这里面有两个选择,一是path里是路径Wiki页的名称,另一个是path里是路径Wiki页的Id,我选择了后者,多个Id之间用下划线连接。

  当然,这个改动也牵涉到GenerateShowText函数,所以先来修改它的单元测试吧,它应该增加一个path参数,当其为null时,处理方式和以前一样,否则将path加入生成的链接里:

代码
[Test]
public void TestTestGenerateShowTestWithPath()
{
    var text 
= "abc [[bb]] xyz";
    var act 
= CommonHelper.GenerateShowText(text, "1_2");
    Assert.AreEqual(
"abc <a href=\"Show.aspx?path=1_2&title=bb\">bb</a> xyz", act);
}

  恩,path也是一个常用常量了,所以也把它加入Const,修改后的GenerateShowText如下:

代码
public static string GenerateShowText(string text, string path)
{
    
return ProcessSymbol(text, "[[""]]",
        title 
=>
        {
            var url 
= new UrlBuilder("Show.aspx");
            
if (!string.IsNullOrEmpty(path))
            {
                url.Add(Const.PathName, path);
            }
            url.Add(Const.TitleName, RemoveHtmlTag(title));
            var link 
= HtmlBuilder.New.a(url.ToString()).include(title).end;
            
return link.ToString();
        });
}

  运行单元测试,全部通过,再编译Web项目,因为我们修改了GenerateShowText的参数,所以出现两个错误,现在我们在Show.aspx加入path参数,在Page_Load里把当前页面的Id加入path序列里,不过对于Home页的子页面而言,是不需要path信息的,修改后的Show.aspx的代码部分是:

代码
[HttpParameter(AllowEmpty = true)] public long? HistoryID;
[HttpParameter] 
public string title;
[HttpParameter(AllowEmpty 
= true)] public string path;

protected void Page_Load(object sender, EventArgs e)
{
    
if (HistoryID == null)
    {
        var article 
= Article.FindByTitle(title);
        
if (article != null && article.Title != Const.HomeName)
        {
            
if (string.IsNullOrEmpty(path))
            {
                path 
= article.Id.ToString();
            }
            
else
            {
                path 
+= "_" + article.Id;
            }
        }
        ContextHolder.Text
            
= article != null
            
? CommonHelper.GenerateShowText(article.Content, path)
            : 
"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 
= CommonHelper.GenerateShowText(h.Content, null);
        }
    }
}

  现在运行程序,进入Home页,编辑它以增加一个链接,点击链接,进入新页,再编辑它增加一个链接,可以卡这个链接里已经包含了path信息。现在生成链接部分已经完成,就差在Wiki页顶端显示路径了。生成这个导航栏根据的基本信息就是title和path,所以应该增加一个help函数,写个单元测试先:

 

代码
[Test]
public void TestGetNavigationBar()
{
    DbEntry.Context.DropAndCreate(
typeof(Article));
    Article.New.Init(
"Home""abc [[Hello]] xyz").Save();
    Article.New.Init(
"Hello""abc [[Next]] xyz").Save();
    Article.New.Init(
"Next""abc [[Last]] xyz").Save();

    var result 
= CommonHelper.GetNavigationBar("Home"null);
    Assert.AreEqual(
@"<a href=""Show.aspx?title=Home"">Home</a>", result);

    result 
= CommonHelper.GetNavigationBar("Hello"null);
    Assert.AreEqual(
@"<a href=""Show.aspx?title=Home"">Home</a> &gt; <a href=""Show.aspx?title=Hello"">Hello</a>", result);

    result 
= CommonHelper.GetNavigationBar("Next""2");
    Assert.AreEqual(
@"<a href=""Show.aspx?title=Home"">Home</a> &gt; <a href=""Show.aspx?title=Hello"">Hello</a> &gt; <a href=""Show.aspx?path=2&title=Next"">Hello</a>", result);

    result 
= CommonHelper.GetNavigationBar("Last""2_3");
    Assert.AreEqual(
@"<a href=""Show.aspx?title=Home"">Home</a> &gt; <a href=""Show.aspx?title=Hello"">Hello</a> &gt; <a href=""Show.aspx?path=2&title=Next"">Hello</a> &gt; <a href=""Show.aspx?path=2_3&title=Last"">Hello</a>", result);
}


   实现上有一点儿复杂,但经过一些时间的编写、修改,也就可以通过所有的测试了:

代码
public static string GetNavigationBar(string title, string path)
{
    var buildUrls 
= new StringBuilder();
    
string buildPath = "";
    buildUrls.Append(GetNavigationItem(Const.HomeName, 
null)).Append(Const.MenuSpliter);
    
if (title != null)
    {
        
if (path != null)
        {
            
string[] ss = path.Split(Const.ParameterSpliter);
            
foreach (var s in ss)
            {
                buildUrls.Append(GetNavigationItemById(s, buildPath));
                buildUrls.Append(Const.MenuSpliter);
                
if (buildPath == "")
                {
                    buildPath 
= s;
                }
                
else
                {
                    buildPath 
+= Const.ParameterSpliter + s;
                }
            }
        }
        
if (title != Const.HomeName)
        {
            buildUrls.Append(GetNavigationItem(title, path)).Append(Const.MenuSpliter);
        }
    }
    buildUrls.Length 
-= Const.MenuSpliter.Length;
    
return buildUrls.ToString();
}

private static string GetNavigationItemById(string sid, string buildPath)
{
    var id 
= long.Parse(sid);
    var article 
= Article.FindById(id);
    
return GetNavigationItem(article.Title, buildPath);
}

private static string GetNavigationItem(string title, string path)
{
    var html 
= HtmlBuilder.New;
    var url 
= new UrlBuilder("Show.aspx");
    
if (!string.IsNullOrEmpty(path))
    {
        url.Add(Const.PathName, path);
    }
    url.Add(Const.TitleName, title);
    
return html.a(url.ToString()).text(title).end.ToString();
}


  现在,我们打开Main.master,把上一次加入的Home链接,替换成一个Label控件:

<asp:Label ID="NavigationBar" runat="server" Text="Home"></asp:Label> +++++++

  再添加path参数,然后在Page_Load里添加如下的代码:

NavigationBar.Text = CommonHelper.GetNavigationBar(title, path);

  再次运行程序,一路点击Wiki页内的链接,确认页顶的导航栏都显示正确。这时,进行编辑操作,会发现可能出现路径缺失现象,因为Edit.aspx页面还没有处理path参数,我们打开Edit.aspx页面,添加path参数,然后修改生成的用于Redirect的url为:

Response.Redirect(new UrlBuilder("Show.aspx").Add(Const.PathName, path).Add(Const.TitleName, title).ToString());

  再次运行程序,仍然有路径缺失现象,发现是进入编辑页面的时候,路径就被丢弃了,所以我们修改SetLink函数,增加path参数:

代码
public static void SetLink(HyperLink link, string pageName, string linkPageName, string title, string path)
{
    
if (pageName.ToLower() == linkPageName.ToLower())
    {
        link.Enabled 
= false;
    }
    
else
    {
        link.Enabled 
= true;
        link.NavigateUrl 
= new UrlBuilder(linkPageName).Add(Const.PathName, path).Add(Const.TitleName, title).ToString();
    }
}

  再次运行程序,终于全部正常了。至此,Wiki编辑功能全部完成,只是界面还有点儿惨不忍睹,下一步我们就要进行一些界面调整,不过现在,提交代码先。目前的代码:VisualWiki5.7z

  未完待续……
posted @ 2009-12-04 21:58  梁利锋  阅读(1383)  评论(4编辑  收藏  举报