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
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 SupportedType = (type) => { if (type == typeof(Url) || type == typeof(IEnumerable)) 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)) BuildSyndicationFeed(value, writeStream, content.Headers.ContentType.MediaType); }); } private void BuildSyndicationFeed(object models, Stream stream, string contenttype) { List items = new List(); var feed = new SyndicationFeed() { Title = new TextSyndicationContent("My Feed") }; if (models is IEnumerable) { var enumerator = ((IEnumerable)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; } }