RSS Feed di ASP.NET MVC

113

Bagaimana Anda merekomendasikan penanganan RSS Feed di ASP.NET MVC? Menggunakan perpustakaan pihak ketiga? Menggunakan barang RSS di BCL? Hanya membuat tampilan RSS yang menampilkan XML? Atau sesuatu yang sama sekali berbeda?

Lance Fisher
sumber
Menggunakan RssToolkit, Anda hanya perlu memiliki satu file .ashx dalam proyek Anda untuk menghasilkan RSS feed. Kemudian Anda dapat menulis ulang URL-nya menjadi URL yang ramah. Saya pikir tidak ada yang menentang MVC dalam pendekatan ini.
Mahdi Taghizadeh
Berikut adalah posting tindak lanjut yang membawa ide RssActionResult sedikit lebih jauh dengan kelas hasil SyndicationAction umum serta filter get bersyarat NotModified 304. 58bits.com/blog/…
Blue Waters
Saya telah menulis sebuah RssResult yang dapat Anda lihat jika Anda mau. Ini harus memenuhi persyaratan Anda http://www.wduffy.co.uk/blog/rssresult-aspnet-mvc-rss-actionresult/
WDuffy
1
Hanya untuk memperbarui pertanyaan ini pada 18 bulan setelah pengeditan terakhir - Tampaknya masuk akal untuk mempertanyakan 'apakah ada yang berubah dengan iterasi ke .net dan mvc yang akan mengubah cara kita mendekati masalah pengelolaan feed'? Konsensus (melalui thread SO yang berbeda) adalah, 'Tidak ada perubahan mendasar - ini tetap menjadi alternatif terbaik Anda.'
justSteve
saran buruk untuk ASP.NET MVC.
tugberk

Jawaban:

64

Inilah yang saya rekomendasikan:

  1. Buat kelas bernama RssResult yang mewarisi kelas dasar abstrak ActionResult.
  2. Ganti metode ExecuteResult.
  3. ExecuteResult memiliki ControllerContext yang diteruskan kepadanya oleh pemanggil dan dengan ini Anda bisa mendapatkan tipe data dan konten.
  4. Setelah Anda mengubah tipe konten menjadi rss, Anda akan ingin membuat serial data ke RSS (menggunakan kode Anda sendiri atau pustaka lain) dan menulis ke respon.

  5. Buat tindakan pada pengontrol yang ingin Anda kembalikan rssnya dan setel jenis kembalian sebagai RssResult. Ambil data dari model Anda berdasarkan apa yang ingin Anda kembalikan.

  6. Kemudian setiap permintaan untuk tindakan ini akan menerima rss data apa pun yang Anda pilih.

Itu mungkin cara tercepat dan dapat digunakan kembali untuk mengembalikan rss memiliki respons terhadap permintaan di ASP.NET MVC.

Dale Ragan
sumber
10
Hanselman memiliki solusi serupa (video: mulai sekitar 41m) di mana ia mewarisi dari FileResult. Dengan demikian, Anda dapat memiliki panggilan konstruktor kelas Anda base("application/rss+xml")dan menghindari langkah 3 dan 4. Dia menimpa ExecuteResult, tetapi itu tidak penting. Dia juga pintas banyak kode biasanya-tenunan sendiri dan menggunakan 3.5 + fitur SyndicateItem, SyndicateFeeddan Rss20FeedFormatter.
patridge
@Dale: apakah mungkin untuk menulis ke respons ketika Anda ingin mengeluarkan output ke umpan ke tampilan parsial? Terima kasih.
Christian
1
Tautan diperbarui video Hanselman dari komentar saya sebelumnya.
patridge
150

Kerangka .NET memperlihatkan kelas yang menangani sindasi: SyndicationFeed, dll. Jadi, alih-alih melakukan rendering sendiri atau menggunakan beberapa pustaka RSS yang disarankan, mengapa tidak membiarkan kerangka yang mengurusnya?

Pada dasarnya Anda hanya perlu ActionResult kustom berikut dan Anda siap untuk pergi:

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);
        }
    }
}

Sekarang dalam tindakan pengontrol Anda, Anda dapat mengembalikan yang berikut ini:

return new RssActionResult() { Feed = myFeedInstance };

Ada contoh lengkap di blog saya di http://www.developerzen.com/2009/01/11/aspnet-mvc-rss-feed-action-result/

Eran Kampf
sumber
34

Saya setuju dengan Haacked. Saat ini saya menerapkan situs / blog saya menggunakan kerangka kerja MVC dan saya menggunakan pendekatan sederhana dalam membuat Tampilan baru untuk RSS:

<%@ 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>

Untuk informasi lebih lanjut, lihat (steker tak tahu malu) http://rickyrosario.com/blog/creating-an-rss-feed-in-asp-net-mvc

Ricky
sumber
4
untuk penggunaan Razor: @model PageModel @ {Response.ContentType = "application / rss + xml"; } <? xml version = "1.0" encoding = "UTF-8"?>
Anthony Johnston
2
Overhead apa? maksud Anda fakta bahwa Anda menulis lebih sedikit kode untuk mencapai hal yang sama dengan cara yang lebih mudah dibaca?
Paul
12

Pendekatan gila lainnya, tetapi memiliki keuntungannya, adalah menggunakan tampilan .aspx normal untuk merender RSS. Dalam metode tindakan Anda, cukup setel jenis konten yang sesuai. Satu keuntungan dari pendekatan ini adalah mudah untuk memahami apa yang sedang dirender dan bagaimana menambahkan elemen kustom seperti geolocation.

Kemudian lagi, pendekatan lain yang terdaftar mungkin lebih baik, saya hanya belum menggunakannya. ;)

Haacked
sumber
3
@Haacked: Dunia ini penuh dengan XML RSS tidak valid yang dibuat oleh sistem template. Tolong jangan menambah kekacauan! Ricky, pengkodean HTML! = Pengkodean XML.
Brad Wilson
Di bawah ini adalah dokumentasi Encode Html dari MSDN:> Karena detail implementasi saat ini, fungsi ini dapat digunakan sebagai fungsi xmlEncode. Saat ini, semua entitas bernama yang digunakan oleh fungsi ini juga merupakan entitas bernama standar xml. Entitas tersebut <> "& dikodekan sebagai & lt; & gt; & quot; dan & amp ;. Entitas lain dikodekan desimal seperti & # 160 ;. http://msdn.microsoft.com/en-us/library/73z22y6h.aspx
Ricky
Bagaimana Anda bisa memastikan XML valid dengan cara ini? Alangkah baiknya jika rendering tampilan dipisahkan dari permintaan web yang masuk, untuk membuat tampilan XML, atau template email seperti done ruby ​​on rails.
Paco
Daripada menggunakan mesin tampilan, Anda dapat membuat RssResult yang berasal dari ActionResult. Kami melakukan ini dengan JsonResult yang membuat serial objek ke JSON. Dalam kasus Anda, Anda akan menemukan beberapa serializer (saya pikir WCF memilikinya) yang bersambung ke RSS.
Haacked
8

Saya mendapat ini dari Eran Kampf dan vid Scott Hanselman (lupa tautannya) jadi hanya sedikit berbeda dari beberapa posting lain di sini, tetapi semoga bermanfaat dan siap salin tempel sebagai contoh umpan rss.

Dari blog saya

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);
        }
    }
}

Dan Kode Pengontrol ....

    [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
sumber