Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jacob Polden 67 posts 177 karma points
    Jan 09, 2012 @ 11:35
    Jacob Polden
    0

    Consume an RSS feed in Razor

    Has anyone in the Umbraco community created a script that allows a RSS feed to be consumed an output segments as HTML that we can style?

     

    THANKS!

  • Warren Buckley 2106 posts 4814 karma points MVP ∞ admin hq c-trib
    Jan 09, 2012 @ 11:40
    Warren Buckley
    0

    Hi Jacob is it any particular RSS feed you are trying to consume, such as a Flickr feed or a generic RSS news item feed?
    I have lost the example I wrote for someone else, however I will try and comble somethign together shortly.

    Warren

  • Jacob Polden 67 posts 177 karma points
    Jan 09, 2012 @ 11:44
    Jacob Polden
    0

    Thank you for the response!

    It is for a Tumblr RSS feed.

     

    Jacob

  • Warren Buckley 2106 posts 4814 karma points MVP ∞ admin hq c-trib
    Jan 09, 2012 @ 11:45
    Warren Buckley
    0

    Do you have an example to a Tumblr RSS feed URL that I can experiment with and then I can see what I can do.

    Warren

  • Sebastiaan Janssen 4985 posts 15098 karma points MVP admin hq
    Jan 09, 2012 @ 11:45
    Sebastiaan Janssen
    3

    Here's a quick & dirty one that works: 

    @{
        var xml = "";
        var targetUri = new Uri("http://blog.orcare.com/rss");
        var request = (HttpWebRequest)WebRequest.Create(targetUri);
        if ((request.GetResponse().ContentLength > 0))
        {
            var stream = new StreamReader(request.GetResponse().GetResponseStream());
            xml = stream.ReadToEnd();
            if (stream != null)
            {
                stream.Close();
            }
        }
        var feed = Library.ToDynamicXml(xml);
    }
    
    @foreach (var post in feed.channel.item)
    {
        @post.title   <br />
    }

    The thing to remember is that you're turning the feed into a dynamic object. So "channel.item" is actually the item node in the channel node. Also, in post.title, the "title" is the title node in that "channel.item".

    You can do all kinds of fun things with it like @Library.Find and so on (see my examples project and the cheat sheet for more information)

  • Jacob Polden 67 posts 177 karma points
    Jan 09, 2012 @ 11:49
    Jacob Polden
    0

    @Warren Buckley

    Here's our Tumblr feed: http://blog.orcare.com/rss 

  • Sebastiaan Janssen 4985 posts 15098 karma points MVP admin hq
    Jan 09, 2012 @ 11:52
    Sebastiaan Janssen
    0

    Updated my post with that URL, and tested it, still works :-)

  • Warren Buckley 2106 posts 4814 karma points MVP ∞ admin hq c-trib
    Jan 09, 2012 @ 12:11
    Warren Buckley
    2

    Sebastian's way might be the nicer way to do it, in terms of fetching the item value out using dot noation eg @post.description, @post.title etc
    However this was the approach I done when I helped out Anders Stentebjerg

    @using System.Xml;
    
    @{
        //Get the XML from remote URL
        XmlDocument xml = new XmlDocument();
        
        //URL currently hardcoded - but you could use a macro param to pass in URL
        xml.Load("http://blog.orcare.com/rss");
        
        //Select the nodes we want to loop through
        XmlNodeList nodes = xml.SelectNodes("//item");
        
        //Traverse the entire XML nodes.
        foreach (XmlNode node in nodes)
        {
            //Get the value from the <title> node
            var title = node.SelectSingleNode("title").InnerText;
    
            //Get the value from the <description> node
            var description = node.SelectSingleNode("description").InnerText;
            
            <h1>@title</h1>
            @Html.Raw(description)
            
        } 
    }
  • Tim 1193 posts 2675 karma points MVP c-trib
    Jan 09, 2012 @ 12:40
    Tim
    0

    Just a quickie in terms of performance, depending on the size of the RSS feed and where its located (e.g. its usually slower to retrieve a feed from another site that's in another country than it is t get one from the same server/location), you'll want to consider caching. You can either set a high cache rate for the Macro, or you can use the excellent Feed Cache package, which allows you to cache the feed at periodic intervals and you can get your list macro to read from the cached file instead. It reduces the network travel to nothing, and if the RSS feed goes down for any reason, you'll still have the cached copy, so the feed won't just drop off your site!

  • Warren Buckley 2106 posts 4814 karma points MVP ∞ admin hq c-trib
    Jan 09, 2012 @ 12:54
    Warren Buckley
    3

    Anders just sent me the link to the version I sent him a while ago, which is very similar but shows a slightly different approach again, but Tim you make some great points about combining with the Feed Cache package, as you can ensure you wil always have XML to retrieve if the remote site is down.

    @using System.Xml.XPath;
    @using System.Xml;
    
    @{
        //Fetch RSS XML
        XmlTextReader udBrudRSS = new XmlTextReader("http://myblog.com/rss");
    
        //Create new XML document
        XmlDocument doc = new XmlDocument();
    
        //Load in our remote XML into our XML document
        doc.Load(udBrudRSS);
    
        //Select our nodes we want with some xPath
        XmlNodeList rssItems = doc.SelectNodes("//item");
    
    }
    <ul>
        @{
            //For each item node we can then ouput what we want
            foreach (XmlNode node in rssItems)
            {
                <li>
                    <div class="date">@node["pubDate"].InnerText</div>
                    <a href="@node["link"].InnerText">@node["title"].InnerText</a>
                </li>
            }
        }
    </ul>
  • Jacob Polden 67 posts 177 karma points
    Jan 09, 2012 @ 12:56
    Jacob Polden
    0

    Thanks a lot guys, I will implemet later and let you know if it works or not!

     

    Jacob

  • Steve 472 posts 1216 karma points
    Jan 31, 2013 @ 17:00
    Steve
    0

    Warren,

    I am trying to modify your script to limit the number of Items pulled from the feed. I was trying this, but it doesn't like "Take" in this syntax. Can you point me in the right direction? Thanks!

    <ul>
       
    @{
           
    //For each item node we can then ouput what we want
           
    foreach(XmlNode node in rssItems.Take(6))
           
    {
               
    <li>
                   
    <div class="date">@node["pubDate"].InnerText</div>
                    <a href="@node["link"].InnerText">@node["title"].InnerText</
    a>
               
    </li>
            }
        }
    </
    ul>
  • MikeD 92 posts 112 karma points
    Feb 08, 2013 @ 22:28
    MikeD
    0

    I would like to know how to do this as well, limit the nummber of results.  Why does it hate Take()?

  • MikeD 92 posts 112 karma points
    Feb 12, 2013 @ 15:57
    MikeD
    0

    Hey Steve, I figured out a solution if you ahve not come up with anything yet.  I am not a programmer so I had to do a lot of searching, but here is my solution:

    @using System.Xml.XPath;
    @using System.Xml;
     
    @{
    //Fetch RSS XML
    @*
    var feedUrl = @Parameter.feedUrl;
    var limit = Int32.Parse(@Parameter.setLimit);
    *@
    var feedUrl = @Model.feedUrl;
    var limit = @Model.setLimit;
    XmlTextReader udBrudRSS = new XmlTextReader(feedUrl);
    //Create new XML document
    XmlDocument doc = new XmlDocument();
    //Load in our remote XML into our XML document
    doc.Load(udBrudRSS);
    //Select our nodes we want with some xPath
    XmlNodeList rssItems = doc.SelectNodes("//item");
    var letsCountNodes = 1;
    //For each item node we can then ouput what we want
    foreach (XmlNode node in rssItems)
    {
    if (@letsCountNodes <= limit)
    {
    <div id="rssBlurb">
    <a href="@node["link"].InnerText" target="_blank">@node["title"].InnerText</a>
    <div class="rssDesc">@Html.Raw(@node["description"].InnerText)</div>
    <div class="rssDate">posted: @node["pubDate"].InnerText</div>
    </div>
    letsCountNodes++;
    }
    }
    }
  • René Andersen 238 posts 684 karma points
    Jun 18, 2013 @ 21:31
    René Andersen
    0

    Hi

    I know that it has been a long time since the last post but I will show my solution anyway regarding limit the number of Items pulled from the feed.

    @inherits umbraco.MacroEngines.DynamicNodeContext

    @using System.Xml.XPath;
    @using System.Xml;

    @{
    //Fetch RSS XML
    XmlTextReader udBrudRSS = new XmlTextReader("http://frederikssund.lokalavisen.dk/section/senestenytrss");

    //Create new XML document
    XmlDocument doc = new XmlDocument();

    //Load in our remote XML into our XML document
    doc.Load(udBrudRSS);

    //Select our nodes we want with some xPath
    XmlNodeList rssItems = doc.SelectNodes("//item");

    }

    @{
    //For each item node we can then ouput what we want

    var maxItems = 5;
    var displayCount = rssItems.Count < maxItems ? rssItems.Count : maxItems;
    for (int index = 0; index < displayCount; index++)
    {
    var node = rssItems[index];

    <article class="blog-post text-post">
    <div class="blog-content">
    <div class="title">
    <h2><a href="@node["link"].InnerText">@node["title"].InnerText</a></h2>
    </div>
    <p>@node["description"].InnerText</p>
    </div>
    </article>

    }
    }

    // René

  • Steve 472 posts 1216 karma points
    Jun 18, 2013 @ 21:43
    Steve
    0

    Thanks Rene,

    This is what I ended up using. A simple if statement to control the number of items in the feed.

    @using System.Xml.XPath;
    @using System.Xml;
    @using umbraco.MacroEngines;
    @inherits umbraco.MacroEngines.DynamicNodeContext
    
    @{
        //Fetch RSS XML
        XmlTextReader udBrudRSS = new XmlTextReader("http://rosestem.rose-hulman.edu/controls/cms_v2/components/rss/rss.aspx?sid=1554&gid=1&calcid=1110&page_id=402");
    
        //Create new XML document
        XmlDocument doc = new XmlDocument();
    
        //Load in our remote XML into our XML document
        doc.Load(udBrudRSS);
    
        //Select our nodes we want with some xPath
        XmlNodeList rssItems = doc.SelectNodes("//item");
    
    }
    <ul class="rss-feed">
        @{
            //For each item node we can then ouput what we want
            var i = 0;
            foreach (XmlNode node in rssItems)
                {
                <li>
                    <a href="@node["link"].InnerText">@node["title"].InnerText</a>
                    <div class="date">@Html.Raw(@node["description"].InnerText)</div>
    
                </li>
                i++;
                if (i == 5){ break; }
                } 
    
        }
    </ul>
  • Maria 34 posts 128 karma points
    Sep 10, 2013 @ 10:25
    Maria
    0

    An alternative solution:

    XmlNodeList rssItems = doc.SelectNodes("//item");
    
    List<XmlNode> feedItems = new List<XmlNode>();
    
    foreach(XmlNode node in rssItems)
    {
        feedItems.Add(node);
    }
    

    This will now allow you to do:

     foreach (XmlNode feedItem in feedItems.Take(6))
        {...}
    
  • Maria 34 posts 128 karma points
    Sep 10, 2013 @ 10:27
    Maria
    0

    Sorry, it got posted twice and I don't seem to be able to delete it.

  • Max 14 posts 44 karma points
    Feb 27, 2014 @ 20:57
    Max
    0

    Hi All!

    It's a bit late answer, but why not to use XPath to limit scope:

    XmlNodeList rssItems = doc.SelectNodes("//item[position() < 5]");

  • Steve 472 posts 1216 karma points
    Feb 28, 2014 @ 17:50
    Steve
    0

    Hey, something has come up with my feed parser. I was pulling a feed in using:

    @{
       
    //Fetch RSS XML
       
    XmlTextReader udBrudRSS =newXmlTextReader("http://rosestem.rose-hulman.edu/controls/cms_v2/components/rss/rss.aspx?sid=1554&gid=1&calcid=1110&page_id=402");

       
    //Create new XML document
       
    XmlDocument doc =newXmlDocument();

       
    //Load in our remote XML into our XML document
        doc
    .Load(udBrudRSS);

       
    //Select our nodes we want with some xPath
       
    XmlNodeList rssItems = doc.SelectNodes("//item");

    }
    <ul class="rss-feed">
       
    @{
           
    //For each item node we can then ouput what we want
           
    var i =0;
           
    foreach(XmlNode node in rssItems)
               
    {
               
    <li>
                   
    <a href="@node["link"].InnerText">@node["title"].InnerText</a>
                    <div class="date">@Html.Raw(@node["description"].InnerText)</
    div>

               
    </li>
                i++;
                if (i == 5){ break; }
                }

        }

    This code worked until the location of the feed suffered a DOS and changed their firewall set up.

    After talking with their IT support department, they suggested adding a "user agent" within the script, but I am unfamiliar with how to do this in razor. Could someone show me how to accomplish this in my current script?

  • Brian McNally 12 posts 90 karma points
    Sep 29, 2014 @ 19:34
    Brian McNally
    1

    Hi Warren,

    thanks so much for your solution in this thread. I've been using it and it seems to work great most of the time. Sometimes the page throws an error 'server unavailable' pointing to the doc.Load(udBrudRSS); line, and I'm guessing it's because perhaps the rss feed is currently unavailable?

    What's the easiest/best syntax to just add a check on that BLOG rss URL? If that URL isn't available/accessible, I would rather have no feed returned than a full page error.

    @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
    @using System.Xml.XPath;
    @using System.Xml;
    @using umbraco.MacroEngines;
    
    
    @{
        //Fetch RSS XML
        XmlTextReader udBrudRSS = new XmlTextReader("http://myblogurl/feeds/posts/default?alt=rss");
    
        //Create new XML document
        XmlDocument doc = new XmlDocument();
    
        //Load in our remote XML into our XML document
        doc.Load(udBrudRSS);
    
        //Select our nodes we want with some xPath
        XmlNodeList rssItems = doc.SelectNodes("(//item)[position() <= 3]");
    
    
    
    
    }
    
    <ul  class="listicon">
    
    
        @{
    
            foreach (XmlNode node in rssItems)
            {
    
                <li class="blogIcon"><a title="@node["title"].InnerText" href="@node["link"].InnerText" target="_blank" >@node["title"].InnerText</a></li>
    
            }
    
        }
    </ul>
    
  • Max 14 posts 44 karma points
    Sep 30, 2014 @ 09:35
    Max
    0

    Hi Brian! You might can try to use Try/Catch, something like:

    try
    {
        doc.Load(udBrudRSS);
    }
    catch { }

  • Bobi 339 posts 932 karma points
    Feb 28, 2017 @ 05:00
    Bobi
    0

    Hi,

    Do any of these examples prevent Internet users from seeing what rss feed url's you are pulling (i.e. prevent them from seeing what .rss or .xml files you are using)?

Please Sign in or register to post replies

Write your reply to:

Draft