首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET 產生 RSS Feed:RssBase 元件完整實作與擴充

     編輯:關於ASP.NET

元件設計目標

  • 封裝 RSS 2.0 規範 (Channel、Item、Media 擴充)。
  • 支援媒體內容 (MediaRSS):圖片、影片、縮圖、版權。
  • 物件導向:`ItemInfo` 承載單篇內容中繼資料。
  • 靈活輸出:接受 `XmlTextWriter`,可寫入 `Response.OutputStream`、檔案、字串。

核心類別:RssBase

public class RssBase
{
 // 常數設定
 private const string TITLE = "MyMedia RSS";
 private const string LINK = "https://www.example.com/";
 private const string DESCRIPTION = "網站內容摘要";
 private const string LANGUAGE = "zh-TW";
 private const string COPYRIGHT = "Copyright 2024";
 private const string GENERATOR = "MyMedia RSS Generator";
 private const string IMAGE_URL = "https://www.example.com/logo.png";
 private const string IMAGE_TITLE = "MyMedia";
 private const string IMAGE_LINK = "https://www.example.com/";
 private const string XMLNS_MEDIA = "https://search.yahoo.com/mrss/";
 private const string XMLNS_DC = "https://purl.org/dc/elements/1.1/";

 // 內部狀態
 private XmlTextWriter _writer;
 private bool _hasMedia;
 private IList _items;

 // 建構子
 public RssBase(XmlTextWriter writer) : this(writer, false, null) { }
 public RssBase(XmlTextWriter writer, bool hasMedia, IList items)
 {
 _writer = writer;
 _hasMedia = hasMedia;
 _items = items ?? new List();
 }

 // Item 資料模型
 [Serializable]
 public sealed class ItemInfo
 {
 public string ItemTitle { get; set; }
 public string ItemLink { get; set; }
 public string ItemDescription { get; set; }
 public string ItemPubDate { get; set; } = DateTime.Now.ToString("R"); // RFC 1123
 public string ItemAuthor { get; set; }
 public string ItemGuid { get; set; }
 // MediaRSS 欄位
 public string MediaContentUrl { get; set; }
 public string MediaTitle { get; set; }
 public string MediaDescription { get; set; }
 public string MediaThumbUrl { get; set; }
 public string MediaThumbWidth { get; set; }
 public string MediaThumbHeight { get; set; }
 public string MediaAuthor { get; set; }

 public ItemInfo() { }
 public ItemInfo(string title, string link, string desc, string pubDate, string author, string guid) { /* ... */ }
 public ItemInfo(string title, string link, string desc, string pubDate, string author, string guid,
 string mediaUrl, string mediaTitle, string mediaDesc, string thumbUrl, string thumbW, string thumbH, string mediaAuthor) { /* ... */ }
 }

 // 產生 RSS
 public void WriteRSS()
 {
 WritePrologue();
 foreach (var item in _items)
 {
 WriteItem(item);
 if (_hasMedia) WriteItemMedia(item);
 WriteItemEnd();
 }
 WriteEnd();
 _writer.Flush();
 }

 // 私有寫入方法 (節選)
 private void WritePrologue()
 {
 _writer.WriteStartDocument();
 _writer.WriteStartElement("rss");
 _writer.WriteAttributeString("version", "2.0");
 _writer.WriteAttributeString("xmlns:media", XMLNS_MEDIA);
 _writer.WriteAttributeString("xmlns:dc", XMLNS_DC);
 _writer.WriteStartElement("channel");
 _writer.WriteElementString("title", TITLE);
 _writer.WriteElementString("link", LINK);
 _writer.WriteElementString("description", DESCRIPTION);
 _writer.WriteElementString("language", LANGUAGE);
 _writer.WriteElementString("pubDate", DateTime.Now.ToString("R"));
 _writer.WriteElementString("lastBuildDate", DateTime.Now.ToString("R"));
 _writer.WriteElementString("generator", GENERATOR);
 _writer.WriteElementString("copyright", COPYRIGHT);
 // Image 區塊
 _writer.WriteStartElement("image");
 _writer.WriteElementString("url", IMAGE_URL);
 _writer.WriteElementString("title", IMAGE_TITLE);
 _writer.WriteElementString("link", IMAGE_LINK);
 _writer.WriteEndElement();
 }

 private void WriteItem(ItemInfo item)
 {
 _writer.WriteStartElement("item");
 _writer.WriteElementString("title", item.ItemTitle);
 _writer.WriteElementString("link", item.ItemLink);
 _writer.WriteStartElement("description");
 _writer.WriteCData(item.ItemDescription); // CDATA 避免 HTML 實體編碼
 _writer.WriteEndElement();
 _writer.WriteElementString("pubDate", item.ItemPubDate);
 _writer.WriteElementString("dc:date", item.ItemPubDate);
 _writer.WriteElementString("author", item.ItemAuthor);
 _writer.WriteStartElement("guid");
 _writer.WriteAttributeString("isPermaLink", "false");
 _writer.WriteString(item.ItemGuid);
 _writer.WriteEndElement();
 }

 private void WriteItemMedia(ItemInfo item)
 {
 if (string.IsNullOrEmpty(item.MediaContentUrl)) return;
 _writer.WriteStartElement("media", "content", XMLNS_MEDIA);
 _writer.WriteAttributeString("url", item.MediaContentUrl);
 _writer.WriteAttributeString("type", "image/jpeg"); // 或 video/mp4 等
 _writer.WriteEndElement();
 _writer.WriteElementString("media", "title", XMLNS_MEDIA, item.MediaTitle);
 _writer.WriteStartElement("media", "description", XMLNS_MEDIA);
 _writer.WriteAttributeString("type", "html");
 _writer.WriteString(item.MediaDescription);
 _writer.WriteEndElement();
 _writer.WriteStartElement("media", "thumbnail", XMLNS_MEDIA);
 _writer.WriteAttributeString("url", item.MediaThumbUrl);
 _writer.WriteAttributeString("width", item.MediaThumbWidth);
 _writer.WriteAttributeString("height", item.MediaThumbHeight);
 _writer.WriteEndElement();
 _writer.WriteStartElement("media", "credit", XMLNS_MEDIA);
 _writer.WriteAttributeString("role", "photographer");
 _writer.WriteString(item.MediaAuthor);
 _writer.WriteEndElement();
 }

 private void WriteItemEnd() => _writer.WriteEndElement(); // 
 private void WriteEnd()
 {
 _writer.WriteEndElement(); // 
 _writer.WriteEndElement(); // 
 _writer.WriteEndDocument();
 }
}

使用範例:產生 RSS 回應

public class RssHandler : IHttpHandler
{
 public void ProcessRequest(HttpContext context)
 {
 context.Response.ContentType = "application/rss+xml";
 context.Response.ContentEncoding = Encoding.UTF8;

 using (XmlTextWriter writer = new XmlTextWriter(context.Response.OutputStream, Encoding.UTF8))
 {
 writer.Formatting = Formatting.Indented;

 var items = new List
 {
 new RssBase.ItemInfo("文章標題 1", "https://example.com/post/1", "

摘要...

", DateTime.Now.ToString("R"), "作者", "guid-1", "https://example.com/img1.jpg", "圖片標題", "圖片描述", "https://example.com/thumb1.jpg", "120", "90", "攝影師"), new RssBase.ItemInfo("文章標題 2", "https://example.com/post/2", "

摘要...

", DateTime.Now.AddDays(-1).ToString("R"), "作者", "guid-2") }; var rss = new RssBase(writer, hasMedia: true, items: items); rss.WriteRSS(); } } public bool IsReusable => false; }

進階:動態從資料庫產生

// 在 Ashx 或 Controller 中
var items = db.Posts.Where(p => p.Published)
 .OrderByDescending(p => p.PubDate)
 .Take(20)
 .Select(p => new RssBase.ItemInfo
 {
 ItemTitle = p.Title,
 ItemLink = Url.Action("Detail", "Post", new { id = p.Id }, Request.Url.Scheme),
 ItemDescription = p.Summary,
 ItemPubDate = p.PubDate.ToString("R"),
 ItemAuthor = p.Author.Name,
 ItemGuid = p.Id.ToString(),
 MediaContentUrl = p.CoverImageUrl,
 MediaThumbUrl = p.ThumbnailUrl,
 MediaThumbWidth = "300",
 MediaThumbHeight = "200",
 MediaAuthor = p.Photographer
 }).ToList();

var rss = new RssBase(writer, true, items);
rss.WriteRSS();

RSS 2.0 關鍵規範提醒

  • `pubDate` 必須符合 RFC 822/1123 格式:`DateTime.ToString("R")`。
  • `` 建議使用 CDATA 區塊包裝 HTML 內容。
  • `guid` 的 `isPermaLink="false"` 表示非永久連結,僅作唯一識別碼。
  • MediaRSS 命名空間:`xmlns:media="https://search.yahoo.com/mrss/"`。
  • 輸出編碼統一 UTF-8,設定 `Response.ContentEncoding`。

現代替代:SyndicationFeed (System.ServiceModel.Syndication)

var feed = new SyndicationFeed("標題", "描述", new Uri("https://example.com/"), "feed-id", DateTimeOffset.Now);
feed.Items = posts.Select(p => new SyndicationItem(p.Title, p.Summary, new Uri(p.Url), p.Id, p.PubDate)
{
 Authors = { new SyndicationPerson(p.Author.Email, p.Author.Name, "") },
 PublishDate = p.PubDate
}).ToList();

var formatter = new Rss20FeedFormatter(feed);
using (XmlWriter writer = XmlWriter.Create(context.Response.OutputStream, new XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true }))
formatter.WriteTo(writer);

.NET Framework 3.5+ 內建,支援 Atom 1.0、RSS 2.0,物件模型更豐富,建議新專案優先使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved