Multiple RSS Aggregator Web Part Example - Zlatan's Blog [MVP SharePoint]

Multiple RSS Aggregator Web Part Example

Ok so............. long time ago, in a city far far away (from Cape Town) our very own Willy (http://dotnet.org.za/willy) wanted to re-launch SAArchitect (http://www.saarchitect.net/) community and envisaged a need to aggregate all the feeds from SAArchitect community members and filter on a certain tag in the blog posts posted by those same members (in particular "SAArchitect" tag).  Since http://www.saarchitect.net/ is running on a SharePoint 2007 platform, he needed a SharePoint kind of guy that can make this idea a reality. He searched high and low, and after being bounced around a bit he found me :), and considering the fact that at that time I thought I might have some free time between 3am and 4am every 4th day I thought, why the hell not. So Willy even blogged about it to make sure that my commitment stayed public (http://dotnet.org.za/willy/archive/2008/02/20/sa-architect-re-launching-the-community-why-how-and-where-next.aspx).

I wrote the Web Part and sent it to Willy, and although he successfully tested it, he still didn't get around to deploying it (hosting company issues I think).

After all this time I decided to share this with the community, as this is quite cool for community sites powered by SharePoint 2007, and I'm sure someone else might also find it quite useful.

I needed first to know how to get a simple, single RSS feed to display its data so I found this example from Sahil (http://blah.winsmarts.com/2006-7-Sharepoint_Webparts_AS_-_Writing_the_WebParts_-_The_RSS_Feed_WebPart.aspx) and used it as a starting point.

The way this works is that you can specify multiple feeds (separated by a character ";"), and the filter criteria as well the number of feeds displayed. This was my first shot at it, and it's quite simple, so feel free to take it apart, and I think this concept has quite a bit of potential so I think I'll revisit this once again (when I find time) with even more exciting technology.

Be careful as the example uses "saarchitect" as default value to filter on, make sure to change that when you deploy the web part, or you can even take out that whole concept out of the code.

It was written with Visual Studio 2005 SP1 with VSeWSS 1.1 (beta I think).

You can download the project files + source code with a wsp here (http://dotnet.org.za/blogs/zlatan/RSSWebPart.zip).

It used standard references (Microsoft.SharePoint, System, System.Web, System.XML)

Here's the code:

 using System;

using System.Runtime.InteropServices;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Serialization;

 

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

using Microsoft.SharePoint.WebPartPages;

using System.Collections.Generic;

using System.Xml;

using System.Text.RegularExpressions;

using System.ComponentModel;

 

namespace RSSWebPart

{

    [Guid("c4cc9fd1-2865-4d28-9e33-6e2f80eb4868")]

    public class RSSWebPart : System.Web.UI.WebControls.WebParts.WebPart

    {

        public RSSWebPart()

        {

            this.ExportMode = WebPartExportMode.All;

        }

        private string rssUrl;

        private string feedName;

        private const string constDefFeedCriteriaValue = "saarchitect";

        private string filterCriteria = constDefFeedCriteriaValue;

        private const string constDefFeedLimitValue = "5";

        private string feedLimit = constDefFeedLimitValue;

        private int feedLmt;

        private string tagValue;

 

 

        protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)

        {

            try

            {

                feedLmt = Convert.ToInt32(feedLimit);

            }

            catch (Exception)

            {

                feedLmt = 0;

            }

            RssFeed feed = new RssFeed(rssUrl);

            feed.Sort(delegate(RssItem r1, RssItem r2)

            {

                return r2.PubDate.CompareTo(r1.PubDate);

            });

 

            int i = 0;

           

            foreach (RssItem singleRssItem in feed)

            {

                if (i < feedLmt)

                {

                    if (filterCriteria != null && singleRssItem.Tags != null)

                    {

                        tagValue = singleRssItem.Tags.ToLower();

                        if (tagValue.Contains(filterCriteria) == true)

                        {

                            writer.Write("<div class=\"container\">");

                            writer.Write("<font size=\"4\" face=\"Verdana\"><b><a href =\"");

                            writer.Write(singleRssItem.Href);

                            writer.Write("\"><font size=\"2\" face=\"Verdana\">");

                            writer.Write(singleRssItem.Title);

                            writer.Write("</a></b></font>");

 

                            writer.Write("<div class=\"module-content\"><table width=\"100%\" border=\"0\"><tr><td><font size=\"2\" face=\"Verdana\">");

                            writer.Write(singleRssItem.Body);

                            writer.Write("</font></td></tr></table></div>");

                            writer.Write("</div>");

 

                            writer.Write("<div class=\"module-content\"><table width=\"100%\" border=\"0\"><tr><td><font size=\"2\" face=\"Verdana\">");

                            writer.Write(singleRssItem.Tags);

                            writer.Write("</font></td></tr></table></div>");

                            writer.Write("</div>");

 

                            writer.Write("<div class=\"module-content\"><table width=\"100%\" border=\"0\"><tr><td><font size=\"2\" face=\"Verdana\">");

                            writer.Write(singleRssItem.PubDate.ToString());

                            writer.Write("</font></td></tr></table></div>");

                            writer.Write("</div>");

                            i++;

                        }

                    }

                }

            }

        }

 

        public string FeedName

        {

            get

            {

                return feedName;

            }

            set

            {

                feedName = value;

            }

        }

 

 

        [WebBrowsable(true),

        Personalizable(true),

        Category("RSS Aggregator Web Part"),

        DisplayName("URLs of the Feed"),

        WebDisplayName("URLs of the Feed"),

        Description("Please enter the URLs of the feed separated by ';' character.")]

        public string FeedURL

        {

            get

            {

                return rssUrl;

            }

            set

            {

                rssUrl = value;

            }

        }

 

        [WebBrowsable(true),

        Personalizable(true),

        Category("RSS Aggregator Web Part"),

        DisplayName("Filter Criteria"),

        WebDisplayName("Filter Criteria"),

        Description("Please enter the tag value you wish to filter on for desired RSS feeds."),

        DefaultValue(constDefFeedCriteriaValue)]

        public string FilterOn

        {

            get

            {

                return filterCriteria.ToLower();

            }

            set

            {

                filterCriteria = value.ToLower();

            }

        }

 

        [WebBrowsable(true)]

        [Personalizable(true),

        Category("RSS Aggregator Web Part"),

        DisplayName("Feed Limit"),

        WebDisplayName("Feed Limit"),

        Description("Defines the list the web part will read from."),

        DefaultValue(constDefFeedLimitValue)]

        public string FeedLimit

        {

            get

            {

                return feedLimit;

            }

            set

            {

                feedLimit = value;

            }

        }

 

    }

 

 

    internal class RssFeed : List<RssItem>

    {

        private XmlDocument rssDoc;

 

        internal RssFeed(string RssURL)

        {

 

            if (RssURL == null)

            {

                this.Add(new RssItem());

            }

            else

            {

                string[] rssUrlsArray = RssURL.Split(new char[] { ';' });

                foreach (string url in rssUrlsArray)

                {

                   

                    try

                    {

                        rssDoc = new XmlDocument();

                        XmlTextReader xRead = new XmlTextReader(url);

                        rssDoc.Load(xRead);

 

                        XmlNodeList xNodes = rssDoc.SelectNodes("./rss/channel/item");

                       

                        foreach (XmlNode xNode in xNodes)

                        {

                            

                            this.Add(new RssItem(xNode));

                           

                        }

                       

                    }

                    catch (Exception)

                    {

                        this.Add(new RssItem());

                    }

                }

            }

        }

    }

 

    internal class RssItem

    {

        private string title;

        private string href;

        private string body;

        private string tags;

        private DateTime pubDate;

 

 

        public string Href

        {

            get { return href; }

        }

 

 

        public string Title

        {

            get { return title; }

        }

 

        internal RssItem()

        {

            title = "Feed not available at this time";

            href = "~";

        }

 

 

        public string Body

        {

            get { return body; }

            set { body = value; }

        }

 

        public string Tags

        {

            get { return tags; }

            set { tags = value; }

        }

 

        public DateTime PubDate

        {

            get { return pubDate; }

            set { pubDate = value; }

        }

 

        internal RssItem(XmlNode xNode)

        {

            title = xNode.SelectSingleNode("./title").InnerText;

            href = xNode.SelectSingleNode("./link").InnerText;

            body = FixDesc(xNode.SelectSingleNode("./description").InnerText, href);

            pubDate = Convert.ToDateTime(xNode.SelectSingleNode("./pubDate").InnerText);

 

            XmlNodeList nodeList = xNode.SelectNodes("./category");

            foreach (XmlNode node in nodeList)

            {

                tags = tags + " " + node.InnerText;

            }

        }

 

        public string FixDesc(object desc, object link)

        {

            if (link == null || desc == null) return String.Empty;

 

            string description = desc.ToString();

            //Replace all HTML tags so none get cut-off and screw up the page

            Regex reg = new Regex("<.*?>", RegexOptions.Compiled);

            string stripDesc = reg.Replace(description, String.Empty);

            if (stripDesc.Length > 250)

            {

                int startPos = 250;

                char[] chars = stripDesc.ToCharArray();

                char c = chars[startPos];

                while (!Char.IsWhiteSpace(c) && startPos < chars.Length)

                {

                    startPos++;

                    c = chars[startPos];

                }

                stripDesc = new String(chars, 0, startPos) + " ... <a href='" + link.ToString() + "'> More</a>";

 

            }

            return stripDesc;

        }

    }

}

Published Friday, June 06, 2008 3:11 PM by Zlatan

Comments

# Dew Drop &ndash; June 7, 2008 | Alvin Ashcraft's Morning Dew

Pingback from  Dew Drop &ndash; June 7, 2008 | Alvin Ashcraft's Morning Dew

Saturday, June 07, 2008 10:03 PM by Dew Drop – June 7, 2008 | Alvin Ashcraft's Morning Dew

# Links (6/8/2008) &laquo; Steve Pietrek - Everything SharePoint

Pingback from  Links (6/8/2008) &laquo; Steve Pietrek - Everything SharePoint

# Multiple RSS Aggregator Web Part Example

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Friday, June 20, 2008 10:10 PM by DotNetKicks.com

# re: Multiple RSS Aggregator Web Part Example

Bulldog, your controll will go live on SA Architect as soon as our very own server is operational. We are currently hosting the community site on a shared server and were therefore unable to deploy ... soon SA Architect will run on its own server and then your control will definitely make it onto our home page!

Friday, June 20, 2008 10:51 PM by willy

# SharePoint Kaffeetasse #76

Web Content Management TechNet: Administering Web content management TechNet: White paper: End-to-End

Sunday, June 22, 2008 6:33 PM by Michael Greth MVP SharePoint Blog

# Teched 2008 South-Africa - Countdown T-30 Days

The Teched event is slowly, but surely crawling towards us and as part of the MVP and SA Architect we

Saturday, July 05, 2008 1:00 PM by Willy-Peter Schaub's Cave of Chamomile Simplicity

# Goodbye SAArchitect, welcome SAArchitect!

Thanks to some amazing work from two our our SAArchitect leads, Robert MacLean (who still has not uploaded

Wednesday, October 01, 2008 10:28 AM by Willy-Peter Schaub's Cave of Chamomile Simplicity

# Blog Aggregator for SharePoint | SADev.co.za

Pingback from  Blog Aggregator for SharePoint | SADev.co.za

Wednesday, October 22, 2008 2:39 PM by Blog Aggregator for SharePoint | SADev.co.za

# Updated SharePoint RSS Aggregator Web Part

I&#39;ve decided to start using CodePlex so I uploaded SharePoint RSS Aggregator Web Part that I posted

Friday, November 28, 2008 11:48 PM by Zlatan's Blog [MVP SharePoint]

# Updated SharePoint RSS Aggregator Web Part

I&#39;ve decided to start using CodePlex so I uploaded SharePoint RSS Aggregator Web Part that I posted

Saturday, November 29, 2008 12:38 AM by SharePoint MVP Blogs