Blazor with an RSS Feed

5/30/2022

If you run a blog like this or any other website and you would like to expose a RSS Feed (like this very website) in your Blazor or any ASP.NET Core application you can do this with ease. We will use the help of a package named System.ServiceModel.Syndication.

And Blazor Webassembly?

The guide will only work on hosted versions of ASP.NET Core as Blazor Server is. If you host your Blazor WASM application on a GitHub page then this will not work. If you deliver your Blazor WASM via ASP.NET Core then go for it (in Visual Studio it is called ASP.NET Core hosted). The reason is that we need an active ASP.NET Core Server running for a controller which we have to create.

The Controller

The first thought might be that we render some kind of RSS feed inside a razor view, but that will not work for two reasons:

  1. We can't set a content type for a Blazor component / page.
  2. Even if we could it will be tricky to remove all the other stuff and have the XML structure of a normal RSS feed.

To do this we do the "old" ASP.NET Core way of doing things. We just add support for controllers in our Blazor App. For that go either to your Startup.cs or Program.cs and extend WebApplication with the following:

app.UseRouting();

app.MapControllers(); // Add the controller support here

app.MapBlazorHub();

Now that was easy, wasn't it? And the best thing is that we are halfway done.

Nuget package to the rescue

I don't want to deal with how a RSS feed is exactly formed. Which means I don't want to create the xml file on my own. And we don't have to, because there is a nice package called System.ServiceModel.Syndication. This does all the magic for us. So let's include this to our project.

Create the controller

Let's create a new class called RssFeedController which has the following content:

using Microsoft.AspNetCore.Mvc;

namespace BlazorRSSFeed.Controller;

public class RssFeedController : ControllerBase
{
    [ResponseCache(Duration = 1200)]
    [HttpGet]
    [Route("feed.rss")]
    public async Task<IActionResult> GetRssFeed()
    {
        return Accepted();
    }
}

Now the ResponseCache of course is optional. I just wanted to highlight that you can take the "normal" ASP.NET Core stuff as in any other Web API project. RSS Feeds are normal GET request and we defined the route via: [Route("feed.rss")]. Now if we hit compile and go to our browser and go to our endpoint like that: https://localhost:7207/feed.rss we see an empty page. That is good because it is working as expected.

Now let's fill the content:

public async Task<IActionResult> GetRssFeed()
{
    // Get the current url
    var url = $"{Request.Scheme}://{Request.Host}{Request.PathBase}";
    
    // This object reflects our RSS feed root item
    var feed = new SyndicationFeed(
        "Title",
        "This is a sample title",
        new Uri(url))
    {
        // You could create a list here of your blog posts for example
        Items = new[]
        {
            new SyndicationItem(
                "A Blog Post",
                "Somecontent",
                new Uri(url + "/url-to-your-sub-item"))
        }
    };

    // Create the XML Writer with it's settings
    var settings = new XmlWriterSettings
    {
        Encoding = Encoding.UTF8,
        NewLineHandling = NewLineHandling.Entitize,
        NewLineOnAttributes = true,
        Indent = true, // Makes it easier to read for humans
        Async = true, // You can omit this if you don't use the async API
    };

    using var stream = new MemoryStream();
    await using var xmlWriter = XmlWriter.Create(stream, settings);
    // Create the RSS Feed
    var rssFormatter = new Rss20FeedFormatter(feed, false);
    rssFormatter.WriteTo(xmlWriter);
    await xmlWriter.FlushAsync();

    return File(stream.ToArray(), "application/rss+xml; charset=utf-8");
}

The result

If we know go again to our RSS feed in the browser, we will see the follwing:

<?xml version="1.0" encoding="utf-8"?>
<rss
  version="2.0">
  <channel>
    <title>Title</title>
    <link>https://localhost:7207/</link>
    <description>This is a sample title</description>
    <item>
      <link>https://localhost:7207/url-to-your-sub-item</link>
      <title>A Blog Post</title>
      <description>Somecontent</description>
    </item>
  </channel>
</rss>

Resources

  • The code for this blog post can be found here
  • The majority of code samples can be found here
  • The implementation for this very blog can be found here

.NET 8 and Blazor United / Server-side rendering

New .NET and new Blazor features. In this blog post, I want to highlight the new features that are hitting us with .NET 8 in the Blazor world. So let's see what's new.

Prerendering Blazor Apps - How does it work / tips and tricks

Blazor comes with the option to prerender your webpage on the server. This works for the client-side version as well as the server side version of Blazor.

Let's have a look how does it work and what might be some pitfalls and how can we come around those.

Blazor Project Structure

Did you ever wonder what is a nice way of structuring your Blazor application?

I will show you how I structure my Blazor projects (as well as this very blog). What are the upside in contrast to the "default" structuring you get with the Blazor template.

An error has occurred. This application may no longer respond until reloaded. Reload x