Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create RSS feed in MVC4/WebAPI

I'm looking for the best way to create an RSS feed via MVC4 (and/or WebAPI). This post seemed the most applicable http://www.strathweb.com/2012/04/rss-atom-mediatypeformatter-for-asp-net-webapi/. But it was written in the pre-Release days of WebAPI. I've used Nuget to bring all packages up-to-date but attempting to build the project tosses:

Error   2   The type or namespace name 'FormatterContext' could not be found (are you missing a using directive or an assembly reference?)  G:\Code\MvcApplication-atomFormatter\MvcApplication-atomFormatter\SyndicationFeedFormatter.cs   38  129 MvcApplication_syndicationFeedFormatter

I've found a number of articles explaining that the MediaTypeFormatter has changed significantly since beta but I have found details on the adjustments required to the code snippet in question.

Is there an updated resource showing the construction of an RSSFormatter?

thx

like image 502
justSteve Avatar asked Sep 15 '12 13:09

justSteve


1 Answers

Yes I wrote that tutorial against Beta.

Below is the code updated to RTM version.

One advice, if I may, is that this example uses a simple "whitelist" of concrete types for which RSS/Atom feed is build (in this case my Url model). Ideally in more complex scenarios, you'd have the formatter set up against an interface, rather than a concrete type, and have all Models which are supposed to be exposed as RSS to implement that interface.

Hope this helps.

   public class SyndicationFeedFormatter : MediaTypeFormatter
    {
        private readonly string atom = "application/atom+xml";
        private readonly string rss = "application/rss+xml";

        public SyndicationFeedFormatter()
        {
            SupportedMediaTypes.Add(new MediaTypeHeaderValue(atom));
            SupportedMediaTypes.Add(new MediaTypeHeaderValue(rss));
        }

        Func<Type, bool> SupportedType = (type) =>
        {
            if (type == typeof(Url) || type == typeof(IEnumerable<Url>))
                return true;
            else
                return false;
        };

        public override bool CanReadType(Type type)
        {
            return SupportedType(type);
        }

        public override bool CanWriteType(Type type)
        {
            return SupportedType(type);
        }

        public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
        {
            return Task.Factory.StartNew(() =>
            {
                if (type == typeof(Url) || type == typeof(IEnumerable<Url>))
                    BuildSyndicationFeed(value, writeStream, content.Headers.ContentType.MediaType);
            });
        }

        private void BuildSyndicationFeed(object models, Stream stream, string contenttype)
        {
            List<SyndicationItem> items = new List<SyndicationItem>();
            var feed = new SyndicationFeed()
            {
                Title = new TextSyndicationContent("My Feed")
            };

            if (models is IEnumerable<Url>)
            {
                var enumerator = ((IEnumerable<Url>)models).GetEnumerator();
                while (enumerator.MoveNext())
                {
                    items.Add(BuildSyndicationItem(enumerator.Current));
                }
            }
            else
            {
                items.Add(BuildSyndicationItem((Url)models));
            }

            feed.Items = items;

            using (XmlWriter writer = XmlWriter.Create(stream))
            {
                if (string.Equals(contenttype, atom))
                {
                    Atom10FeedFormatter atomformatter = new Atom10FeedFormatter(feed);
                    atomformatter.WriteTo(writer);
                }
                else
                {
                    Rss20FeedFormatter rssformatter = new Rss20FeedFormatter(feed);
                    rssformatter.WriteTo(writer);
                }
            }
        }

        private SyndicationItem BuildSyndicationItem(Url u)
        {
            var item = new SyndicationItem()
            {
                Title = new TextSyndicationContent(u.Title),
                BaseUri = new Uri(u.Address),
                LastUpdatedTime = u.CreatedAt,
                Content = new TextSyndicationContent(u.Description)
            };
            item.Authors.Add(new SyndicationPerson() { Name = u.CreatedBy });
            return item;
        }
    }
like image 181
Filip W Avatar answered Nov 16 '22 04:11

Filip W