在BlogEngine.Net 1.0中, Post的連結是根據Post.Title來判斷的, 獲取Post的相對Uri屬性RelativeLink時, 關鍵語句是Utils.RemoveIlegalCharacters(Title),我們先看看RemoveIlegalCharacters()方法:
/// <summary>
/// Strips all illegal characters from the specified title.
/// </summary>
public static string RemoveIlegalCharacters(string text)
{
if (string.IsNullOrEmpty(text))
return text;
StringBuilder sb = new StringBuilder();
text = text.Replace(" ", "-");
foreach (char c in text)
{
if (IsAllowedCharacter(c))
sb.Append(c);
}
return sb.ToString();
}
private static bool IsAllowedCharacter(char character)
{
string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
foreach (char c in allowedChars)
{
if (c == character)
return true;
}
return false;
}
由上面的程式碼可看見, 如果不是"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" 這些字元的, 該字元將被忽略掉,如我們輸入標題: 中文Abc, 進行Utils.RemoveIlegalCharacters("中文Abc")後, 只會得到"Abc", 這樣我們看到的連結將是"/post/Abc.aspx". /// Strips all illegal characters from the specified title.
/// </summary>
public static string RemoveIlegalCharacters(string text)
{
if (string.IsNullOrEmpty(text))
return text;
StringBuilder sb = new StringBuilder();
text = text.Replace(" ", "-");
foreach (char c in text)
{
if (IsAllowedCharacter(c))
sb.Append(c);
}
return sb.ToString();
}
private static bool IsAllowedCharacter(char character)
{
string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-";
foreach (char c in allowedChars)
{
if (c == character)
return true;
}
return false;
}
如果標題中有上述字元還行,要是全部由非上述字元組成的話, 如Utils.RemoveIlegalCharacters("中文標題"), 看到的連結將會是"/post/.aspx", 當有兩篇全中文標題的Post時, 之前的那篇Post將不能被連結到.
為了這個解決這個問題, 我作了一些修改, 思路大概如下:
1. 當標題中包含"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"這類字元時, 按原方式進行;
2. 當標題由非""abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-" 字元組成的, 則使用Post.Id進行連結, 連結的形式如: "/post/a9d8c39d-c731-43bc-9ac6-faeafcfe0fcf.aspx".
修改步驟1: 在開啟BlogEngine.Net的原始碼Post.cs, 修改 RelativeLink屬性的實現:
/// <summary>
/// A relative-to-the-site-root path to the post.
/// Only for in-site use.
/// </summary>
public Uri RelativeLink
{
//get { return new Uri(VirtualPathUtility.ToAbsolute("~/post/" + Utils.RemoveIlegalCharacters(Title) + ".aspx"), UriKind.Relative); }
//當標題全部字元都是非ASCII碼字元時,URL形式為: /post/a9d8c39d-c731-43bc-9ac6-faeafcfe0fcf.aspx
//其中a9d8c39d-c731-43bc-9ac6-faeafcfe0fcf是Post的Id的字串形式
//改進,支援非ASCII碼字元標題 --Start
get
{
string link = Utils.RemoveIlegalCharacters(Title);
if (link.Length == 0)
{
return new Uri(VirtualPathUtility.ToAbsolute("~/post/" + Id.ToString() + ".aspx"), UriKind.Relative);
}
return new Uri(VirtualPathUtility.ToAbsolute("~/post/" + link + ".aspx"), UriKind.Relative);
}
//改進,支援非ASCII碼字元標題 --End
}
/// A relative-to-the-site-root path to the post.
/// Only for in-site use.
/// </summary>
public Uri RelativeLink
{
//get { return new Uri(VirtualPathUtility.ToAbsolute("~/post/" + Utils.RemoveIlegalCharacters(Title) + ".aspx"), UriKind.Relative); }
//當標題全部字元都是非ASCII碼字元時,URL形式為: /post/a9d8c39d-c731-43bc-9ac6-faeafcfe0fcf.aspx
//其中a9d8c39d-c731-43bc-9ac6-faeafcfe0fcf是Post的Id的字串形式
//改進,支援非ASCII碼字元標題 --Start
get
{
string link = Utils.RemoveIlegalCharacters(Title);
if (link.Length == 0)
{
return new Uri(VirtualPathUtility.ToAbsolute("~/post/" + Id.ToString() + ".aspx"), UriKind.Relative);
}
return new Uri(VirtualPathUtility.ToAbsolute("~/post/" + link + ".aspx"), UriKind.Relative);
}
//改進,支援非ASCII碼字元標題 --End
}
步驟2: 開啟UrlRewrite.cs, 修改RewritePost()方法:
private static void RewritePost(HttpContext context)
{
//string title = ExtractTitle(context, "/post/");
//Post post = Post.GetPostByName(title);
//if (post != null)
// context.RewritePath("~/post.aspx?id=" + post.Id.ToString() + GetQueryString(context), false);
//當標題全部字元都是非ASCII碼字元時,URL形式為: /post/a9d8c39d-c731-43bc-9ac6-faeafcfe0fcf.aspx
//其中a9d8c39d-c731-43bc-9ac6-faeafcfe0fcf是Post的Id的字串形式
//改進,支援非ASCII碼字元標題 --Start
string title = ExtractTitle(context, "/post/");
Post post = Post.GetPostByName(title);
if (post != null)
{
context.RewritePath("~/post.aspx?id=" + post.Id.ToString() + GetQueryString(context), false);
return;
}
post = Post.GetPost(new Guid(title));
if (post != null)
{
context.RewritePath("~/post.aspx?id=" + post.Id.ToString() + GetQueryString(context), false);
}
//改進,支援非ASCII碼字元標題 --End
}
{
//string title = ExtractTitle(context, "/post/");
//Post post = Post.GetPostByName(title);
//if (post != null)
// context.RewritePath("~/post.aspx?id=" + post.Id.ToString() + GetQueryString(context), false);
//當標題全部字元都是非ASCII碼字元時,URL形式為: /post/a9d8c39d-c731-43bc-9ac6-faeafcfe0fcf.aspx
//其中a9d8c39d-c731-43bc-9ac6-faeafcfe0fcf是Post的Id的字串形式
//改進,支援非ASCII碼字元標題 --Start
string title = ExtractTitle(context, "/post/");
Post post = Post.GetPostByName(title);
if (post != null)
{
context.RewritePath("~/post.aspx?id=" + post.Id.ToString() + GetQueryString(context), false);
return;
}
post = Post.GetPost(new Guid(title));
if (post != null)
{
context.RewritePath("~/post.aspx?id=" + post.Id.ToString() + GetQueryString(context), false);
}
//改進,支援非ASCII碼字元標題 --End
}
步驟3: 重新編譯, 執行並測試:
成功!!!
類似地, 還可以修改Category, Tag等等....
希望這篇文章對你有用.
PS: 1.1版本已經修復了Title和Category的中文連結問題, 而Tag的中文連結問題的修復方法:
修改App_Code/Controls/TagCloud.cs中的RenderControl()方法替換成如下方法即可.
/// <summary>
/// Renders the control.
/// </summary>
public override void RenderControl(HtmlTextWriter writer)
{
writer.Write("<ul id=\"tagcloud\">");
foreach (string key in WeightedList.Keys)
{
writer.Write("<li>");
writer.Write(string.Format(LINK, Utils.RelativeWebRoot + "?tag=/" + HttpUtility.UrlEncode(key), WeightedList[key], "Tag: " + key, key));
writer.Write("</li>");
}
writer.Write("</ul>");
writer.Write(Environment.NewLine);
}