RSS Feeds ใน ASP.NET MVC


113

คุณจะแนะนำการจัดการ RSS Feeds ใน ASP.NET MVC ได้อย่างไร ใช้ไลบรารีของบุคคลที่สาม? ใช้ RSS stuff ใน BCL หรือไม่? เพียงแค่สร้างมุมมอง RSS ที่แสดง XML? หรือสิ่งที่แตกต่างอย่างสิ้นเชิง?


การใช้ RssToolkit คุณต้องมีไฟล์. asx ไฟล์เดียวในโปรเจ็กต์ของคุณเพื่อสร้าง RSS feed จากนั้นคุณสามารถเขียน URL ใหม่เป็น URL ที่จำง่าย ฉันคิดว่าไม่มีอะไรต่อต้าน MVC ในแนวทางนี้
Mahdi Taghizadeh

นี่คือโพสต์ติดตามผลที่นำแนวคิด RssActionResult ไปอีกเล็กน้อยด้วยคลาสผลลัพธ์ SyndicationAction ทั่วไปรวมถึงตัวกรองรับเงื่อนไขแบบ NotModified 304 58bits.com/blog/…
Blue Waters

ฉันได้เขียน RssResult ซึ่งคุณสามารถดูได้หากต้องการ ควรเป็นไปตามข้อกำหนดของคุณhttp://www.wduffy.co.uk/blog/rssresult-aspnet-mvc-rss-actionresult/
WDuffy

1
เพียงเพื่ออัปเดตคำถามนี้เมื่อ 18 เดือนหลังจากการแก้ไขครั้งล่าสุด - ดูเหมือนว่าสมเหตุสมผลที่จะตั้งคำถามว่า 'มีสิ่งต่างๆเปลี่ยนแปลงไปจากการทำซ้ำทั้ง. net และ mvc ซึ่งจะเปลี่ยนวิธีที่เราแก้ไขปัญหาในการจัดการฟีด'? ฉันทามติ (ผ่านเธรด SO อื่น) คือ 'ไม่มีการเปลี่ยนแปลงพื้นฐาน - นี่ยังคงเป็นทางเลือกที่ดีที่สุดของคุณ'
justSteve

ข้อเสนอแนะที่ไม่ดีสำหรับ ASP.NET MVC
tugberk

คำตอบ:


64

นี่คือสิ่งที่ฉันแนะนำ:

  1. สร้างคลาสที่เรียกว่า RssResult ที่สืบทอดจากคลาสพื้นฐานที่เป็นนามธรรม ActionResult
  2. แทนที่เมธอด ExecuteResult
  3. ExecuteResult มี ControllerContext ส่งผ่านไปยังผู้โทรและด้วยสิ่งนี้คุณจะได้รับข้อมูลและประเภทเนื้อหา
  4. เมื่อคุณเปลี่ยนประเภทเนื้อหาเป็น rss คุณจะต้องทำให้ข้อมูลเป็นอนุกรมเป็น RSS (โดยใช้รหัสของคุณเองหรือไลบรารีอื่น) และเขียนตอบกลับ

  5. สร้างการดำเนินการบนคอนโทรลเลอร์ที่คุณต้องการส่งคืน rss และตั้งค่าประเภทการส่งคืนเป็น RssResult รับข้อมูลจากแบบจำลองของคุณตามสิ่งที่คุณต้องการส่งคืน

  6. จากนั้นคำขอใด ๆ ในการดำเนินการนี้จะได้รับ rss ของข้อมูลที่คุณเลือก

นั่นอาจเป็นวิธีที่เร็วที่สุดและสามารถใช้ซ้ำได้ในการส่งคืน rss มีการตอบสนองต่อคำขอใน ASP.NET MVC


10
Hanselman มีวิธีแก้ปัญหาที่คล้ายกัน (วิดีโอ: เริ่มต้นประมาณ 41 นาที) ซึ่งเขาได้รับมรดกจาก FileResult โดยการทำเช่นนี้คุณสามารถเรียกใช้คอนสตรัคเตอร์ของชั้นเรียนbase("application/rss+xml")และหลีกเลี่ยงขั้นตอนที่ 3 และ 4 เขาจะแทนที่ ExecuteResult แต่ก็ไม่สำคัญ นอกจากนี้เขายังลัดมากรหัสมักจะ-พื้นเมืองและใช้คุณสมบัติของ 3.5+ SyndicateItem, และSyndicateFeed Rss20FeedFormatter
patridge

@ เดล: เป็นไปได้ไหมที่จะเขียนตอบกลับเมื่อคุณต้องการส่งออกเพื่อป้อนข้อมูลไปยังมุมมองบางส่วน? ขอบคุณ
Christian

1
อัปเดตลิงค์ของวิดีโอของ Hanselmanจากความคิดเห็นก่อนหน้าของฉัน
patridge

150

NET framework จะแสดงคลาสที่จัดการ syndation: SyndicationFeed เป็นต้นดังนั้นแทนที่จะทำการเรนเดอร์ด้วยตัวเองหรือใช้ไลบรารี RSS อื่น ๆ ที่แนะนำทำไมไม่ปล่อยให้ Framework ดูแลมันล่ะ?

โดยพื้นฐานแล้วคุณต้องมี ActionResult ที่กำหนดเองต่อไปนี้และคุณก็พร้อมที่จะไป:

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

ตอนนี้ในการดำเนินการควบคุมของคุณคุณสามารถคืนค่าสิ่งต่อไปนี้:

return new RssActionResult() { Feed = myFeedInstance };

มีตัวอย่างเต็มในบล็อกของฉันที่http://www.developerzen.com/2009/01/11/aspnet-mvc-rss-feed-action-result/


34

ฉันเห็นด้วยกับ Haacked ขณะนี้ฉันกำลังใช้งานไซต์ / บล็อกของฉันโดยใช้กรอบงาน MVC และฉันใช้วิธีง่ายๆในการสร้าง View ใหม่สำหรับ 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>

สำหรับข้อมูลเพิ่มเติมโปรดดู (ปลั๊กไร้ยางอาย) http://rickyrosario.com/blog/creating-an-rss-feed-in-asp-net-mvc


4
สำหรับการใช้ Razor: @model PageModel @ {Response.ContentType = "application / rss + xml"; } <? xml version = "1.0" encoding = "UTF-8"?>
Anthony Johnston

2
ค่าใช้จ่ายอะไร? คุณหมายถึงความจริงที่ว่าคุณเขียนโค้ดน้อยลงเพื่อทำสิ่งเดียวกันให้สำเร็จด้วยวิธีที่อ่านได้ง่ายขึ้น?
พอล

12

อีกวิธีหนึ่งที่บ้าคลั่ง แต่มีข้อได้เปรียบคือการใช้มุมมอง. aspx ปกติเพื่อแสดงผล RSS ในวิธีการดำเนินการของคุณเพียงตั้งค่าประเภทเนื้อหาที่เหมาะสม ข้อดีอย่างหนึ่งของแนวทางนี้คือง่ายต่อการทำความเข้าใจว่ากำลังแสดงผลอะไรอยู่และจะเพิ่มองค์ประกอบที่กำหนดเองเช่นตำแหน่งทางภูมิศาสตร์ได้อย่างไร

จากนั้นอีกครั้งวิธีการอื่น ๆ ที่ระบุไว้อาจดีกว่าฉันไม่ได้ใช้ ;)


3
@ แฮ็ก: โลกนี้เต็มไปด้วย RSS XML ที่ไม่ถูกต้องที่สร้างขึ้นโดยระบบเทมเพลต กรุณาอย่าเพิ่มความยุ่ง! Ricky การเข้ารหัส HTML! = การเข้ารหัส XML
Brad Wilson

ด้านล่างนี้เป็นเอกสารของการเข้ารหัส Html จาก MSDN:> เนื่องจากรายละเอียดการใช้งานปัจจุบันสามารถใช้ฟังก์ชันนี้เป็นฟังก์ชัน xmlEncode ได้ ปัจจุบันเอนทิตีที่มีชื่อทั้งหมดที่ใช้โดยฟังก์ชันนี้ยังเป็นเอนทิตีที่มีชื่อที่กำหนดไว้ล่วงหน้า xml พวกเขา <> "& เข้ารหัสเป็น & lt; & gt; & quot; และ & amp; เอนทิตีอื่น ๆ มีการเข้ารหัสทศนิยมเช่น & # 160; http://msdn.microsoft.com/en-us/library/73z22y6h.aspx
Ricky

คุณจะมั่นใจได้อย่างไรว่า XML ถูกต้องโดยทำเช่นนี้ คงจะดีไม่น้อยหากการแสดงผลมุมมองถูกแยกออกจากคำขอทางเว็บที่เข้ามาเพื่อสร้างมุมมอง XML หรือเทมเพลตอีเมลเช่นทับทิมบนรางที่ทำได้
Paco

แทนที่จะใช้ view engine คุณสามารถสร้าง RssResult ที่มาจาก ActionResult เราทำสิ่งนี้ด้วย JsonResult ซึ่งทำให้วัตถุเป็นอนุกรมเป็น JSON ในกรณีของคุณคุณจะพบ serializer (ฉันคิดว่า WCF มีอยู่) ที่ทำให้เป็นอนุกรมกับ RSS
เลิก

8

ฉันได้รับสิ่งนี้จาก Eran Kampf และ Scott Hanselman vid (ลืมลิงก์) ดังนั้นจึงแตกต่างจากโพสต์อื่น ๆ ที่นี่เพียงเล็กน้อย แต่หวังว่าจะเป็นประโยชน์และคัดลอกวางพร้อมเป็นฟีด rss ตัวอย่าง

จากบล็อกของฉัน

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

และรหัสผู้ควบคุม ....

    [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()));

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.