如何在ASP.NET中使用Syndication创建一个RSS源

前言

RSS(Really Simple Syndication)一词有时候仍大体上意为网摘,一个Syndication源采用已知的XML标准。因此,任何一台电脑都能解析Syndication数据,使用者输入RSS阅读器地址或是用滑鼠点取浏览器上指向订阅程序的RSS小图示之URI(非通常称为URL)来订阅网摘。RSS阅读器定期检阅使是否有更新,然后下载够监看用者介面。例如:cnblogs博客园-所有随笔区的阅读器更新了最近(最新)的40篇开发技术文章,你可以把它显示在你的博客。

.NET Framework在最新的3.5之前没有提供任何内置的功能,但在3.5推出System.ServiceModel.Syndication名称空间,其中一个核心类叫SyndicationFeed,它提供了如Title,Description,Links和Copyright详细信息,并通过其具体的Items属性的Item对象SyndicationItem提供详细内容。本文介绍了如何在ASP.NET3.5中使用System.ServiceModel.Syndication来为网站创建一个RSS Feeds。

版本

目前RSS规范的主要版本有0.91、1.0和2.0等。0.91版和1.0版完全不同,风格不同,制定标准的人也不同。0.91版和2.0版一脉相承。1.0版更接近XML标准。目前世界上大多数知名,虽有很多种不同的RSS,但都定型于两个重要的支干(RDF和2.*)。RDF或RSS 1.*的分支包括下列版本: RSS 0.90原本属于美国网景公司的版本。这个RSS被称为RDF Site Summary,但其基础构图建立在初期的RDF规格上,以及和末版的RDF推荐标准不相容。 RSS 1.0是一个开放式的版本,由RSS-DEV工作团队再次建立为RDF Site Summary。RSS 1.0是一个像RSS 0.90的RDF形式,但是并没有完全的和他相容,自从1.0基新闻网站都提供RSS订阅支持。

历史

RSS格式采纳之前有过几次web联合化的尝试,但都没有达到广泛的传播。关于重构web站点信息的基本思想可以追溯到早至1995年,当时Ramanathan V. Guha以及他在苹果公司高科技小组的同事开发出了元内容框架。对这些早期发展的更详细讨论,请参见网页联合供稿技术的历史

RSS的第一个版本为RDF Site Summary,在1999年三月由美国网景公司的Guha为了用在My.Netscape.Com 入口网站而开发。这个版本开始以RSS0.9为名。在1999年七月,美国网景公司的Dan Libby 发明了新版本RSS 0.91,此版本简化了形式,借由 撤去 RDF 元素及合并Dave Winer的 scriptingNews企业联合组织化格式。Libby并且将此重新命名为RSS,全名 "Rich Site Summary",并且在"futures document"论述了未来的发展形式。

这会是Netscape在RSS八年的研究中最后一次的参与,当RSS被一些想要他们的feeds被用在My.Netscape.Com 和其他早期 RSS入口的网路出版者环绕,美国“网景”公司下降RSS并支持 MY. Netscape.Com 在2001年四月期间新主人AOL的重建公司,还取消了支撑格式化的使用说明文件和工具。

创建Syndication RSS Feed网站

网站的RSS源可以是一个静态的XML文件(此方法是生成的静态文件),也可以是一个动态网页输出相应的XML标记,这里演示后者。

项目的结构图如下:

 sshot-1

新建一个Feed.aspx,.aspx页面如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Feed.aspx.cs" Inherits="Feed" %>
<%@ OutputCache Duration="60" VaryByParam="Type" %>

<%-- 因为不是网页,所以删除@ Page之后的HTML. 
     OutputCache表示当生成一次XML输出,在接下来的60分钟,其他请求XML的输出将存储于缓存中, –%>

然后,Feed.aspx Page_Load事件处理程序中的代码如下,数据库使用pubs 数据库,并使用LINQ to SQL作数据访问层:

 protected void Page_Load(object sender, EventArgs e)
    {
        // 获得图书表中的数据并pubdate降序排列
        PubsDataContext db = new PubsDataContext();
        var dataItems = from book in db.Titles
                        orderby book.pubdate descending
                        select book;

        // 确定显示在阅读器中最大列表数
        const int maxItemsInFeed = 10;

        // 确定是否输出一个Atom或RSS格式
        bool outputRss = (Request.QueryString["Type"] == "RSS");
        bool outputAtom = !outputRss;

        // 输出适当的ContentType
        if (outputRss)
            Response.ContentType = "application/rss+xml";
        else if (outputAtom)
            Response.ContentType = "application/atom+xml";

        // 创建RSS格式具体的属性
        SyndicationFeed myFeed = new SyndicationFeed();
        myFeed.Title = TextSyndicationContent.CreatePlaintextContent( "chinabooks.com图书网" );
        myFeed.Description = TextSyndicationContent.CreatePlaintextContent( "chinabooks.com图书网最新的图书." );
        myFeed.Links.Add(SyndicationLink.CreateAlternateLink(new Uri(GetFullyQualifiedUrl("~/Default.aspx"))));
        myFeed.Links.Add(SyndicationLink.CreateSelfLink(new Uri(GetFullyQualifiedUrl(Request.RawUrl))));
        myFeed.Copyright = TextSyndicationContent.CreatePlaintextContent( "版权所有chinabooks.com书店" );
        myFeed.Language = "en-us";

        // 创建并填充SyndicationItems
        List<SyndicationItem> feedItems = new List<SyndicationItem>();

        foreach (Title t in dataItems.Take(maxItemsInFeed))
        {
            // Atom items 必须要有author, 因此没有作者的这一项就跳到下一项
            if (outputAtom && t.TitleAuthors.Count == 0)
                continue;

            SyndicationItem item = new SyndicationItem();
            item.Title = TextSyndicationContent.CreatePlaintextContent(t.title1);
            item.Links.Add(SyndicationLink.CreateAlternateLink(new Uri(GetFullyQualifiedUrl("~/Titles.aspx"))));
            item.Summary = TextSyndicationContent.CreatePlaintextContent(t.notes);
            item.Categories.Add(new SyndicationCategory(t.type));
            item.PublishDate = t.pubdate;

            foreach (TitleAuthor ta in t.TitleAuthors)
            {
                SyndicationPerson authInfo = new SyndicationPerson();
                authInfo.Email = ta.Author.au_lname + "@example.com";
                authInfo.Name = ta.Author.au_lname+ta.Author.au_fname;
                item.Authors.Add(authInfo);

                // RSS源只能有一个作者,所以退出循环。第一个作者已经添加
                if (outputRss)
                    break;
            }

            // 添加到feedItems
            feedItems.Add(item);
        }

        myFeed.Items = feedItems;

        // 用response返回XML数据源
        XmlWriterSettings outputSettings = new XmlWriterSettings();
        outputSettings.Indent = true; //(使用注释便于阅读)
        XmlWriter feedWriter = XmlWriter.Create(Response.OutputStream, outputSettings);

        if (outputAtom)
        {
            // 使用 Atom 1.0  格式标准      
            Atom10FeedFormatter atomFormatter = new Atom10FeedFormatter(myFeed);
            atomFormatter.WriteTo(feedWriter);
        }
        else if (outputRss)
        {
            // 否则使用 RSS 2.0 格式
            Rss20FeedFormatter rssFormatter = new Rss20FeedFormatter(myFeed);
            rssFormatter.WriteTo(feedWriter);
        }

        feedWriter.Close();
    }
结果
sshot-9 

从网站的一个页面上显示另一个网站的Syndication RSS Feed

除了创建一个SyndicationFeed外,还可以使用SyndicationFeed的Load方法获取另一个网站的RSS,比如博客园:http://www.cnblogs.com/all(具体代码请下载最后给出的项目):

sshot-2

接下来

记得在网站首页的头部新增meta链接到输出feed的HTML页面。使得小RSS图标发光的显示在Web浏览器地址栏中。

<link rel="Alternate" type="application/atom+xml" href="Feed.aspx?Type=Atom" />
<link rel="Alternate" type="application/rss+xml" href="Feed.aspx?Type=RSS" />
sshot-3 

最后

Thanks Scott Mitchell,

下载项目Source 539K

posted @ 2009-02-24 17:49  真见  阅读(2349)  评论(2编辑  收藏  举报