C# RSS generator in less than than 50 lines of code

What kind of technical blog doesn’t have RSS feed? Well, this one didn’t have one. This short post will present single method for generating RSS feed we are using, and answer why we are not using existing solution.

After googling for existing solutions for generating RSS feed, one of the first solution was to use Wildermuth’s RssSyndication library. After trying to install nuget package WilderMinds.RssSyndication I quickly realized it won’t work, because latest version of the library is targeting .NETStandard 2.0 and our blog is hosted on .NET Core 1.1. We could upgrade to .NET Core 2.0, but then we would either have to either 1) switch server because we have more than one app on this server running on .NET Core 1.1 or 2) publish our app as self-contained-binaries. We didn’t like our options. Another solution would have been to use older version of WilderMinds.RssSyndication.

Quickly digging trough commits brought me to the commit which was updating WilderMinds.RssSyndication from .NETStandard 1.3 to .NETStandard 2.0. As you can see there aren’t any significant changes there except the target versions. So, why aren’t we using older version of the library? Because if we stay with older version of the library, we might miss bug-fixes, so we could either open an issue on the GitHub repo and politely ask Shawn to bring back the support of older .NETStandard or create our own generator. Creating our own generator was probably the faster solution. Here is the code that generates our RSS feed.

private string BuildRssFeedContent()
{
    string url = "https://hackingmonkeys.com/";
    string description = "Monkey's code, monkey's hacks, monkey's thoughts. .NET (Core) and stuff...";
    
    var posts = GetRenderedPages(); // cached

    var feed = new XDocument(new XElement("rss"));
    feed.Root.Add(new XAttribute("version", "2.0"));
    
    string copyYear = "2018";
    if (DateTime.Today.Year > 2018) 
    {
        copyYear = "2018-" + DateTime.Today.Year;
    }
    XNamespace atomNs = "http://www.w3.org/2005/Atom";
    var ch = new XElement("channel");
    ch.Add(new XElement("title", "HackingMonkeys Blog"));
    ch.Add(new XElement("link", url));
    ch.Add(new XElement(atomNs + "link", 
        new XAttribute("href", url + "rss"), 
        new XAttribute("rel", "self"), 
        new XAttribute("type", "application/rss+xml")));
    ch.Add(new XElement("description", new XCData(description)));
    ch.Add(new XElement("copyright", $"Copyright {copyYear} hackingmonkeys.com"));
    ch.Add(new XElement("language", "en"));
    ch.Add(new XElement("lastBuildDate", posts.First().CreatedDate.ToString("r")));
    ch.Add(new XElement("pubDate", posts.First().CreatedDate.ToString("r")));
    ch.Add(new XElement("generator", "manually hacked by hackingmonkeys"));
    ch.Add(new XElement("managingEditor", $"{_email} (${_name})"));
    ch.Add(new XElement("webMaster", $"{_email} (${_name})"));
    ch.Add(new XElement("ttl", (60*4).ToString()));
    feed.Root.Add(ch);
    foreach (var post in posts)
    {
        var postElement = new XElement("item");
        postElement.Add(new XElement("title", new XCData(post.Title)));
        postElement.Add(new XElement("link", $"{url}blog/{post.FormatedCreatedDate}/{post.Id}"));
        postElement.Add(new XElement("description", new XCData(post.ShortHtml)));
        // postElement.Add(new XElement("author", ""));
        foreach (var c in post.Tags) postElement.Add(new XElement("category", new XCData(c)));
        postElement.Add(new XElement("pubDate", post.CreatedDate.ToString("r")));
        ch.Add(postElement);
    }
    return "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>" + Environment.NewLine + feed.ToString();
}

This method was inspired by this postthis SO answer, and WilderMinds.RssSyndication Feed class. Comparing our code with Feed class from WilderMinds.RssSyndication you can notice a few differences:

  • channel node has a few more elements (lastBuildDatemanagingEditorlanguage, etc…)
  • channel has link with rel="self" and Atom namespace, as it was asked by online validator
  • some nodes that could contain HTML are using CData in oder to avoid possible XML escaping problems

Source : https://hackingmonkeys.com/blog/2018-03-29/rss-generator-in-less-than-50-lines-of-code

Author:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.