需求就是这样,不过,如何实现呢?应该可以对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);
}
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();
});
}
{
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 );
}
}
}
[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> > <a href=""Show.aspx?title=Hello"">Hello</a> " , result);
result = CommonHelper.GetNavigationBar( " Next " , " 2 " );
Assert.AreEqual( @" <a href=""Show.aspx?title=Home"">Home</a> > <a href=""Show.aspx?title=Hello"">Hello</a> > <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> > <a href=""Show.aspx?title=Hello"">Hello</a> > <a href=""Show.aspx?path=2&title=Next"">Hello</a> > <a href=""Show.aspx?path=2_3&title=Last"">Hello</a> " , result);
}
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> > <a href=""Show.aspx?title=Hello"">Hello</a> " , result);
result = CommonHelper.GetNavigationBar( " Next " , " 2 " );
Assert.AreEqual( @" <a href=""Show.aspx?title=Home"">Home</a> > <a href=""Show.aspx?title=Hello"">Hello</a> > <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> > <a href=""Show.aspx?title=Hello"">Hello</a> > <a href=""Show.aspx?path=2&title=Next"">Hello</a> > <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();
}
{
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();
}
<
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();
}
}
{
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
未完待续……