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.
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.
3. Missing atom:link with rel="self"
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