Feature Request: Featured Articles Widget

Topics: Controls
Mar 30, 2009 at 4:03 PM
What would be nice from BE.NET is a widget that could show titles and excerpts from 2 or 3 "featured" articles.  Sometimes, bloggers may want to showcase their best work on the sidebar, and having this sort of thing will help them.

...Matt
Apr 3, 2009 at 5:17 PM
Hi Matt..
  I don't know if this is what u like, but u could have a look to this template...

http://www.onesoft.dk/post/arthemia-theme-ready-for-BlogEngine.aspx 

this is an interesting solution...

Ciao

Alessandro
Apr 7, 2009 at 9:20 PM
This would require me to change my theme.

I may just have to write a widget myself :)

...Matt
Apr 8, 2009 at 8:03 PM
Ok.  I've done it.  A featured post widget which can be used to highlight or "feature" as many posts as the user wants.

http://www.insidercoding.com/post/2009/04/08/BlogEngineNET-Widget-Featured-Posts.aspx
Apr 9, 2009 at 9:06 AM
Hi I'm tryinmg your widget but getting errors
I get the following error (sorry for translating the second part... the error was in italian):

Widget Featured Posts not found.
"Reference to an object not set up on object request"

if I dont insert any slugs the widget show the expected message

When I insert the slug I get that and I can't renmove the widget

I'm using the inove template...

thanks

Apr 9, 2009 at 2:01 PM
Hi paologalli,

In the App_Data/datastore/widgets/... directory is an Xml file with the configuration for the Featured Posts.  Can you send this to me?

...Matt
Apr 9, 2009 at 2:17 PM
here it comes...

<?xml version="1.0" encoding="utf-8"?>
<SerializableStringDictionary>
  <SerializableStringDictionary>
    <DictionaryEntry Key="slugs" Value="Pubblicita-e-Web-quali-orizzonti" />
  </SerializableStringDictionary>
</SerializableStringDictionary>
Apr 9, 2009 at 2:30 PM
What version of BE.NET are you using?

...Matt
Apr 9, 2009 at 3:00 PM
And can you post a link to your blog?  I'd like to see the article that you're featuring.
Apr 9, 2009 at 3:07 PM
Unfortunately the widget is on my local machine and not in production

I saw that the slug is correct and that the post exist in to the
\App_Data\posts directory
Apr 9, 2009 at 3:11 PM
Can you send me the xml file for the post? Maybe there is something specific in the post that's causing issues.
Apr 9, 2009 at 3:29 PM
uhm...  I also tried with different posts, anyway here it comes. thanks

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<post>
  <author>Paolo</author>
  <title>Pubblicità e Web: quali orizzonti?</title>
  <description />
  <content>&lt;p&gt;
Articolo interessante di &lt;strong&gt;Luca De Biase&lt;/strong&gt; sugli scenari futuri legati a web e fonti di remunerazione...
&lt;/p&gt;
 
&lt;blockquote&gt;
       
    &lt;p&gt;
    &lt;em&gt;La pubblicit&amp;agrave; online &amp;egrave; cresciuta molto negli ultimi anni. Pu&amp;ograve; anche continuare a farlo, anche se qualche segno di cedimento si &amp;egrave; gi&amp;agrave; visto (novembre scorso ha segnato addirittura un lieve arretramento).&lt;/em&gt;
    &lt;/p&gt;
        
    &lt;p&gt;
    &lt;em&gt;Di certo, non pu&amp;ograve; rimpiazzare ogni modello di business basato sulla vendita di prodotti e servizi. Non pu&amp;ograve; rimpiazzare tutta la vendita di software, tutta la musica, tutta l&amp;#39;informazione.&lt;/em&gt;
    &lt;/p&gt;
        
    &lt;p&gt;
    &lt;em&gt;Anche perch&amp;eacute; la pubblicit&amp;agrave; ha un effetto incentivante per la quantit&amp;agrave; di traffico, non necessariamente per la qualit&amp;agrave; dell&amp;#39;attenzione che il pubblico dedica ai contenuti. Dopo la mania di rielaborare ogni modello di business in funzione della pubblicit&amp;agrave; che cosa si pu&amp;ograve; pensare?&lt;/em&gt;
    &lt;/p&gt;
    
&lt;/blockquote&gt;
 
&lt;p&gt;
&lt;a href="http://blog.debiase.com/2009/03/dopo-la-pubblicita.html"&gt;Leggetevi il suo post&lt;/a&gt; e meditateci sopra... personalmente lo condivido. La pubblicit&amp;agrave; aiuta nel medio-breve periodo. Se per&amp;ograve; non esiste un modello di business alternativo e valido non c&amp;#39;&amp;egrave; futuro. Di qualunque iniziativa si tratti e qualunque gruppo economico abbia alle spalle.
&lt;/p&gt;
 
&lt;p&gt;
Il difficile, in questo momento soprattutto, &amp;egrave; trovare un modello di business che non cozzi con il tentativo delle persone di trovare vie pi&amp;ugrave; economiche per vivere o lavorare.
&lt;/p&gt;
 
&lt;p&gt;
Vale a dire: se il tuo servizio &amp;egrave; di qualit&amp;agrave; ma qualcun altro a costi inferiori o con modelli economici diversi e pi&amp;ugrave; aggressivi offre cose paragonabili (o anche inferiori ma non scadenti) alle tue... allora sono dolori. Assomiglia a un circolo vizioso da cui uscire sembra impossibile... ma occorre trovare una via. Io ci sto pensando... se mi viene un&amp;#39;idea fenomenale vi avviso ;)
&lt;/p&gt;
</content>
  <ispublished>True</ispublished>
  <iscommentsenabled>True</iscommentsenabled>
  <pubDate>2009-03-23 12:19:00</pubDate>
  <lastModified>2009-03-23 12:20:13</lastModified>
  <raters>1</raters>
  <rating>5</rating>
  <slug>Pubblicita-e-Web-quali-orizzonti</slug>
  <tags>
    <tag>web</tag>
    <tag>pubblicità</tag>
  </tags>
  <comments />
  <categories>
    <category>81eb13d5-456f-42a0-b940-9f44c5002d33</category>
  </categories>
  <notifications />
</post>
Apr 9, 2009 at 4:21 PM
Edited Apr 9, 2009 at 6:16 PM

Below is a new Widget.aspx.cs file.  Please replace it in the Featured Posts directory and try again.  If it still fails, please send me App_Data/FeaturedPosts_Log.txt

//==File Begins==

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Web.Caching;
using System.Xml;
using System.IO;
using System.Text;
using BlogEngine.Core;

// Featured Post Widget for BlogEngine.NET 1.4.5
// Written by Matt Houser
// http://www.insidercoding.com
public partial class widgets_FeaturedPosts_widget : WidgetBase
{
 public static void RecordLog(string msg)
 {
  string log = DateTime.Now.ToString() + ":" + msg + "\r\n";

  string logFile = System.IO.Path.Combine(BlogSettings.Instance.StorageLocation, "FeaturePosts_Log.txt");
  logFile = System.Web.Hosting.HostingEnvironment.MapPath(logFile);

  System.IO.File.AppendAllText(logFile, log);
 }

 // LoadWidget
 //
 // Called when the widget is loaded (obviously).
 // Get the slug list from the widget's settings.
 // Split the slug list from a string into a true list.
 // Collect the list of posts whose slug is in the slug list.
 // Render the posts.
 public override void LoadWidget()
 {
  RecordLog("LoadWidget Begins");
  StringDictionary settings = GetSettings();

  string sSlugs = settings["slugs"];
  if (sSlugs == null)
   RecordLog("Slugs is null");
  List<string> postsToFeature = new List<string>();

  if (!String.IsNullOrEmpty(sSlugs))
  {
   RecordLog("sSlugs is NOT IsNullOrEmpty");
   string[] arr = sSlugs.Split('\n', '\r');
   RecordLog(String.Format("arr.Length = {0}", arr.Length));
   foreach (string s in arr)
   {
    RecordLog(s);
    string sTrim = s.Trim();
    if (!String.IsNullOrEmpty(sTrim))
     postsToFeature.Add(sTrim);
   }
   RecordLog("Done Parsing");
  }

  RecordLog("Before Findall");
  List<Post> posts = Post.Posts.FindAll(delegate(Post p)
   {
    return postsToFeature.Contains(p.Slug);
   });
  RecordLog("After Findall");

  RecordLog("Before RenderPosts");
  string content = RenderPosts(posts, settings);
  RecordLog("After RenderPosts");

  LiteralControl html = new LiteralControl(content);
  phPosts.Controls.Add(html);
  RecordLog("LoadWidget Ends");
 }

 // RenderPosts
 //
 // Called to render the posts into HTML.
 // If there are no posts, send "<p>None</p>" (localized).
 // Create the initial span open tag.
 // For each visible post, create an excerpt from the article's
 // description, or create one our own way.
 // Piece together the HTML for this post.
 // Append the span's closing tag.
 private string RenderPosts(List<Post> posts, StringDictionary settings)
 {
  RecordLog("RenderPosts Begins");
  if (posts.Count == 0)
  {
   RecordLog("posts.Count == 0");
   return "<p>" + Resources.labels.none + "</p>";
  }

  StringBuilder sb = new StringBuilder();
  sb.Append("<span class=\"featuredPosts\" id=\"featuredPosts\">");

  foreach (Post post in posts)
  {
   RecordLog("Post");
   if (!post.IsVisible)
    continue;
   //if (!post.IsPublished)
   // continue;

   RecordLog("post.Description");
   string sExcerpt = post.Description;
   if (String.IsNullOrEmpty(sExcerpt))
    sExcerpt = CreateExcerpt(post.Content);
   RecordLog("post.Author");
   string sAuthor = post.Author;
   RecordLog("post.AuthorProfile.RelativeLink");
   string sAuthorLink = null;
   if (post.AuthorProfile != null)
    sAuthorLink = post.AuthorProfile.RelativeLink;
   RecordLog("post.DateCreated.ToShortDateString()");
   string sDate = post.DateCreated.ToShortDateString();

   RecordLog("Author Code");
   string sAuthorCode = sAuthor;
   if (sAuthorLink != null)
   {
    RecordLog("Not Null");
    sAuthorCode = String.Format("<a href=\"{1}\">{0}</a>", sAuthor, sAuthorLink);
   }

   string sHtml = "<p class=\"title\"><a href=\"{0}\">{1}</a></p><p class=\"post-info\">Posted by {3} on {4}</p><p class=\"text\">{2}</p>";
   RecordLog("sb.AppendFormat");
   sb.AppendFormat(sHtml, post.RelativeLink, HttpUtility.HtmlEncode(post.Title), sExcerpt, sAuthorCode, sDate);
   RecordLog("Done loop");
  }

  sb.Append("</span>");
  RecordLog("RenderPosts Ends");
  return sb.ToString();
 }

 // CreateExcerpt
 //
 // Called to create a short excerpt from the contents of
 // the article.
 // Strip out the HTML.
 // If the article is short, then exit, otherwise
 // use the first 250 characters.
 private string CreateExcerpt(string sContent)
 {
  RecordLog("CreateExcerpt Begins");
  string sText = Utils.StripHtml(sContent);

  if (sText.Length <= 250)
  {
   RecordLog("CreateExcerpt Ends early");
   return sText;
  }

  sText = sText.Substring(0, 250) + "...";
  RecordLog("CreateExcerpt Ends");
  return sText;
 }

 // Name
 //
 // Fixed name for the widget.  Must match
 // the sub-folder that contains the widget code
 // otherwise bad things happen.
 // This also ends up being the default title
 // for the widget.
 public override string Name
 {
  get { return "Featured Posts"; }
 }

 // IsEditable
 //
 // Our widget is editable, so return true
 public override bool IsEditable
 {
  get { return true; }
 }

}

//==File Ends==

Apr 9, 2009 at 6:03 PM
thanks but it doesn't work...

09/04/2009 20.00.04:LoadWidget Begins
09/04/2009 20.00.04:sSlugs is NOT IsNullOrEmpty
09/04/2009 20.00.04:arr.Length = 1
09/04/2009 20.00.04:Pubblicita-e-Web-quali-orizzonti
09/04/2009 20.00.04:Done Parsing
09/04/2009 20.00.04:Before Findall
09/04/2009 20.00.04:After Findall
09/04/2009 20.00.04:Before RenderPosts
09/04/2009 20.00.04:RenderPosts Begins
09/04/2009 20.00.04:Post
09/04/2009 20.00.04:post.Description
09/04/2009 20.00.04:CreateExcerpt Begins
09/04/2009 20.00.04:CreateExcerpt Ends
09/04/2009 20.00.04:post.Author
09/04/2009 20.00.04:post.AuthorProfile.RelativeLink
09/04/2009 20.00.14:LoadWidget Begins
09/04/2009 20.00.14:sSlugs is NOT IsNullOrEmpty
09/04/2009 20.00.14:arr.Length = 1
09/04/2009 20.00.14:Pubblicita-e-Web-quali-orizzonti
09/04/2009 20.00.14:Done Parsing
09/04/2009 20.00.14:Before Findall
09/04/2009 20.00.14:After Findall
09/04/2009 20.00.14:Before RenderPosts
09/04/2009 20.00.14:RenderPosts Begins
09/04/2009 20.00.14:Post
09/04/2009 20.00.14:post.Description
09/04/2009 20.00.14:CreateExcerpt Begins
09/04/2009 20.00.14:CreateExcerpt Ends
09/04/2009 20.00.14:post.Author
09/04/2009 20.00.14:post.AuthorProfile.RelativeLink
09/04/2009 20.00.22:LoadWidget Begins
09/04/2009 20.00.22:sSlugs is NOT IsNullOrEmpty
09/04/2009 20.00.22:arr.Length = 1
09/04/2009 20.00.22:Pubblicita-e-Web-quali-orizzonti
09/04/2009 20.00.22:Done Parsing
09/04/2009 20.00.22:Before Findall
09/04/2009 20.00.22:After Findall
09/04/2009 20.00.22:Before RenderPosts
09/04/2009 20.00.22:RenderPosts Begins
09/04/2009 20.00.22:Post
09/04/2009 20.00.22:post.Description
09/04/2009 20.00.22:CreateExcerpt Begins
09/04/2009 20.00.22:CreateExcerpt Ends
09/04/2009 20.00.22:post.Author
09/04/2009 20.00.22:post.AuthorProfile.RelativeLink
09/04/2009 20.00.22:LoadWidget Begins
09/04/2009 20.00.22:sSlugs is NOT IsNullOrEmpty
09/04/2009 20.00.22:arr.Length = 1
09/04/2009 20.00.22:Pubblicita-e-Web-quali-orizzonti
09/04/2009 20.00.22:Done Parsing
09/04/2009 20.00.22:Before Findall
09/04/2009 20.00.22:After Findall
09/04/2009 20.00.22:Before RenderPosts
09/04/2009 20.00.22:RenderPosts Begins
09/04/2009 20.00.22:Post
09/04/2009 20.00.22:post.Description
09/04/2009 20.00.22:CreateExcerpt Begins
09/04/2009 20.00.22:CreateExcerpt Ends
09/04/2009 20.00.22:post.Author
09/04/2009 20.00.22:post.AuthorProfile.RelativeLink
09/04/2009 20.00.35:LoadWidget Begins
09/04/2009 20.00.35:Slugs is null
09/04/2009 20.00.35:Before Findall
09/04/2009 20.00.35:After Findall
09/04/2009 20.00.35:Before RenderPosts
09/04/2009 20.00.35:RenderPosts Begins
09/04/2009 20.00.35:posts.Count == 0
09/04/2009 20.00.35:After RenderPosts
09/04/2009 20.00.35:LoadWidget Ends
09/04/2009 20.00.52:LoadWidget Begins
09/04/2009 20.00.52:Slugs is null
09/04/2009 20.00.52:Before Findall
09/04/2009 20.00.52:After Findall
09/04/2009 20.00.52:Before RenderPosts
09/04/2009 20.00.52:RenderPosts Begins
09/04/2009 20.00.52:posts.Count == 0
09/04/2009 20.00.52:After RenderPosts
09/04/2009 20.00.52:LoadWidget Ends
09/04/2009 20.01.00:LoadWidget Begins
09/04/2009 20.01.00:sSlugs is NOT IsNullOrEmpty
09/04/2009 20.01.00:arr.Length = 1
09/04/2009 20.01.00:Test-di-post-con-data-futura
09/04/2009 20.01.00:Done Parsing
09/04/2009 20.01.00:Before Findall
09/04/2009 20.01.00:After Findall
09/04/2009 20.01.00:Before RenderPosts
09/04/2009 20.01.00:RenderPosts Begins
09/04/2009 20.01.00:Post
09/04/2009 20.01.00:post.Description
09/04/2009 20.01.00:CreateExcerpt Begins
09/04/2009 20.01.00:CreateExcerpt Ends early
09/04/2009 20.01.00:post.Author
09/04/2009 20.01.00:post.AuthorProfile.RelativeLink

Apr 9, 2009 at 6:17 PM
Edited Apr 9, 2009 at 6:35 PM
I have updated the code in the post above. Please use that code and try again.  It looks like there's a null AuthorProfile.   If it still fails, post the log file again.
Apr 9, 2009 at 8:42 PM
While I am waiting for paologalli to confirm whether this fixes his issue, I have posted version 1.1 on my blog with the fix that I think should fix his issue (atleast it'll fix someone's issue :) )
Apr 10, 2009 at 6:51 AM
it works... great job!
thanks a lot