It was about time I migrated my weblog, based on .Text version 0.95 to a more modern blogging platform. As you will probably know, the codebase of .Text was integrated to Community Server ages ago. I doubt whether much of that original code is still alive in CS, if any at all.
Anyway, both BlogEngine.NET and dasBlog seemed like good alternatives. Subtext too. I decided to go with BlogEngine.NET. It’s not that I did extensive research on all the options, as long I was able to migrate the content and use Live Writer for posting. A post by Erik Lane helped me through it. He also posts instructions on how to keep old links working. I didn’t want to mess in the code of BlogEngine.NET, so after updating the BE.NET database, I just added the following hack to global.asax:
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
// Handle .Text rss feed requests.
if (context.Request.Url.PathAndQuery.ToLower().Contains("/rss.aspx"))
{
context.Response.Redirect("syndication.axd", false);
context.Response.StatusCode = 301;
context.Response.End();
}
// Handle .Text requests from archived posts
if (context.Request.Url.PathAndQuery.Contains("/archive/"))
{
// lookup post
int dotTextPostId = GetPostId(context.Request.Url.PathAndQuery);
System.Collections.Generic.Dictionary<int, string> posts = GetPosts();
string relativeLink = string.Empty;
if (posts.ContainsKey(dotTextPostId))
relativeLink = posts[dotTextPostId];
string redirUrl = string.Format("{0}://{1}{2}",
context.Request.Url.Scheme, context.Request.Url.Authority,
relativeLink);
context.Response.Redirect(redirUrl, false);
context.Response.StatusCode = 301;
context.Response.End();
}
}
private static readonly Regex DOTTEXT =
new Regex(@"/archive/\d{4}/\d{2}/\d{2}/(?<postId>\d+)\.aspx$",
RegexOptions.IgnoreCase | RegexOptions.Compiled);
private int GetPostId(string url)
{
Match match = DOTTEXT.Match(url);
if (match.Groups.Count > 0)
{
int postId;
if (int.TryParse(match.Groups["postId"].ToString(), out postId))
{
return postId;
}
}
return 0;
}
// Retrieve a list of old posts, cache the result
protected System.Collections.Generic.Dictionary<int, string> GetPosts()
{
System.Collections.Generic.Dictionary<int, string> posts =
HttpContext.Current.Cache["posts"] as
System.Collections.Generic.Dictionary<int, string>;
if (posts != null) return posts;
posts = new System.Collections.Generic.Dictionary<int, string>();
string query =
"SELECT PostID, DottextPostID FROM be_Posts WHERE DottextPostID IS NOT NULL";
System.Data.SqlClient.SqlDataAdapter sqlDa =
new System.Data.SqlClient.SqlDataAdapter(query,
ConfigurationManager.ConnectionStrings["BlogEngine"].ConnectionString);
System.Data.DataTable postTable = new System.Data.DataTable();
sqlDa.Fill(postTable);
foreach (System.Data.DataRow item in postTable.Rows)
{
Post p = Post.GetPost((Guid)item["PostID"]);
posts.Add(int.Parse(item["DottextPostID"].ToString()), p.RelativeLink);
}
HttpContext.Current.Cache.Add("posts", posts, null, DateTime.MaxValue,
Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
return posts;
}
It may not be the most well-designed code, but it does the trick.