Skip to content

Instantly share code, notes, and snippets.

@AaronSadlerUK
Last active October 27, 2021 14:54
Show Gist options
  • Select an option

  • Save AaronSadlerUK/4169ab6207557fdf13a4b3c8d701f654 to your computer and use it in GitHub Desktop.

Select an option

Save AaronSadlerUK/4169ab6207557fdf13a4b3c8d701f654 to your computer and use it in GitHub Desktop.
How to create an RSS & Atom feed in Umbraco V9
using System.ServiceModel.Syndication;
public interface ISyndicationXmlService
{
Atom10FeedFormatter GenerateAtomXml(string feedTitle, string feedDescription);
Rss20FeedFormatter GenerateRssXml(string feedTitle, string feedDescription);
}
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
public class RegisterServicesComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.Services.AddTransient<ISyndicationXmlService, SyndicationXmlService>();
}
}
using System.IO;
using System.Text;
using System.Xml;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Logging;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.Web;
using Umbraco.Cms.Infrastructure.Persistence;
using Umbraco.Cms.Web.Website.Controllers;
public class SyndicationSurfaceController : SurfaceController
{
private readonly ISyndicationXmlService _syndicationXmlService;
private readonly XmlWriterSettings _xmlWriterSettings = new()
{
Encoding = Encoding.UTF8,
NewLineHandling = NewLineHandling.Entitize,
NewLineOnAttributes = true,
Indent = true
};
[Route("blog/feed.rss")]
[ResponseCache(Duration = 900)]
public FileContentResult Rss()
{
using var stream = new MemoryStream();
using (var xmlWriter = XmlWriter.Create(stream, _xmlWriterSettings))
{
var feed = _syndicationXmlService.GenerateRssXml("My RSS Feed Title", "My RSS Feed Description");
feed.WriteTo(xmlWriter);
xmlWriter.Flush();
}
return File(stream.ToArray(), "application/rss+xml; charset=utf-8");
}
[Route("blog/feed.atom")]
[ResponseCache(Duration = 900)]
public FileContentResult Atom()
{
using var stream = new MemoryStream();
using (var xmlWriter = XmlWriter.Create(stream, _xmlWriterSettings))
{
var feed = _syndicationXmlService.GenerateAtomXml("My Atom Feed Title", "My Atom Feed Description");
feed.WriteTo(xmlWriter);
xmlWriter.Flush();
}
return File(stream.ToArray(), "application/atom+xml; charset=utf-8");
}
public SyndicationSurfaceController(IUmbracoContextAccessor umbracoContextAccessor, IUmbracoDatabaseFactory databaseFactory, ServiceContext services, AppCaches appCaches, IProfilingLogger profilingLogger, IPublishedUrlProvider publishedUrlProvider, ISyndicationXmlService syndicationXmlService)
: base(umbracoContextAccessor, databaseFactory, services, appCaches, profilingLogger, publishedUrlProvider)
{
_syndicationXmlService = syndicationXmlService;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using Umbraco.Cms.Core.Models.PublishedContent;
using Umbraco.Cms.Core.Web;
using Umbraco.Extensions;
public class SyndicationXmlService : ISyndicationXmlService
{
private readonly IUmbracoContextFactory _umbracoContextFactory;
public SyndicationXmlService(IUmbracoContextFactory umbracoContextFactory)
{
_umbracoContextFactory = umbracoContextFactory;
}
public Rss20FeedFormatter GenerateRssXml(string feedTitle, string feedDescription)
{
return new Rss20FeedFormatter(GenerateSyndicationFeed(feedTitle, feedDescription));
}
public Atom10FeedFormatter GenerateAtomXml(string feedTitle, string feedDescription)
{
return new Atom10FeedFormatter(GenerateSyndicationFeed(feedTitle, feedDescription));
}
private SyndicationFeed GenerateSyndicationFeed(string feedTitle, string feedDescription)
{
using var context = _umbracoContextFactory.EnsureUmbracoContext().UmbracoContext;
var feed = new SyndicationFeed(feedTitle, feedDescription,
new Uri(context.CleanedUmbracoUrl.GetLeftPart(UriPartial.Authority)),
context.OriginalRequestUrl.AbsoluteUri,,
DateTime.Now)
{
Copyright = new TextSyndicationContent($"{DateTime.Now.Year} Copyright Name")
};
var rootNode = context.Content.GetByXPath("//home").First().FirstChild<Blog>();
var nodes = rootNode
.Descendants<BlogPost>()
.Where(x => x.HasTemplate())
.Where(x => x.IsVisible())
.Where(x => x.Value<bool>("hideFromXmlSyndication") == false);
var items = new List<SyndicationItem>();
foreach (var node in nodes)
{
var title = !string.IsNullOrEmpty(node.Heading) ? node.Heading : node.Name;
var description = new TextSyndicationContent(node.Introduction);
items.Add(
new SyndicationItem(
title,
description,
new Uri(node.Url(null, UrlMode.Absolute)),
node.UrlSegment(),
node.CreateDate));
}
feed.Items = items;
return feed;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment