Aggregate Multiple RSS Feeds in ASP.NET Core
Public websites and blogs often expose their content in the form of RSS or
Atom feeds. If you are developing ASP.NET Core website you can either use
System.Xml classes to generate the RSS feed yourself or resort to
System.ServiceModel.Syndication classes to generate RSS / Atom feeds. At times
you also need to aggregate multiple feeds into a new feed. This is a case when
you have a network of websites and you wish to expose content from all of them
into a single feed. You might also have many feeds for individual content
categories and want the end user to either get individual feeds or a combined
feed. To that end this article discusses how to aggregate multiple RSS feeds in
ASP.NET Core.
Begin by creating a new ASP.NET Core website and configure it to use MVC and
default routing. In order to combine RSS feeds from multiple sources you need to
read them first and then generate a new feed. To accomplish this task we
will use System.ServiceModel.Syndication NuGet package. So, using the Manager
NuGet packages option install System.ServiceModel.Syndication as shown below :
Ok. Now open the HomeController and import the following namespaces :
using System.Xml;
using System.ServiceModel.Syndication;
Then add an action method called Rss() as shown below:
public void Rss()
{
...
...
}
Notice that the Rss() action returns void instead of IActionResult. This is
because we will be writing the feed content directly on the response stream.
Next, declare a string array inside the Rss() action to hold a list of RSS
feed URLs. This is shown below:
string[] feeds = new string[] {
"http://example.com/feed1",
"http://example.com/feed2"
};
Also declare a List of SyndicationItem objects to hold the combined RSS feed
items.
List<SyndicationItem> finalItems = new List<SyndicationItem>();
Now, we will iterate through the feeds array and fetch RSS feed items from
each feed one-by-one.
foreach (string feed in feeds)
{
XmlReader reader = XmlReader.Create(feed);
Rss20FeedFormatter formatter = new Rss20FeedFormatter();
formatter.ReadFrom(reader);
reader.Close();
finalItems.AddRange(formatter.Feed.Items);
}
As you can see, we create an XmlReader object based on a feed URL. This is
done using the Create() method of XmlReader class. Then we create
Rss20FeedFormatter object and load the RSS feed into it. This is done using the
ReadFrom() method. The ReadFrom() method accepts an XmlReader object and pulls
the RSS feed into the formatter. The XmlReader is then closed and the feed items
are added to the finalItems list using the AddRange()method.
The above code will aggregate multiple RSS feed items into a single list, but
these items may not be in the descending order of publication date. So, we need
to sort the finalItems list based on the PublishDate property if FeedItem
objects.
finalItems.Sort(CompareDates);
Here, CompareDates() is a private method supplied to the Sort() method and is
shown below:
private int CompareDates(SyndicationItem x, SyndicationItem y)
{
return y.PublishDate.CompareTo(x.PublishDate);
}
Ok. So far so good. Now we have all the RSS feed items into a single place,
that too in proper order. We can now form the final feed using SyndicationFeed
class. This is done as shown below:
SyndicationFeed finalFeed = new SyndicationFeed();
finalFeed.Title = new TextSyndicationContent("My RSS Feed");
finalFeed.Copyright = new TextSyndicationContent
("Copyright (C) 2018. All rights reserved.");
finalFeed.Description = new TextSyndicationContent
("RSS Feed Generated .NET Syndication Classes");
finalFeed.Generator = "My RSS Feed Generator";
finalFeed.Items = finalItems;
The above code creates an SyndicationFeed object. It then sets various
properties of the final feed such as Title, Copyright, Descriptions, and
Generator. Moreover, it sets the Items collection to the finalItems so that the
aggregated list of items becomes the part of the new feed.
Our aggregated RSS feed is now ready. We can send it back to the client using
the following code:
Response.ContentType = "text/xml";
XmlWriter writer = XmlWriter.Create(Response.Body);
Rss20FeedFormatter finalFormatter =
new Rss20FeedFormatter(finalFeed);
finalFormatter.WriteTo(writer);
writer.Close();
Response.Body.Flush();
In order to write the aggregated feed onto the response stream, we set the
ContentType to text/xml since an RSS feed is an XML document. We then create an
XmlWriter based on the Response's Body property (which is a Stream). A new
Rss20FeedFormatter object is then created by passing the XmlWriter.
The WriteTo() methof of Rss20FeedFormatter class writes the RSS feed onto the
response stream. We then close the XmlWriter and Flush() the response stream.
If you run the application you should see RSS feed in the browser. The
following figure shows a sample run of the application.
That's it for now! Keep coding!!