How do I make an RSS feed in Episerver?

  • Page Owner: Not Set
  • Last Reviewed: 2020-06-16

How do I make an RSS feed in Episerver?


Answer

Here's the RSS Feed Page from Calamos

RSSPageController.cs:

using Blend.Episerver;
using BlendInteractive.EPiServerSolr;
using Calamos.Base.Business.Solr;
using Calamos.Base.Controllers;
using Calamos.CalamosInvestments.Models.Pages;
using Calamos.CalamosInvestments.Models.Pages.ViewModels;
using EPiServer.Framework.DataAnnotations;
using EPiServer.Web.Mvc;
using SolrNet;
using System;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Xml;
using System.Xml.Linq;
​
namespace Calamos.CalamosInvestments.Controllers.Pages
{
    [TemplateDescriptor(AvailableWithoutTag = false, ModelType = typeof(BlogPage), Tags = new[] { "RSS" })]
    public class RssBlogPageController : PageController<BlogPage>
    {
        public RssBlogPageController()
        {
        }
​
        public RssActionResult Index(BlogPage currentPage)
        {
            var model = new BlogPageViewModel(currentPage);
​
            var query = this.DefaultSolrSearch(model);
​
            if (currentPage.FeaturedPostContentArea.HasValue())
                query.ExcludeIds(currentPage.FeaturedPostContentArea.AsContent<BlogPostPage>().Select(x => x.ContentLink));
​
            var searchResults = query.Search().Results.GetContentResult<SearchDocument, BlogPostPage>();
​
            var feed = CreateValidFeed(currentPage.Name, currentPage.GetFriendlyUrl(GetFriendlyUrlOption.UseSiteDefinitionHost | GetFriendlyUrlOption.IncludeHost), currentPage.Summary);
​
            feed.Items = searchResults.Select(ConvertToSyndicationItem);
​
            return new RssActionResult() { Feed = feed };
        }
​
        private IEPiServerSolrSearch<SearchDocument> DefaultSolrSearch(BlogPageViewModel model)
        {
            var query = new EPiServerSolrSearch<SearchDocument>()
                .IncludeContentTypeExact(typeof(BlogPostPage).Name)
                .AddFacetField(x => x.BlogCategories)
                .AddFacetField(x => x.BlogVerticals)
                .AddFacetField(x => x.BlogTags)
                .AddFacetField(x => x.Authors)
                .AddFilterForContentBranch(model.CurrentPage.ContentLink)
                .SortBy(x => x.PublicDate, Order.DESC)
                .PageIndex(1)
                .PageWeight(50);
​
            return query;
        }
​
        private SyndicationItem ConvertToSyndicationItem(BlogPostPage item)
        {
            return new SyndicationItem
            {
                Title = new TextSyndicationContent(item.Name),
                Id = item.GetFriendlyUrl(GetFriendlyUrlOption.UseSiteDefinitionHost),
                Content = new TextSyndicationContent(item.Summary),
                BaseUri = new Uri(item.GetFriendlyUrl(GetFriendlyUrlOption.UseSiteDefinitionHost)),
                PublishDate = item.StartPublish.Value
            };
        }
​
        private SyndicationFeed CreateValidFeed(string title, string url, string description)
        {
            var uri = new Uri(url);
​
            var feed = new SyndicationFeed()
            {
                Title = new TextSyndicationContent(title),
                Description = new TextSyndicationContent(description),
                BaseUri = uri,
                LastUpdatedTime = DateTime.Now,
                Language = "en-us",
            };
​
            XNamespace atom = "http://www.w3.org/2005/Atom";
            feed.AttributeExtensions.Add(new XmlQualifiedName("atom", XNamespace.Xmlns.NamespaceName), atom.NamespaceName);
            feed.ElementExtensions.Add(new XElement(atom + "link", new XAttribute("href", url), new XAttribute("rel", "self"), new XAttribute("type", "application/rss+xml")));
            feed.Links.Add(new SyndicationLink(uri, "alternate", "Link Title", "text/html", 1000));
​
            var formatter = feed.GetRss20Formatter();
            formatter.SerializeExtensionsAsAtom = false;
            return formatter.Feed;
        }
    }
}

RssActionResult.cs

using System.ServiceModel.Syndication;
using System.Text;
using System.Web.Mvc;
using System.Xml;

namespace Apta.Base.Model
{
    public class RssActionResult : ActionResult
    {
        public SyndicationFeed Feed { get; set; }

        public override void ExecuteResult(ControllerContext context)
        {
            context.HttpContext.Response.Clear();
            context.HttpContext.Response.ContentEncoding = Encoding.UTF8;
            context.HttpContext.Response.ContentType = "text/xml";

            Rss20FeedFormatter rssFormatter = new Rss20FeedFormatter(Feed);
            using (var writer = XmlWriter.Create(context.HttpContext.Response.Output))
            {
                rssFormatter.WriteTo(writer);
            }
        }
    }
}

Additional Posts

I solved this problem a few years back.

https://gitlab.blendinteractive.com/deane/RssFactory

RssFactory is just a generic RSS feed. EpiserverRssFactory wraps that for Episerver content.

Something like:

var rssFactory = new EpiserverRssFactory()
{
   Title = "whatever",
   TitleProperty = "PageName",
   SummaryProperty = "MainBody",
   // more properties here
};
rssFactory.Pages = myPages;  // It's an IList<PageData>
var rss = rssFactory.GetRss();