SharePoint AJAX RSS Aggregator WebPart - Zlatan's Blog [MVP SharePoint]

SharePoint AJAX RSS Aggregator WebPart

 

Ok so I thought to myself.... what if I make the RSS Aggregator (http://dotnet.org.za/zlatan/archive/2008/11/28/updated-sharepoint-rss-aggregator-web-part.aspx) AJAX enabled.

Some of you might even remember me blogging about developing AJAX web parts for SharePoint last year some time (http://dotnet.org.za/zlatan/archive/2007/10/12/developing-ajax-web-parts-in-sharepoint-2007.aspx).

Well here's what came out of this experiment, although this is more for messing around, to see how it works and for an odd chance that someone is permanently displaying a screen with aggregated RSS feeds that needs smooth updates (every 30 seconds or so). It uses my favourite UpdatePanel and also Ticker control.

Download the source code here:

http://www.codeplex.com/AJAXRSSAggregator

Don't forget to follow this (http://msdn.microsoft.com/en-us/library/bb861898.aspx) to configure your SharePoint for AJAX, unless you did that already.

Here's the code as well:

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;
using System.Xml.Linq;
using System.Net;
using System.Text;

namespace AJAXRSSAggregator
{
    [Guid("5905eac7-df55-4529-8d7a-f6f7ff9b6fa3")]
    public class AJAXRSSAggregator : System.Web.UI.WebControls.WebParts.WebPart
    {
        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;
        private Label displayName;
        private int refreshInterval = 30;
        private string htmlstuff = null;

        public AJAXRSSAggregator()
        {
        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            //Fix for the UpdatePanel postback behaviour.
            EnsurePanelFix();

            UpdatePanel refreshName = new UpdatePanel();
            ScriptManager scriptHandler = new ScriptManager();
            displayName = new Label();

            scriptHandler.ID = "scriptHandler";
            refreshName.ID = "refreshName";
            refreshName.UpdateMode = UpdatePanelUpdateMode.Conditional;
            refreshName.ChildrenAsTriggers = true;


            Timer timer = new Timer();

            timer.Interval = refreshInterval * 1000;
            timer.Tick += new EventHandler<EventArgs>(TimerHandler);
            refreshName.ContentTemplateContainer.Controls.Add(timer);

            refreshName.ContentTemplateContainer.Controls.Add(this.displayName);

            //The ScriptManager control must be added first.
            this.Controls.Add(scriptHandler);
            this.Controls.Add(refreshName);
        }

        private void TimerHandler(object sender, EventArgs args)
        {
            htmlstuff = null;
            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 (singleRssItem.Tags != null)
                    {
                        if (filterCriteria != null)
                            tagValue = singleRssItem.Tags.ToLower();

                        if (tagValue.Contains(filterCriteria) == true || filterCriteria == null)
                        {
                            htmlstuff += "<div class=\"container\">";
                            htmlstuff += "<font size=\"4\" face=\"Verdana\"><b><a href =\"";
                            htmlstuff += singleRssItem.Href;
                            htmlstuff += "\"><font size=\"2\" face=\"Verdana\">";
                            htmlstuff += singleRssItem.Title;
                            htmlstuff += "</a></b></font>";

                            htmlstuff +="<div class=\"module-content\"><table width=\"100%\" border=\"0\"><tr><td><font size=\"2\" face=\"Verdana\">";
                            htmlstuff +=singleRssItem.Body;
                            htmlstuff +="</font></td></tr></table></div>";
                            htmlstuff +="</div>";

                            htmlstuff +="<div class=\"module-content\"><table width=\"100%\" border=\"0\"><tr><td><font size=\"2\" face=\"Verdana\">";
                            htmlstuff +=singleRssItem.Tags;
                            htmlstuff +="</font></td></tr></table></div>";
                            htmlstuff +="</div>";

                            htmlstuff +="<div class=\"module-content\"><table width=\"100%\" border=\"0\"><tr><td><font size=\"2\" face=\"Verdana\">";
                            htmlstuff +=singleRssItem.PubDate.ToString();
                            htmlstuff +="</font></td></tr></table></div>";
                            htmlstuff +="</div>";
                            i++;
                        }
                    }
                }
            }

            this.displayName.Text = htmlstuff;
        }

        private void EnsurePanelFix()
        {
            if (this.Page.Form != null)
            {
                string fixupScript = @"_spBodyOnLoadFunctionNames.push(""_initFormActionAjax"");

             function _initFormActionAjax()
             {
               if (_spEscapedFormAction == document.forms[0].action)
               {
                 document.forms[0]._initialAction = document.forms[0].action;
               }
             }

             var RestoreToOriginalFormActionCore = RestoreToOriginalFormAction;

             RestoreToOriginalFormAction = function()
             {
               if (_spOriginalFormAction != null)
               {
                 RestoreToOriginalFormActionCore();
                 document.forms[0]._initialAction = document.forms[0].action;
               }
             }";
                ScriptManager.RegisterStartupScript(this, typeof(AJAXRSSAggregator), "UpdatePanelFixup", fixupScript, true);
            }
        }


        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 XElement 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
                    {
                        WebClient client = new WebClient();
                        byte[] byteData = client.DownloadData(url);
                        string strData = Encoding.UTF8.GetString(byteData);
                        rssDoc = XElement.Parse(strData);

                        foreach (var elm in rssDoc.Descendants("item"))
                        {

                            this.Add(new RssItem(elm));

                        }

                    }
                    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(XElement xNode)
        {
            if (xNode.NodeType == XmlNodeType.CDATA)
            {
                XCData titleCData = xNode.FirstNode as XCData;
                title = titleCData.Value;
            }
            else
                title = (string)xNode.Element("title").Value;

            if (xNode.NodeType == XmlNodeType.CDATA)
            {
                XCData linkCData = xNode.FirstNode as XCData;
                href = linkCData.Value;
            }
            else
                href = (string)xNode.Element("link").Value;

            if (xNode.NodeType == XmlNodeType.CDATA)
            {
                XCData bodyCData = xNode.FirstNode as XCData;
                body = FixDesc(bodyCData.Value, href);
            }
            else
                body = FixDesc((string)xNode.Element("description").Value, href);

            pubDate = Convert.ToDateTime((string)xNode.Element("pubDate").Value);

            foreach (XElement node in xNode.Elements("category"))
            {
                if (node.NodeType == XmlNodeType.CDATA)
                {
                    XCData categoryCData = node.FirstNode as XCData;
                    if (tags == null)
                        tags = (string)categoryCData.Value;
                    else
                        tags = tags + ", " + (string)categoryCData.Value;
                }
                else
                {
                    if (tags == null)
                        tags = (string)node.Value;
                    else
                        tags = tags + ", " + (string)node.Value;
                }
            }
        }

        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 Saturday, November 29, 2008 2:36 AM by Zlatan

Comments

# SharePoint AJAX RSS Aggregator WebPart

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

Saturday, November 29, 2008 1:13 AM by DotNetKicks.com

# re: SharePoint AJAX RSS Aggregator WebPart

trackback-ed

Wednesday, January 07, 2009 4:39 PM by François @ London