修正BlogEngine.Net中的使用全中文为标题的链接问题(在1.1以上版本此问题已被修复)
PS: 本文只针对BlogEngine.Net 1.0 有效!!!在1.1以上版本,已经不存在这个问题了. 可到此下载最新版本:Download
在BlogEngine.Net 1.0中, Post的链接是根据Post.Title来判断的, 获取Post的相对Uri属性RelativeLink时, 关键语句是Utils.RemoveIlegalCharacters(Title),我们先看看RemoveIlegalCharacters()方法:
如果标题中有上述字符还行,要是全部由非上述字符组成的话, 如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属性的实现:
步骤2: 打开UrlRewrite.cs, 修改RewritePost()方法:
在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);
}