Colin Bacon, web developer.

How I removed all validation warnings from my RSS feed - ASP.NET Core

How I removed all validation warnings from my RSS feed - ASP.NET Core

Much has changed with .NET Core, creating syndication feeds isn't one of them.

Background

When migrating my blog from .NET framework to .NET Core, I came to the RSS feed. Considering my original code is 8-10 years old, I wondered what has changed since then? So I had a quick Internet search and found a recent post on the subject (Creating an RSS Feed in ASP.NET Core 3.0). This is an excellent article and I highly recommend having a read if you need to create a feed. It was clear from the article not much had changed, it was the same library, System.ServiceModel.Syndication.

Feed validation warnings

What sparked my interest was the mention of a valid feed, no warnings or errors.

I found several examples; however, they always failed validation from W3C, after much trial and error I have managed to create a working RSS Feed and thought I'd share the process.

W3C has a Feed Validation Service. Enter your feed URL and it checks the content and returns warnings/errors if found. My feed was valid, but I had 3 warnings that I wanted to get rid of.

W3C feed validation result

Fixing the feed

I compared the code in the post to my own to see if I could spot any differences that might help. 

1. Item should contain a guid element

This error was down to the construction of the SyndicationItem (blog posts).

 \\ My code
 var item = new SyndicationItem(title, description, new Uri(postUrl));
 
 \\ Mitchel's code
 var item = new SyndicationItem(title, description, new Uri(postUrl), item.UrlSlug, item.PostDate));

We used different parameters when constructing the SyndicationItem, the fourth parameter named id was missing in mine. Adding this, it removed the warning.

2. Avoid Namespace Prefix: a10

It turns out I was creating a new instance of Rss20FeedFormatter differently.

 var feed = new SyndicationFeed("I am Bacon - Blog", "My blog", new Url("https://iambacon.co.uk/blog"), "https://iambacon.co.uk/feed", DateTime.Now);
 
 \\ My code
 var feedFormatter = new Rss20FeedFormatter(feed);
 
 \\ Mitchel's code
 var rssFormatter = new Rss20FeedFormatter(feed, false);

Notice I am only passing the SyndicationFeed into the constructor. The description for the boolean parameter named serializeExtensionsAsAtom is.

A value that specifies whether to serialize elements that are defined in the Atom 1.0 specification but not in the RSS 2.0 specification. The default value is true.

This was adding the Atom namespace to the feed.

 <rss xmlns:a10="http://www.w3.org/2005/Atom" version="2.0">

With serializeExtensionsAsAtom set to false it removed the namespace and the warning had gone.

This one was trickier. The explanation from the feed validator documentation is.

According to the RSS Advisory Board's Best Practices Profile, identifying a feed's URL within the feed makes it more portable, self-contained, and easier to cache. For these reasons, a feed should contain an atom:link used for this purpose.

And the proposed solution, declaring the Atom namespace at the top of the feed, like so:

 <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">

First attempt

It is possible to add links to the feed by creating a SyndicationLink and adding it to the SyndicationFeed. In fact SyndicationLink has a method called CreateSelfLink. Perfect! 

 feed.Links.Add(SyndicationLink.CreateSelfLink(new Uri("https://iambacon.co.uk/feed")));

After adding this line of code, I tested the feed. Nothing was different, it did not include the link. If you remember earlier, I had changed the instantiation of Rss20FeedFormatter. The code now looked like this :

 var rssFormatter = new Rss20FeedFormatter(feed, false);

I was now passing false into the constructor for the parameter named serializeExtensionsAsAtom. To remind you, this is the description for that parameter.

A value that specifies whether to serialize elements that are defined in the Atom 1.0 specification but not in the RSS 2.0 specification. The default value is true.

By setting serializeExtensionsAsAtom to false, elements defined in the Atom 1.0 specification but not in the RSS 2.0 specification will be ignored.  This was happening with the self link I added. Setting it to true, the link appeared but then the Avoid Namespace Prefix: a10 warning reappeared. This was a catch-22 situation, I needed another solution.

Final solution

After much searching and not coming up with much, I stumbled upon an answer from 2013. SyndicationFeed has an SyndicationElementExtensionCollection which you can add elements to. Essentially, you can create any element and add it.

 XNamespace atom = "http://www.w3.org/2005/Atom";
    feed.ElementExtensions.Add(
        new XElement(atom + "link",
        new XAttribute("href", "https://iambacon.co.uk/feed"),
        new XAttribute("rel", "self"),
        new XAttribute("type", "application/rss+xml")));

Here, I have created an atom:link with rel-"self" and added it to the feed ElementExtensions collection. Now the link appears in the feed, and the warning has gone! 

Summary

Implementing syndication feeds in .NET has changed little, if at all. There are a lot of posts out there that show a working implementation of a feed, but the result will have validation warnings. Luckily, I found this excellent post, that helped me remove two validation warnings I had. The final warning was a pain to get rid of but the result is a valid RSS feed!

Icon made by Freepik from www.flaticon.com