My Initial Bug Fixes for BlogEngine.NET 1.3

Tuesday, 15 April 2008 15:27 by snyhol

This blog is part of a series, Checklist for Starting Your Own Blog Business.

When choosing to implement an open source blog server, I figured that there would be a fair amount of customization required.  I decided to use BlogEngine.NET 1.3.  Choosing a product that is still in the 1.x versions assured that I would need to do some work with it.  It was actually fun to pop open the hood and see how this thing ran!  In the process, I learned A LOT about this software.  Of course, before putting time into making changes, I first checked the forums, the issues that have already been reported, and the classic developer database (Google)

Essentially, I just made a branched version of the source code.  When the next version of BlogEngine.NET comes out, I will have to choose between sticking with my modified BlogEngine.NET 1.3 (ignoring the new features and bug fixes made by the team) or upgrading to the newer version and then re-apply my changes.  I will probably choose to upgrade.  To help ease migration to future versions of BlogEngine, I tagged my changes with "HACK" and the date of the change.  I also kept a log of the changes I made and put that log in this blog post.

The changes detailed in this post are:

  • State Management for Search Fields
  • Include Description in Searches
  • Include My Blog Title in All Page Titles
  • Change Wording on Recent Posts Control
  • Improve Styling Support for "More..." link
  • Validate Empty Tags when Saving Posts
  • Support Posting and Editing of HTML Code 
  • Improve Styling Support for Archive Totals
  • Improve Styling Support for Error404 Page
  • Simplify the Search Results Data
  • Only Count Approved Comments in the Archive Page
  • When Saving a Comment, Use the Correct Time
  • Make Email Optional when Saving Comment
  • Only Send Comment Emails When Comments Are Approved
  • Use HTML Formatting for Comment Emails
  • RelatedPosts Control Should use Content if the Description is Blank

Whew!  That's it for now!  In the future, I'll post more about this great blog server software. 

State Management for Search Fields

When you include search fields on the sidebar, those fields do not retain their state on postback.  I was expecting the text I typed in the searchbox to stay there.  Instead, it moved to the "main" textbox in the content area of the search page.  To make the "SearchBox" sidebar control retain its state, I had to make subtle changes to almost the entire control.  I've included the whole file in the code snippet below, with unchanged regions "collapsed."  Basically, the search page retains its state using querystring values.  I modified the control with some static private variables to capture and retain the state, using a similar caching scheme as the original code and using the same variables as the Search.aspx page.  View this issue on CodePlex.

  • Project: BlogEngine.Web
  • File: App_code/Controls/SearchBox.cs
  • Method: almost all methods in the file
... Using ...
namespace Controls
{
  public class SearchBox : Control
  {
    ...
static SearchBox() ...

   
private static object _SyncRoot = new object();

   
private static string _Html;
    ...
/// <summary>  ...
    private string Html
    {
     
get
      {
       
//HACK: SN 3-23-08: Check to see if we should pre-populate the search form with querystring values.
        if (_Html == null || RebuildSearchBoxHtml())
        {
         
lock (_SyncRoot)
          {
           
//HACK: SN 3-23-08: Removed redundant code.  The null check was already done.
            //if (_Html == null)
            BuildHtml();
          }
        }

       
return _Html;
      }
    }

   
/// <summary>
    /// HACK: SN 3-23-08: Added method. Checks to see if we should pre-populate the search form with querystring values.
    /// </summary>
    /// <returns>bool, indicating that the we should rebuild the HTML for the search form</returns>
    private bool RebuildSearchBoxHtml() {
       
//SearchText is an application level constant that is populated once.
        //It can be used to check to see if the control needs to be initialized.
        if (_SearchText == null)
           
return true;

       
//If searchtext has new content (it is stored in the querystring), return true
        string searchText = Context.Request.QueryString["q"];
       
if (searchText != _SearchText)
           
return true;

       
//If "include comments" checkbox was checked (it is stored in the querystring), return true
        string check = Context.Request.QueryString["comment"] != null ? defaultCheckText : string.Empty;
       
if (check != _Check)
           
return true;

       
//If we got this far, nothing needs to be updated. return false
        return false;
    }

   
/// <summary>
    /// HACK: SN 3-23-08: Added this string property to support pre-populating the search form with querystring values.
    /// </summary>
    /// <returns>string, the prompt text to place inside the "search" HTML textbox</returns>
    private static string _SearchText;
   
private string SearchText {
       
get {
           
//by default, use the search prompt saved in the application settings
            _SearchText = BlogSettings.Instance.SearchDefaultText;

           
//use querystring searchtext if it contains new, non-default content
            string searchText = Context.Request.QueryString["q"];
           
if (searchText != null && searchText.Length > 0 && searchText != _SearchText)
                _SearchText = searchText;

           
return _SearchText;
        }
    }

   
/// <summary>
    /// HACK: SN 3-23-08: added this string property to support pre-populating the search form with querystring values
    /// </summary>
    /// <returns>string, the text that determines the initial state of the "include comments" HTML checkbox</returns>
    private static string _Check;
   
private string defaultCheckText = "checked=\"checked\"";
   
private string Check {
       
get {
            _Check = Context.Request.QueryString[
"comment"] != null ? defaultCheckText : string.Empty;
           
return _Check;
        }
    }

   
private void BuildHtml()
    {
     
StringBuilder sb = new StringBuilder();
      sb.AppendLine(
"<div id=\"searchbox\">");
      sb.Append(
"<label for=\"searchfield\" style=\"display:none\">Search</label>");

     
//HACK: SN 3-23-08: pre-populate the search textbox with querystring values if they exist
      sb.AppendFormat("<input type=\"text\" value=\"{0}\" id=\"searchfield\" onkeypress=\"if(event.keyCode==13) return Search('{1}')\" onfocus=\"SearchClear('{2}')\" onblur=\"SearchClear('{2}')\" />", SearchText, Utils.RelativeWebRoot, BlogSettings.Instance.SearchDefaultText);
      sb.AppendFormat(
"<input type=\"button\" value=\"{0}\" id=\"searchbutton\" onclick=\"Search('{1}');\" onkeypress=\"Search('{1}');\" />", BlogSettings.Instance.SearchButtonText, Utils.RelativeWebRoot);

     
if (BlogSettings.Instance.EnableCommentSearch)
      {
       
//HACK: SN 3-23-08: pre-populate the "include comments" checkbox with querystring values if they exist
        sb.AppendFormat("<br /><input type=\"checkbox\" id=\"searchcomments\" {0} />", Check);
       
if (!string.IsNullOrEmpty(BlogSettings.Instance.SearchCommentLabelText))
          sb.AppendFormat(
"<label for=\"searchcomments\">{0}</label>", BlogSettings.Instance.SearchCommentLabelText);
      }

      sb.AppendLine(
"</div>");
      _Html = sb.ToString();
    }

    ...
/// <summary>  ...
    ... public override void RenderControl(HtmlTextWriter writer) ...
  }
}

 

Include Description in Searches

There is a UX bug on the search page.  The search results show the Description for each search result.  If the Description is not available for a result, it will show the Content.  The bug is that the search engine does not search through the text in the Description field.  I noticed this bug when I ran a search and decided to filter the results.  I copied some text from a post's Description and pasted the text into the search textbox.  Since this text did not match any posts, the search returned 0 results.  I was expecting it to at least return a result for the post I copied the text from.  View this issue on CodePlex

  • Project: BlogEngine.Core
  • File: Search.cs
  • Method: BuildResultSet  
//HACK: SN: 3-23-08: Including Description matches in the search results to improve the UX. 
//This change also required the Content matching to get a higher ranking.
//  For example, while on the search page, highlight text from a description and search on that text.  Notice the results.

int titleMatches = Regex.Matches(entry.Title, regex).Count;
result.Rank = titleMatches * 20;

int postMatches = Regex.Matches(entry.Content, regex).Count;
result.Rank += postMatches * 2;

int descriptionMatches = Regex.Matches(entry.Item.Description, regex).Count;
result.Rank += descriptionMatches;

 

Include My Blog Title in All Page Titles

When someone saves a bookmark/favorite/shortcut of a page from my website, it should be branded with my site's name.   This is as simple as including the site's name in the title tag of the HTML head.  My preference is to put the site name first, then a delimiter, then the page name... something like this:

<head>
    <title>My Website: Home Page</title>
</head>

In BlogEngine.NET 1.3, the page titles are appropriately set in the codebehind for individual pages.  They are set in the Page_Load event.  However, they do not always include the blog's name in the title.  Alex and ilektran have raised similar issues. I followed the convention from default.aspx.cs to use " - " as the delimiter.  View this issue on CodePlex.  To apply the fix, I changed the Page.Title to be something like the following:

  • Project: BlogEngine.Web
  • Files: search.aspx.cs, archive.aspx.cs, contact.aspx.cs, error404.aspx.cs, post.aspx.cs
  • Method: Page_Load  
//HACK: SN: 3-23-08 include the blog name in the page title
Page.Title = Server.HtmlEncode(BlogSettings.Instance.Name) + " - " + [PAGE_NAME_HERE];

 

Change Wording on Recent Posts Control

I decided to change the wording on this sidebar control.  The star-rating verbiage originally said “rating: (rating avg) / (# raters).” I think it should be “rating: (rating avg) by (# raters) raters”. Since the verbiage was hard coded in the control, this was a code change.  Ideally, I would like to see this text put into the RESX files.  I made the change in Controls.RecentPosts | RenderPosts():

  • Project: BlogEngine.Web
  • Files: App_Code/Controls/RecentPosts.cs
  • Method: RenderPosts
//HACK: SN: 3-26-08: change verbiage of this control
string ratersString = string.Empty;
if (post.Raters != 1)
    ratersString =
"s";
string rate = string.Format("<span>{0}: {1} by {2} rater{3}</span>", Resources.labels.rating, rating, post.Raters, ratersString);

 

Improve Styling Support for "More..." link

I really like the ability to include a special tag to abbreviate the content of a post on a listing page.  However, I wanted to see the "More" link be a little bigger and more obvious to the user.  Unfortunately, the rendered HTML didn't easily support styling.  I dug into the Extensions code and "fixed" the HTML output to support CSS styling. View this issue on CodePlex.

  • Project: BlogEngine.Web
  • Files: App_Code/Extensions/BreakPost.cs
  • Method: AddMoreLink
//HACK: SN: 3-26-08: add support for CSS styling of More link
string link = "<a class=\"moreLink\" href=\"" + post.RelativeLink + "#continue\">" + Resources.labels.more + "...</a>";

 

Validate Empty Tags when Saving Posts

I noticed that the posts I published with Windows Live Writer sometimes had malformed Tags.  If the Keywords field in Windows Live Writer was blank, it would publish the post with one Keyword/Tag, which was an empty string.  I had to edit the metaweblog API to validate the tags before saving them.   I also added aggressive data scrubbing to make sure I'm not adding tags with extra spacing and to prevent saving basically empty tags that only contain white space. View this issue on CodePlex.

  • Project: BlogEngine.Core
  • File: API/MetaWeblog/MetaWeblogHandler.cs
  • Methods: NewPost, EditPost
post.Tags.Clear();
foreach (string item in sentPost.tags)
{
 
//HACK: SN: 3-26-08: Scrub out extra white space and validate the Tag data before saving it
  if (item != null && item.Trim() != string.Empty)
    post.Tags.Add(item.Trim());
}

 

Support Posting and Editing of HTML Code

Since I use Windows Live Writer to write and publish my posts, the need for a raw HTML editor didn't occur until I decided to use HTML coded characters for my About Me post.  Windows Live Writer wanted to "help me" by converting the coded characters into human readable ASCII without my permission!  It didn't matter if I used the "HTML Code" view or not.  TinyMCE did the same thing.  I needed a dumber and less helpful tool.  Something like Notepad, but with the ability to publish a blog.  jemnery raised the same issue.  With this inspiration, I built the ultimate TinyMCE replacement - a textbox! My workaround involved: edit the admin ASP.NET control to add a checkbox for toggling the TinyMCE control with a plain multiline textbox control, use javascript kicked off by the checkbox to dynamically swap the TinyMCE editor (using the TinyMCE API) with a textbox on the client side and on the server side, save the content from one or the other to the DB, depending on whether the checkbox was checked.  Another important detail was to show the textbox by default.  This was important because TinyMCE will change your HTML code on page load!  If you want to be able to edit the HTML dircetly, you cannot allow TinyMCE to be the default editor.  View this issue on CodePlex.

  • Project: BlogEngine.Web
  • File: admin/htmlEditor.ascx
  • Methods: entire file
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="htmlEditor.ascx.cs" Inherits="admin_htmlEditor" %>
<%
@ Register Src="tinyMCE.ascx" TagName="tinyMCE" TagPrefix="uc1" %>
<%
@ Import Namespace="BlogEngine.Core" %>
<asp:CheckBox Checked="true" ID="ShowPlainTextbox" runat="server" onClick="ToggleTinyMCEVisibility()" Text="Show Plain Textbox" />
<
div id="TinyMCEArea" style="display:none;"><uc1:tinyMCE ID="TinyMCE1" runat="server" /></div>
<
div id="ContentPlainTextArea">
<
span style="color:Red;">CAUTION: AutoSave will not preserve plain text content!! You must click the Save Post button to save this content!!</span>
<
asp:TextBox ID="ContentPlainText" runat="server" TextMode="MultiLine" Columns="123" Rows="15" style="color:Black;" /></div>
<
script type="text/javascript">
function
ToggleTinyMCEVisibility()
{
 
var tinyMCEArea = document.getElementById('TinyMCEArea');
 
var contentPlainTextArea = document.getElementById('ContentPlainTextArea');
 
var contentPlainText = document.getElementById('<%=ContentPlainText.ClientID%>');
 
var textBoxSwitcher = document.getElementById('<%=ShowPlainTextbox.ClientID%>');
 
if (textBoxSwitcher.checked == true) {
    contentPlainTextArea.style.display =
"block";
    tinyMCEArea.style.display =
"none";
    contentPlainText.value = tinyMCE.getContent(
'mce_editor_0');
    }
 
else{
    contentPlainTextArea.style.display =
"none";
    tinyMCEArea.style.display =
"block";
    tinyMCE.setContent(contentPlainText.value);
    }
}
</script>
  • Project: BlogEngine.Web
  • File: admin/htmlEditor.ascx.cs
  • Method: Text property
public string Text
{
   
get {
     
if (ShowPlainTextbox.Checked)
         
return ContentPlainText.Text;
     
else
          return TinyMCE1.Text;
    }
     
set {
          TinyMCE1.Text =
value;
          ContentPlainText.Text =
value;
      }
}

 

Improve Styling Support for Archive Totals

This one was pretty simple.  Just add CSS class names to some HTML elements on the Archive page to support styling. View this issue on CodePlex.

  • Project: BlogEngine.Web
  • File: archive.aspx
  • Methods: n/a
<h1>Total</h1>
<span class="archiveTotals"><asp:literal runat="server" id="ltPosts" /></span><br />
<span class="archiveTotals"><asp:literal runat="server" id="ltComments" /></span><br />
<span class="archiveTotals"><asp:literal runat="server" id="ltRaters" /></span>

 

Improve Styling Support for Error404 Page

Another styling improvement.  For the Error404 page, I added CSS classes for styling the most typically used scenario.  View this issue on CodePlex.

  • Project: BlogEngine.Web
  • File: error404.aspx
  • Methods: n/a
<div class="error404">
  <h1>Ooops! I can't find the page you're looking for</h1>
  <div id="divSearchEngine" runat="server" visible="False" class="error404search">
    <p>
      You did a search on <strong><a href="<%=Request.UrlReferrer %>"><%=Request.UrlReferrer.Host %></a></strong>
      for <strong><%=SearchTerm %></strong>. However, their index seems to be out of date.
   
</p>
    <h2>All is not lost!</h2>
    <p>I think that the following pages on my site will be able to help you:</p>
    <div id="divSearchResult" runat="server" class="error404searchresult" />
  </div>

 

Simplify the Search Results Data

To my taste, the search page results are a little funny. I decided to make the search results simpler by removing most of the blog meta-data. I prefer to just see the title + a short description and be able to click something to get to the post. I removed Categories, Tags, Keywords, and the permalink URL.  I also removed the Type if comments were not included.  This had a side effect of not differentiating Posts from Pages.  However, many users won't really care about the difference between these two forms of content - they both show a web page.  On the other hand, comments are "hidden" at the bottom of a web page.  The difference between Comments and Posts is substantial; the difference between Posts and Pages is not.  In reviewing the code from my workaround, I would also recommend wrapping the label and the contents of the Type line in stylable elements: SPAN tags with defined CSS classes.  It would also be nice to have an option in the admin pages to toggle the verbosity of the metadata display in the search results.  View this issue on CodePlex.

  • Project: BlogEngine.Web
  • File: search.aspx
  • Methods: n/a
<asp:repeater runat="server" id="rep">
  <ItemTemplate>
    <div class="searchresult">
      <a href="<%# Eval("RelativeLink") %>"><%# Eval("Title") %></a>
      <span class="type" runat="server" id="type" visible="false" />
      <span class="text"><%# GetContent((string)Eval("Description"), (string)Eval("Content")) %></span>
<%--
<!-- HACK: SN: 3-2706: remove the URL metadata from search results -->
          <span class="url"><%# ShortenUrl((String)Eval("RelativeLink")) %></span>
--
%>       
   
</div>
  </ItemTemplate>
</asp:repeater>
  • Project: BlogEngine.Web
  • File: search.aspx.cs
  • Methods: Page_Load, rep_ItemDataBound
  //HACK: SN: 3-27-08 made this be a page-level variable
  bool includeComments = false;

  #region Event handlers

 
protected void Page_Load(object sender, EventArgs e)
  {
    rep.ItemDataBound +=
new RepeaterItemEventHandler(rep_ItemDataBound);

   
if (!string.IsNullOrEmpty(Request.QueryString["q"]))
    {
     
//HACK: SN: 3-27-08 made this be a page-level variable
      includeComments = Request.QueryString["comment"] == "true";
      BindSearchResult(Request.QueryString[
"q"], includeComments);
     
//HACK: SN: 3-23-08 include the blog name in the page title
      Page.Title = Server.HtmlEncode(BlogSettings.Instance.Name) + " - " + Resources.labels.searchResultsFor + " '" + Request.QueryString["q"] + "'";
      h1Headline.InnerText = Page.Title;
    }
   
else
    {
      Page.Title = Resources.
labels.search;
      h1Headline.InnerHtml = Resources.
labels.search;
    }

   
base.AddMetaTag("description", BlogSettings.Instance.Description);
  }

 
void rep_ItemDataBound(object sender, RepeaterItemEventArgs e)
  {
     
HtmlGenericControl control = (HtmlGenericControl)e.Item.FindControl("type");

     
//HACK: SN: 3-27-08:
      //if the search does not include comments, then don't do any more processing
      //i.e. don't show the type (posts vs. pages)
      //and don't show categories, tags, or keywords
      if (!includeComments) {
         
return;
      }
     
else {
          control.Visible =
true;
      }

     
//HACK: SN: 3-27-08: make the entire line of the search result type be bold, so it stands out
      string type = "<strong>Type: {0}</strong>";
     
string categories = "<strong>" + Resources.labels.categories + "</strong> : {0}";
     
string tags = "<strong>Tags</strong> : {0}";
     
string keywords = "<strong>Keywords</strong> : {0}    ";
   
if (e.Item.DataItem is Comment)
    {
      control.InnerHtml =
string.Format(type, Resources.labels.comment);
    }
   
else if (e.Item.DataItem is Post)
    {
     
Post post = (Post)e.Item.DataItem;
     
string text = string.Format(type, Resources.labels.post);
     
//HACK: SN: 3-27-08: remove the categories and tags from search results
      //if (post.Categories.Count > 0) {
      //    string cat = string.Empty;
      //    foreach (Category category in post.Categories) {
      //        cat += category.Title + ", ";
      //    }

      //    text += "<br />" + string.Format(categories, cat.Substring(0, cat.Length - 2));
      //}

      //if (post.Tags.Count > 0) {
      //    string t = string.Empty;
      //    foreach (string tag in post.Tags) {
      //        t += tag + ", ";
      //    }

      //    text += "<br />" + string.Format(tags, t.Substring(0, t.Length - 2));
      //}

      control.InnerHtml = text;
    }
   
else if (e.Item.DataItem is BlogEngine.Core.Page)
    {
      BlogEngine.Core.
Page page = (BlogEngine.Core.Page)e.Item.DataItem;
     
string text = string.Format(type, Resources.labels.page);

     
//HACK: SN: 3-27-08: remove the keywords from search results
      //if (!string.IsNullOrEmpty(page.Keywords))
      //{
      //  text += "<br />" + string.Format(keywords, page.Keywords);
      //}

      control.InnerHtml = text;
    }
  }

  #endregion

 

Only Count Approved Comments in the Archive Page

It was odd to see the Archive page showing the comment count at 5.  Yet, when I viewed the post, there were only 3 comments.  After some debugging, I realized that it was counting all comments, while the post was only showing the approved comments.  In fixing this bug, I also fixed the incorrect comment on the Comments property of the Post class (it was advertising that the property only included Approved Comments).  View this issue on CodePlex.

  • Project: BlogEngine.Web
  • File: archive.aspx.cs
  • Method: CreateArchive
if (BlogSettings.Instance.IsCommentsEnabled)
{
 
HtmlTableCell comments = new HtmlTableCell();
 
//HACK: SN: 3-28-08: only count approved comments
  //(to be consistent with the # of comments shown on the post
  comments.InnerHtml = post.ApprovedComments.Count.ToString();
  comments.Attributes.Add(
"class", "comments");
  row.Cells.Add(comments);
}
  • Project: BlogEngine.Core
  • File: Post.cs
  • Method: Comments property
/// <summary>
/// A Collection of All Comments for the post
/// </summary>
public List<Comment> Comments
{
   
get { return _Comments; }
}

 

When Saving a Comment, Use the Correct Time

When comments were being saved, they were not using the Timezone offset defined in the admin pages. View this issue on CodePlex.

  • Project: BlogEngine.Web
  • File: User controls/CommentView.ascx.cs
  • Method: SaveComment
//HACK: SN: 3-29-08: fix the DateTime that comment was saved to comply with blog settings
comment.DateCreated = DateTime.Now.AddHours(-BlogSettings.Instance.Timezone);

 

Make Email Optional when Saving Comment

Required fields can inhibit some users from completing a form.  I don't think that someone should have to enter an email address just to make a comment on my blog.  This was an easy change to make - remove the * indicator and comment out the required field validator.

  • Project: BlogEngine.Web
  • File: User controls/CommentView.ascx
  • Method: n/a
  <label for="<%=txtEmail.ClientID %>"><%=Resources.labels.email %></label>
  <asp:TextBox runat="Server" ID="txtEmail" TabIndex="2" ValidationGroup="AddComment" />
  <span id="gravatarmsg">
  <%if (BlogSettings.Instance.Avatar != "none" && BlogSettings.Instance.Avatar != "monster"){ %>
  (<%
=string.Format(Resources.labels.willShowGravatar, "<a href=\"http://www.gravatar.com\" target=\"_blank\">Gravatar</a>")%>)
  <%} %>
 
</span>
<%--
HACK: SN: 3-29-08: make email address be an optional field... also removed the * from the label
  <asp:RequiredFieldValidator runat="server" ControlToValidate="txtEmail" ErrorMessage="Required" Display="dynamic" ValidationGroup="AddComment" />
--
%>  <asp:RegularExpressionValidator runat="server" ControlToValidate="txtEmail" ErrorMessage="Please enter a valid email" ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" ValidationGroup="AddComment" /><br />

 

Only Send Comment Emails When Comments Are Approved

When comments are moderated, the unmoderated comments should not be emailed to people who choose, "Notify me when new comments are added."  Unless a comment is approved and will be shown on the website, notification about the comment should not be sent to anyone except admins. View this issue on CodePlex.

  • Project: BlogEngine.Core
  • File: Post.cs
  • Method: ApproveComment
public void ApproveComment(Comment comment)
{
   
CancelEventArgs e = new CancelEventArgs();
   
Comment.OnApproving(comment, e);
   
if (!e.Cancel)
    {
       
int inx = Comments.IndexOf(comment);
        Comments[inx].IsApproved =
true;
        DataUpdate();
       
Comment.OnApproved(comment);
       
//HACK: SN: 3-29-08: move the SendNotifications call to happpen AFTER a comment is approved
        SendNotifications(comment);
    }
}
  • Project: BlogEngine.Core
  • File: Post.cs
  • Method: SendNotifications
//HACK: SN: 3-29-08: Only send notifications if the comment is approved
if (NotificationEmails.Count == 0 || comment.IsApproved == false)
   
return;

 

Use HTML Formatting for Comment Emails

The comment emails were formatted with plain text newline characters "/n" instead of HTML tags.  They were also using slightly less standard information than was used in the SendCommentEmail Extension.  View this issue on CodePlex

  • Project: BlogEngine.Core
  • File: Post.cs
  • Method: SendNotifications
//HACK: SN: 3-29-08: use HTML formatting of email content
//also make the email look more similar to the email sent in
//BlogEngine.Web/App_Code/Extensions/SendCommentEmail.cs
mail.Body = "Comment by " + comment.Author + "<br /><br />";
mail.Body += comment.Content.Replace(
Environment.NewLine, "<br />") + "<br /><br />";
mail.Body +=
string.Format("<a href=\"{0}\">{1}</a>", PermaLink + "#id_" + comment.Id, Title);

 

RelatedPosts Control Should use Content if the Description is Blank

The Related Posts control will include the Description if it exists.  This should be consistent with the search page and use some of the Content if the Description is blank.  Since I decided to always include a Description (or Excerpt) with my posts, this particular UX bug won't impact me.  View this issue on CodePlex.

Currently rated 5.0 by 2 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Related posts

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

July 4. 2008 06:39