修正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()方法:
/// <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".
如果标题中有上述字符还行,要是全部由非上述字符组成的话, 如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
        }

步骤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
        }


步骤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);
    }

 

posted @ 2007-06-07 17:33  MK2  阅读(1660)  评论(24编辑  收藏  举报