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

C# ASP.NET 動態產生 RSS 2.0 Feed 完整實作

     編輯:關於C語言

前言

RSS (Really Simple Syndication) 是內容聚合的標準格式。本文示範在 ASP.NET (Web Forms / MVC / Core) 中動態產生 RSS 2.0 XML,涵蓋資料存取、XML 結構組裝、Content-Type 設定、CDATA 處理、日期格式標準化等關鍵細節。

RSS 2.0 結構速覽

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>網站標題</title>
    <link>https://example.com</link>
    <description>網站描述</description>
    <language>zh-TW</language>
    <lastBuildDate>Mon, 01 Jan 2024 12:00:00 +0800</lastBuildDate>
    <item>
      <title><![CDATA[文章標題]]></title>
      <link>https://example.com/article/123</link>
      <description><![CDATA[文章摘要或全文]]></description>
      <pubDate>Mon, 01 Jan 2024 10:30:00 +0800</pubDate>
      <guid isPermaLink="true">https://example.com/article/123</guid>
      <category>分類名稱</category>
    </item>
    ...
  </channel>
</rss>

ASP.NET Core 現代化實作 (推薦)

// Program.cs / Startup.cs 註冊路由
app.MapGet("/rss", async (HttpContext ctx, IArticleService articles) =>
{
    var items = await articles.GetLatestAsync(50); // 取最新 50 筆
    
    ctx.Response.ContentType = "application/rss+xml; charset=utf-8";
    
    var rss = new XDocument(
        new XDeclaration("1.0", "utf-8", "yes"),
        new XElement("rss",
            new XAttribute("version", "2.0"),
            new XElement("channel",
                new XElement("title", "我的技術部落格"),
                new XElement("link", "https://blog.example.com"),
                new XElement("description", "分享 .NET、架構、DevOps 實戰經驗"),
                new XElement("language", "zh-TW"),
                new XElement("lastBuildDate", DateTimeOffset.UtcNow.ToString("R")), // RFC 1123
                items.Select(a => new XElement("item",
                    new XElement("title", new XCData(a.Title)),
                    new XElement("link", a.Url),
                    new XElement("description", new XCData(a.Summary)),
                    new XElement("pubDate", a.PublishDate.ToString("R")),
                    new XElement("guid", a.Url, new XAttribute("isPermaLink", true)),
                    a.Category != null ? new XElement("category", a.Category) : null
                ))
            )
        )
    );
    
    await rss.SaveAsync(ctx.Response.Body, SaveOptions.None, ctx.RequestAborted);
});

ASP.NET Web Forms 傳統實作 (維護舊專案用)

// Rss.aspx.cs
public partial class Rss : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Clear();
        Response.ContentType = "application/rss+xml";
        Response.ContentEncoding = System.Text.Encoding.UTF8;
        
        var articles = ArticleService.GetLatest(50); // 自行實作資料存取
        
        var rss = new System.Xml.Linq.XDocument(
            new System.Xml.Linq.XDeclaration("1.0", "utf-8", "yes"),
            new System.Xml.Linq.XElement("rss",
                new System.Xml.Linq.XAttribute("version", "2.0"),
                new System.Xml.Linq.XElement("channel",
                    new System.Xml.Linq.XElement("title", "土人制造"),
                    new System.Xml.Linq.XElement("link", "https://www.socent.com"),
                    new System.Xml.Linq.XElement("description", "土人制造"),
                    articles.Select(a => new System.Xml.Linq.XElement("item",
                        new System.Xml.Linq.XElement("title", new System.Xml.Linq.XCData(a.Title)),
                        new System.Xml.Linq.XElement("link", $"https://www.socent.com/ArticleShow@{a.ID}.Html"),
                        new System.Xml.Linq.XElement("description", new System.Xml.Linq.XCData(a.Description)),
                        new System.Xml.Linq.XElement("copyright", "土人制造"),
                        new System.Xml.Linq.XElement("pubDate", a.AddDate.ToString("yyyy-MM-dd HH:mm")),
                        new System.Xml.Linq.XElement("comments", $"https://www.socent.com/CommentShow@{a.ID}.Html")
                    ))
                )
            )
        );
        
        rss.Save(Response.Output);
        Response.End();
    }
}

關鍵技術細節

1. 使用 LINQ to XML (XDocument) 而非字串拼接

  • 自動處理 XML 轉義(< → &lt;)、編碼宣告、縮排格式。
  • XCData 正確包裹含特殊字元的標題/描述,避免 XML 解析錯誤。
  • 型別安全、可讀性高、易於維護。

2. 日期格式必須符合 RFC 822 / RFC 1123

// 標準格式:Mon, 01 Jan 2024 12:00:00 GMT
string rfc1123 = DateTimeOffset.UtcNow.ToString("R"); // .NET 內建格式字串
// 或指定時區
string rfc1123 = DateTimeOffset.Now.ToString("ddd, dd MMM yyyy HH:mm:ss zzz");

原始碼使用 yyyy-MM-dd HH:mm 不符合 RSS 規範,部分閱讀器無法正確排序。

3. 必要的 Channel 子元素

元素必要性說明
title必要Feed 標題
link必要網站首頁網址
description必要Feed 描述
language建議如 zh-TW、en-US
lastBuildDate建議最後更新時間 (RFC 1123)
generator選用產生工具標識
ttl選用快取分鐘數,減少請求

4. Item 關鍵元素

  • guid:唯一識別碼,建議用完整網址並設 isPermaLink="true"。
  • pubDate:發布時間,RFC 1123 格式。
  • category:分類標籤,可多個。
  • enclosure:附件(Podcast 必備),需 url、length、type 屬性。

進階功能擴充

支援 Atom 連結自動發現

在網站 <head> 加入:

<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/rss" />

快取策略

// 伺服器端快取 10 分鐘
[ResponseCache(Duration = 600, Location = ResponseCacheLocation.Any)]
public async Task Rss() { ... }

內容加密/簽章 (可選)

  • 對 <item> 內容產生數位簽章,讓訂閱者驗證來源真實性。
  • 參考 RSS 2.0 Specification - Digital Signatures。

常見問題 FAQ

Q: 瀏覽器直接開啟 RSS 顯示原始碼而非訂閱介面?
A: 現代瀏覽器已移除內建 RSS 閱讀器。需安裝擴充功能(如 RSSHub Radar、Feedly)或使用獨立 RSS 閱讀器測試。
Q: 中文內容出現亂碼?
A: 確認 Response.ContentEncoding = UTF8、XML 宣告 encoding="utf-8"、資料庫連線字串含 Charset=utf8mb4。
Q: 圖片不顯示在 RSS 閱讀器中?
A: <description> 中的 <img> 標籤需使用絕對路徑(https://...),相對路徑在閱讀器中會失效。
Q: 如何支援 Podcast (iTunes)?
A: 加入 <itunes:...> 命名空間元素(author、summary、image、duration、explicit、category),並提供 enclosure 指向音訊檔。

總結

動態產生 RSS Feed 的核心在於:正確的 XML 結構 + 標準日期格式 + CDATA 保護內容 + 適當的 HTTP 標頭。現代 ASP.NET Core 專案建議使用 XDocument + MapGet 輕量實作;舊版 Web Forms 專案同樣適用 XDocument 取代字串拼接,大幅降低維護成本。

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