RSS-Feeds in ASP.NET MVC

113

Wie würden Sie den Umgang mit RSS-Feeds in ASP.NET MVC empfehlen? Verwenden Sie eine Drittanbieter-Bibliothek? Verwenden Sie das RSS-Zeug in der BCL? Nur eine RSS-Ansicht erstellen, die das XML rendert? Oder etwas ganz anderes?

Lance Fisher
quelle
Mit RssToolkit benötigen Sie nur eine einzige .ashx-Datei in Ihrem Projekt, um einen RSS-Feed zu generieren. Dann können Sie die URL in eine freundliche URL umschreiben. Ich denke, es gibt nichts gegen MVC in diesem Ansatz.
Mahdi Taghizadeh
Hier ist ein Follow-up-Beitrag, der die RssActionResult-Idee mit einer verallgemeinerten SyndicationAction-Ergebnisklasse sowie einem 304 NotModified-Filter für bedingte Abrufe ein Stück weiter bringt. 58bits.com/blog/…
Blue Waters
Ich habe ein RssResult geschrieben, das Sie sich ansehen können, wenn Sie möchten. Es sollte Ihren Anforderungen entsprechen http://www.wduffy.co.uk/blog/rssresult-aspnet-mvc-rss-actionresult/
WDuffy
1
Nur um diese Frage ab 18 Monaten nach der letzten Bearbeitung zu aktualisieren - Es schien vernünftig zu sein, die Frage zu stellen, ob sich die Iterationen von .net und mvc geändert haben, um unsere Herangehensweise an das Problem der Feed-Verwaltung zu ändern. Der Konsens (über einen anderen SO-Thread) lautet: "Keine grundlegenden Änderungen - dies bleibt Ihre beste Auswahl an Alternativen."
JustSteve
schlechter Vorschlag für ASP.NET MVC.
Tugberk

Antworten:

64

Folgendes empfehle ich:

  1. Erstellen Sie eine Klasse namens RssResult, die von der abstrakten Basisklasse ActionResult erbt.
  2. Überschreiben Sie die ExecuteResult-Methode.
  3. ExecuteResult hat den ControllerContext vom Aufrufer übergeben und damit können Sie den Daten- und Inhaltstyp abrufen.
  4. Sobald Sie den Inhaltstyp in rss geändert haben, möchten Sie die Daten in RSS serialisieren (unter Verwendung Ihres eigenen Codes oder einer anderen Bibliothek) und in die Antwort schreiben.

  5. Erstellen Sie eine Aktion auf einem Controller, für den Sie RSS zurückgeben möchten, und legen Sie den Rückgabetyp als RssResult fest. Holen Sie sich die Daten aus Ihrem Modell basierend auf dem, was Sie zurückgeben möchten.

  6. Dann erhält jede Anfrage an diese Aktion RSS mit den von Ihnen ausgewählten Daten.

Dies ist wahrscheinlich die schnellste und wiederverwendbare Methode zur Rückgabe von RSS-Antworten auf eine Anforderung in ASP.NET MVC.

Dale Ragan
quelle
10
Hanselman hat eine ähnliche Lösung (Video: ab ca. 41 m), bei der er von FileResult erbt. Auf diese Weise können Sie den Konstruktoraufruf Ihrer Klasse base("application/rss+xml")ausführen und die Schritte 3 und 4 vermeiden. Er überschreibt zwar ExecuteResult, dies ist jedoch nicht unbedingt erforderlich. Er Kürzel auch viele typisch-homespun Code und verwendet die 3.5+ Eigenschaften SyndicateItem, SyndicateFeedund Rss20FeedFormatter.
Patridge
@Dale: Ist es möglich, in die Antwort zu schreiben, wenn Sie eine Ausgabe für eine Teilansicht ausgeben möchten? Vielen Dank.
Christian
1
Der Link zu Hanselmans Video wurde von meinem vorherigen Kommentar aktualisiert .
Patridge
150

Das .NET Framework stellt Klassen bereit, die sich mit der Syndierung befassen: SyndicationFeed usw. Anstatt das Rendering selbst durchzuführen oder eine andere vorgeschlagene RSS-Bibliothek zu verwenden, lassen Sie das Framework sich darum kümmern.

Grundsätzlich benötigen Sie nur das folgende benutzerdefinierte ActionResult und können loslegen:

public class RssActionResult : ActionResult
{
    public SyndicationFeed Feed { get; set; }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.ContentType = "application/rss+xml";

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

Jetzt können Sie in Ihrer Controller-Aktion einfach Folgendes zurückgeben:

return new RssActionResult() { Feed = myFeedInstance };

Ein vollständiges Beispiel finden Sie in meinem Blog unter http://www.developerzen.com/2009/01/11/aspnet-mvc-rss-feed-action-result/.

Eran Kampf
quelle
34

Ich stimme Haacked zu. Ich implementiere derzeit meine Website / mein Blog mithilfe des MVC-Frameworks und habe den einfachen Ansatz gewählt, eine neue Ansicht für RSS zu erstellen:

<%@ Page ContentType="application/rss+xml" Language="C#" AutoEventWireup="true" CodeBehind="PostRSS.aspx.cs" Inherits="rr.web.Views.Blog.PostRSS" %><?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>ricky rosario's blog</title>
<link>http://<%= Request.Url.Host %></link>
<description>Blog RSS feed for rickyrosario.com</description>
<lastBuildDate><%= ViewData.Model.First().DatePublished.Value.ToUniversalTime().ToString("r") %></lastBuildDate>
<language>en-us</language>
<% foreach (Post p in ViewData.Model) { %>
    <item>
    <title><%= Html.Encode(p.Title) %></title>
    <link>http://<%= Request.Url.Host + Url.Action("ViewPostByName", new RouteValueDictionary(new { name = p.Name })) %></link>
    <guid>http://<%= Request.Url.Host + Url.Action("ViewPostByName", new RouteValueDictionary(new { name = p.Name })) %></guid>
    <pubDate><%= p.DatePublished.Value.ToUniversalTime().ToString("r") %></pubDate>
    <description><%= Html.Encode(p.Content) %></description>
    </item>
<% } %>
</channel>
</rss>

Weitere Informationen finden Sie unter (schamloser Stecker) http://rickyrosario.com/blog/creating-an-rss-feed-in-asp-net-mvc

Ricky
quelle
4
für Razor verwenden Sie: @model PageModel @ {Response.ContentType = "application / rss + xml"; } <? xml version = "1.0" encoding = "UTF-8"?>
Anthony Johnston
2
Welcher Aufwand? Sie meinen die Tatsache, dass Sie weniger Code schreiben, um dasselbe besser lesbar zu machen?
Paul
12

Ein anderer verrückter Ansatz, der jedoch seinen Vorteil hat, ist die Verwendung einer normalen ASPX-Ansicht zum Rendern des RSS. Legen Sie in Ihrer Aktionsmethode einfach den entsprechenden Inhaltstyp fest. Der einzige Vorteil dieses Ansatzes besteht darin, dass leicht zu verstehen ist, was gerendert wird und wie benutzerdefinierte Elemente wie die Geolokalisierung hinzugefügt werden.

Andererseits könnten die anderen aufgeführten Ansätze besser sein, ich habe sie einfach nicht verwendet. ;)

Gehackt
quelle
3
@Haacked: Die Welt ist voll von ungültigem RSS-XML, das von einem Template-System generiert wird. Bitte nicht zum Chaos hinzufügen! Ricky, HTML-Codierung! = XML-Codierung.
Brad Wilson
Nachfolgend finden Sie die Dokumentation zu Html Encode von MSDN:> Aufgrund der aktuellen Implementierungsdetails kann diese Funktion als xmlEncode-Funktion verwendet werden. Derzeit sind alle von dieser Funktion verwendeten benannten Entitäten auch vordefinierte XML-benannte Entitäten. Sie sind <> "& codiert als & lt; & gt; & quot; und & amp;. Andere Entitäten sind wie & # 160; dezimal codiert. Http://msdn.microsoft.com/en-us/library/73z22y6h.aspx
Ricky
Wie können Sie auf diese Weise sicherstellen, dass das XML gültig ist? Es wäre schön, wenn das Rendern von Ansichten von einer eingehenden Webanforderung entkoppelt wäre, um XML-Ansichten oder E-Mail-Vorlagen wie Ruby on Rails zu ermöglichen.
Paco
Anstatt eine Ansichts-Engine zu verwenden, können Sie ein RssResult erstellen, das von ActionResult abgeleitet ist. Wir tun dies mit dem JsonResult, das das Objekt in JSON serialisiert. In Ihrem Fall finden Sie einen Serializer (ich glaube, WCF hat einen), der zu RSS serialisiert.
Haacked
8

Ich habe dies von Eran Kampf und einem Scott Hanselman-Video erhalten (habe den Link vergessen), daher unterscheidet es sich nur geringfügig von einigen anderen Posts hier, ist aber hoffentlich hilfreich und kann als Beispiel für einen RSS-Feed kopiert und eingefügt werden.

Aus meinem Blog

Eran Kampf

using System;
using System.Collections.Generic;
using System.ServiceModel.Syndication;
using System.Web;
using System.Web.Mvc;
using System.Xml;

namespace MVC3JavaScript_3_2012.Rss
{
    public class RssFeed : FileResult
    {
        private Uri _currentUrl;
        private readonly string _title;
        private readonly string _description;
        private readonly List<SyndicationItem> _items;

        public RssFeed(string contentType, string title, string description, List<SyndicationItem> items)
            : base(contentType)
        {
            _title = title;
            _description = description;
            _items = items;
        }

        protected override void WriteFile(HttpResponseBase response)
        {
            var feed = new SyndicationFeed(title: this._title, description: _description, feedAlternateLink: _currentUrl,
                                           items: this._items);
            var formatter = new Rss20FeedFormatter(feed);
            using (var writer = XmlWriter.Create(response.Output))
            {
                formatter.WriteTo(writer);
            }
        }

        public override void ExecuteResult(ControllerContext context)
        {
            _currentUrl = context.RequestContext.HttpContext.Request.Url;
            base.ExecuteResult(context);
        }
    }
}

Und der Controller Code ....

    [HttpGet]
public ActionResult RssFeed()
{
    var items = new List<SyndicationItem>();
    for (int i = 0; i < 20; i++)
    {
        var item = new SyndicationItem()
        {
            Id = Guid.NewGuid().ToString(),
            Title = SyndicationContent.CreatePlaintextContent(String.Format("My Title {0}", Guid.NewGuid())),
            Content = SyndicationContent.CreateHtmlContent("Content The stuff."),
            PublishDate = DateTime.Now
        };
        item.Links.Add(SyndicationLink.CreateAlternateLink(new Uri("http://www.google.com")));//Nothing alternate about it. It is the MAIN link for the item.
        items.Add(item);
    }

    return new RssFeed(title: "Greatness",
                       items: items,
                       contentType: "application/rss+xml",
                       description: String.Format("Sooper Dooper {0}", Guid.NewGuid()));

}
TheDev6
quelle