程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 使用WCF和.NET Framework 3.5進行HTTP編程

使用WCF和.NET Framework 3.5進行HTTP編程

編輯:關於.NET

本文以 Visual Studio 2008 的預發布版為基礎。文中包含的所有信息均有 可能變更。

本文討論:

HTTP 消息基礎知識

在 URI 中添加 信息

WCF 和 HTTP

借助 WCF 使用 RSS 和 ATOM

本文使用 了以下技術:

Windows Communication Foundation

目錄

HTTP 消息基礎知識

表達其他信息

REST 和 Web

使 用 WCF 進行 HTTP 編程

WCF 約定中的 HTTP 動詞

綁定和承載

新的整合 API

創建 SyndicationFeed

總結

當它作 為 Microsoft® .NET Framework 3.0 的一部分首次發布時,Windows® Communication Foundation (WCF) 包含一個 Plain Old XML (POX) 的通用對象 模型,以及可以進行多種傳輸的 SOAP 消息。由於 WCF 也可以深入支持 WS-* Web 服務標准,因此它可以毫不費力地與其他現代服務平台進行互操作。.NET Framework 3.0 中的 WCF 具有高度可擴展性,而且擁有可靠的可管理性功能, 如消息記錄、活動跟蹤、服務限制、實例管理以及線程控制。

.NET Framework 3.5 中的 WCF 構建於 .NET Framework 3.0 的擴展點之上,從而為 構建符合 Web 原則的服務提供一流的支持。它包含一個易於使用的 HTTP 編程 模型、JavaScript Object Notation (JSON) 消息傳遞功能,以及新的整合 API ,使創建和使用整合的內容變得非常簡便。憑借此功能集,WCF 現已成為將服務 連接到 Web 客戶端的首選服務平台,不論這些客戶端是 ASP.NET AJAX 控件、 SilverlightTM 客戶端,還是浏覽器。這些功能在部分信任方案(如 ASP.NET 中等信任)中也可發揮作用,因此您可以在各種宿主環境中承載 WCF 服務。除 此之外,Visual Studio® 2008 中還集成了新的工具,極大地縮短了啟動和 運行服務所需的時間。

使 .NET Framework 3.5 中的 WCF 如此引人注目 的特色之一是,以 Web 為中心的通信與 SOAP 和 WS-* 標准組合到了一個服務 堆棧和對象模型中。這意味著您可以構建這樣一個服務,即采用 SOAP 和 WS-* 在企業內部或跨企業邊界進行通信,同時還可以將同一服務配置為使用 Web 協 議與外部通信。實際上,WCF 處理了服務中的煩瑣細節工作,這樣您可以更加專 注於服務所提供的功能。

本文介紹了 .NET Framework 3.5 中 WCF 的一 些以 Web 為中心的新功能。首先是關於 HTTP 和 Web 中的一些重要體系結構原 則的定級性討論,然後將為您介紹 WCF 中新的 HTTP 編程模型,最後是新的整 合 API。

HTTP 消息基礎知識

您可能幾乎每天都在使用 Web,但 有多少次會考慮使 Web 運轉起來的核心概念是什麼呢?我並不想重復關於體系 結構概念的內容,但結合到 Web 中的某些關鍵概念並不是那麼一目了然。在我 看來,要構建符合 Web 協議的服務,對這些原則有個很好的了解是第一步,也 是十分必要的。請記住,由於此主題的研究可長達一整本書,因此在本文中我將 僅提及一些要點。

HTTP 是 Web 的傳輸機制。HTTP 要求一種請求/響應 消息交換模式 (MEP)。您每次使用浏覽器導航到 Web 頁時都會發生下面這個過 程:您發出一個獲取資源的請求,然後一個包含該資源的響應將返回。HTTP 傳 輸會定義若干動詞(也稱為方法),將功能添加到請求/響應 MEP 上,如 GET、 POST、PUT 和 DELETE。為了清楚闡明 HTTP 動詞之間的某些差別,我們來看看 HTTP POST 是什麼樣的。下面是一個簡略的版本:

POST /myservice/PostAlbum HTTP 1.1
HOST: www.cloudsample.net
<albumInfo>
 <albumId>15</albumId>
</albumInfo>

這實際上只是一個發送給偵聽應用程序的 消息。在此例中,消息是發送到 http://www.cloudsamples.net/myservice/PostAlbum。消息還有一個負載,包 含的是 albumId 字段的值。概括地說,您可以將 HTTP POST 想象成是將負載發 送到偵聽應用程序的一種方法。

本例的負載十分簡單,我可以將整個負載表示成數字 15。要使其工作,接收 應用程序需要知道數字 15 是映射到 albumId 字段的值。這是 HTTP GET 中提 供的關鍵功能之一。比方說,這就是從先前的 HTTP POST 轉換到 HTTP GET 的 結果:

GET /myservice/GetAlbum/15 HTTP 1.1
HOST: www.cloudsamples.net

HTTP GET 是經過優化的 HTTP POST,它無需負載。實際上,URI 就是負載。 結果就是可以縮減消息的大小,從而縮短傳輸時間。縮減的消息以及對 URI 的 依賴性還可帶來其他的正面效應:它可以方便其他應用程序(如代理程序或浏覽 器)緩存先前針對同一資源的 HTTP GET 消息的結果。值得注意的是,對 HTTP GET 的使用比任何其他 HTTP 動詞都要頻繁得多。

HTTP GET 的核心是請 求獲取某個資源。為了闡明這一點,請想象您在網頁(如 http://www.cloudsamples.net/pictureservices)上找到了一個有趣的資源, 並且希望用電子郵件將其發送給某位朋友。當您的朋友收到該電子郵件時,您希 望他能夠單擊鏈接來並看到與您所見相同的頁面。如果 http://www.cloudsamples.net/pictureservices 上的資源突然變成了來自 MSNBC 的最新新聞報道,這當然會讓您感到驚訝。實際上,HTTP GET 中所使用 的 URI 代表的就是一個資源,通常您認為該資源不會改變。

雖然 HTTP GET 代表的內容已有明確定論,但對於其他 HTTP 動詞而言並非 如此。讓我們來考慮一下,將一個 HTTP DELETE 消息發送給某個接收應用程序 意味著什麼。接收應用程序是否需要更改其狀態或執行某個動作呢?通常,HTTP DELETE 是與刪減性的狀態變化或動作相關聯,但該狀態變化的具體信息則未定 義。HTTP PUT 同樣如此。通常,HTTP PUT 是與某些增加性狀態變化或動作相關 聯,但變化的具體情況則因應用程序而異。

表達其他信息

收到 HTTP GET 的應用程序會使用嵌入在 URI 中的信息來確定發送哪個資源作為回復 。為了對此進行闡明,讓我們來看看下面這組 URI:

contoso.com/artists/Flaming+Hammer/HitMe
contoso.com/artists/Northwind/Overdone

在這個例子中, Contoso Corporation 有一個應用程序,提供與音樂相關的資源。從這些例子中 您應該可以推斷出藝術家姓名以及唱片名稱是如何映射到 URI 的:

contoso.com/artists/[artist]/[album]

當應用 程序收到 http://contoso.com/artists/Northwind/Overdone 的 HTTP GET 消 息後,它會返回一個與 Northwind 的 Overdone 唱片相關的資源。這個 URI 顯 然有一定的模式。它由一些基本信息 (contoso.com/artists) 和一些 URI 段( 或“孔”)組成,它們將包含藝術家和唱片的值。

在查詢字符串參數中嵌入同類信息也很普遍。雖然格式與前面的例子不同, 但最終結果相同。下面是一組 URI 孔以及一個查詢字符串參數:

contoso.com/artists/Flaming+Hammer?album=HitMe
contoso.com/artists/Northwind?album=Overdone

在本例中, URI 和查詢字符串都使用如下的語法:

contoso.com/artists/ [artist]?album=[album]

HTTP 傳輸還會使用一組可擴展的標頭 ,以表達其他信息。這個信息可以與緩存、消息中數據的類型、發送應用程序的 名稱、內容的長度、主機操作系統以及其他很多信息相關。圖 1 顯示了一條 HTTP GET 消息(1-8 行)以及帶有若干常用標頭的回復消息(9-14 行)。

Figure 1 HTTP GET Request and Response

1  GET /PictureServices/Feed.svc/picture/Pictures;Bridge.jpg HTTP/1.1
2   Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,
    application/x-ms-application, application/vnd.ms- xpsdocument,
    application/xaml+xml, application/x-ms- xbap,
    application/vnd.ms-excel, application/vnd.ms- powerpoint,
    application/msword, application/x-shockwave- flash,
    application/x-silverlight, */*
3  Accept- Language: en-us
4  UA-CPU: x86
5  Accept-Encoding: gzip, deflate
6  User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1;
    .NET CLR 2.0.50727; InfoPath.2; .NET CLR 1.1.4322;
    .NET CLR 3.5.20706; .NET CLR 3.0.590; MS-RTC LM 8)
7  Host: www.cloudsamples.net
8  Proxy-Connection: Keep-Alive

9  HTTP/1.1 200 OK
10  Content-Type: image/jpeg
11  Server: Microsoft-IIS/7.0
12  X-Powered-By: ASP.NET
13  Date: Sat, 15 Sep 2007 18:57:11 GMT
14  Content-Length: 106333

HTTP GET 請求中的 “Accept”標頭指出了客戶端要接收的數據格式。正如您從那一長串 值中所見,客戶端可以接收多種類型的數據(圖像、Office 文檔、Silverlight 應用程序等)。HTTP GET 響應所含數據的格式用 Content-Type 標頭的值(如 第 10 行的 image/jpeg 所示)來描述。這種簡單的機制可以讓發送和接收應用 程序協調數據格式。用標頭來協調數據格式在表達能力上不及 SOAP Web 服務的 Web 服務描述語言 (WSDL) 和 XML 架構定義 (XSD) 語法,但對於 Web 來說已 經足夠了。

REST 和 Web

通過查看 HTTP 傳輸的一些關鍵部分, 您也已經看到了將 Web 松散地聯結在一起的一些重要原則。2000 年,一位名叫 Roy Fielding 的博士生完成了一篇論文,其中一項工作就是將這些原則匯編形成了一種體系結構風格,也就是所謂的具像狀態傳輸 (Representational State Transfer, REST)。(您可以在 ics.uci.edu/~fielding/pubs/dissertation/top.htm 找到 Roy 的論文。)

各種書籍、軟件會議以及看起來無數的博客已經對 REST 體系結構風格 進行了詳細的討論。此處不可能對它面面俱到,但我認為應該可以把它濃縮為三 個要點:

利用 URI

HTTP GET 具有特殊性

Content-Type 是數據模型

為了撰寫本文的目的,我們假設這些要點就是 Web 的原則。 通過將這些原則結合到應用程序中,即可大大增強互操作性以及應用程序功能的 作用范圍。互操作性和作用范圍是大多數 Web 服務舉措背後的關鍵驅動因素。 畢竟,Web 服務實質上就是一個通過結構化消息傳遞架構來提供某種功能的方法 。Web(HTTP 請求/響應)的原則實際描述了可能的消息傳遞架構的子集。事實 上,所有平台、應用程序、操作系統和用戶都了解 Web 原則,因此將其結合在 您的 Web 服務應用程序中即可提高它的作用范圍和互操作性。

需要注意 的是,由於 REST 和 WS-* 之間的選擇並不相互排斥,因此 Web 原則對 WS-* 沒有影響。它們中任何一個都不能解決所有類型的通信要求,因此建議您不要在 自己構建的所有服務上一股腦地應用其中一個。例如,REST 不擅長於向中介發 送消息,而 WS-* 卻擅長於此。另一方面,WS-* 應用程序不太擅長與諸如浏覽 器等簡單的客戶端交互,但 REST 在這方面卻十分出色。

使用 WCF 進行 HTTP 編程

基於這些 Web 基礎知識,我們再看看在 .NET Framework 3.5 中使用 WCF 來構建符合 Web 原則的應用程序。首先,我將介紹 HTTP 編程模型 中一些新的構建塊,然後向上介紹整個系統。

如果要“利用 URI”,您可能需要習慣構建和分析 URI。手動執行這項任務往往容易出錯 且十分枯燥。然而,新的 System.UriTemplate 和 System.UriTemplateMatch 類型挑起了構建和分析 URI 這個重擔,而它們也是 WCF 新的 HTTP 功能中的基 礎構建塊。

UriTemplate 類型是定義上文中所述 URI 孔的基礎構建塊。 UriTemplate 類型的構造函數可以接受代表 URI 中孔的 String。在實例化時, UriTemplate 對象會提供兩個實例方法,將文本值與在實例化中定義的孔綁定。 這些方法會返回一個 URI,它的孔已填充了值。

UriTemplate 對象同樣 也會提供一個名為 Match 的實例方法,用於從 System.Uri 對象的孔提取值。 Match 實例方法可以接受兩個 System.Uri 對象。第一個 Uri 是基本地址,第 二個 Uri 是用於匹配的候選項目。System.UriTemplateMatch 對象是 Match 方 法返回的值。UriTemplateMatch 對象包含一組值,用於 UriTemplate 實例化時 定義的孔。

圖 2 中的代碼闡明了如何使用 UriTemplate 和 UriTemplateMatch 類型來回處理了一次 Uri。此代碼的結果輸出如下所示:

Figure 2 Creating a Template-Based URI

// create a URI bound to the template
Uri baseAddress = new Uri (@"http://localhost:2000");
UriTemplate template = new UriTemplate("{artist}?album={album} ");
Uri boundUri = template.BindByPosition(baseAddress, "Northwind",
  "Overdone");
Console.WriteLine(boundUri.ToString());

// retrieve the value of the artist segment
UriTemplateMatch match = template.Match(baseAddress, boundUri);
String bandName = match.BoundVariables["artist"];
Console.WriteLine ("the name of the artist is {0}", bandName);

http://localhost:2000/Northwind?album=Overdone
the name of the artist is Northwind

System.UriTemplate 和 System.UriTemplateMatch 類型在命名空間中忽略了常見的 WCF System.ServiceModel 標記。這是因為它們的功能使您無需在 WCF 應用程序內 部使用這兩種類型。任何時候您需要創建或分析 URI,它們使用起來都非常方便 。

雖然 UriTemplate 和 UriTemplateMatch 類型使用起來已經非常容易 了,但 WCF 小組還想進一步簡化這兩種類型在 WCF 服務中的使用。目標是提供 一種簡單而直觀的方法,將 URI 段和查詢字符串參數映射到應用程序功能中。 我想下面代碼中所展示的模型就符合這個目標:

[ServiceContract]
public interface IPictureService
{
  [OperationContract]
 [WebGet(UriTemplate = "picture/ {pictureId}")]
 Stream GetPicture(String pictureId);

 [OperationContract]
 [WebGet(UriTemplate = "picture/t/{pictureId}")]
 Stream GetPictureThumbnail (String pictureId);
}

UriTemplate 表面上看起來是 WebGetAttribute 上的一個實例屬性,而 WebGetAttribute 又隨之應用到某個 服務約定。請注意,大括號間的標記映射到方法參數的名稱。雖然這個示例只顯 示了一個參數,但您可以添加多個參數,以任何順序排列,將其作為查詢字符串 參數,甚至可以使用通配符。

運行時,UriTemplate 屬性的值會被傳遞 到 UriTemplate 構造函數。無論是 Client 運行時,還是 Dispatcher,都以這 種方式使用 UriTemplate 屬性值。Dispatcher 用它將傳入消息與某個操作匹配 ,而 Client 則用它確保代理應用程序上的方法被發送到正確的 URI。這種方法 不僅簡單易用,而且可以有效地在您的服務中“利用 URI”。

WCF 約定中的 HTTP 動詞

在 .NET Framework 3.5 中使用 WCF 進行 HTTP 編程可以輕而易舉地將服務約定中的操作映射到 HTTP 動詞。顧名思 義,將 WebGetAttribute 應用到某個操作可以使該操作能夠通過 HTTP GET 使 用。正如您在前面的代碼片段中所見,WebGetAttribute 定義了一個名為 UriTemplate 的實例屬性。

WebGetAttribute 類型還有一些其他實例屬 性。最引人注目的是 RequestFormat 和 ResponseFormat。如其名稱所指,這些 屬性的值指明了操作的消息格式。RequestFormat 和 ResponseFormat 屬性都屬 於 WebMessageFormat 類型,即一種具有兩個值的枚舉類型:Xml 和 Json。WCF 基礎結構會使用這些屬性的值,借用合適的消息編碼器來設置通道堆棧。 WebMessageFormat.Xml 的屬性值將產生使用 XML 編碼器的通道堆棧。將值設置 為 WebMessageFormat.Json 將產生使用 .NET Framework 3.5 中的 JSON 編碼 器的通道堆棧。由於 HTTP 消息交換的雙方都有各自的屬性,因此一個應用程序 可以實現接收 XML 消息並返回 JSON 消息(反之亦然)。

另一個與 HTTP 動詞相關的屬性是 WebInvokeAttribute。將此屬性應用到操作會使該操作 可以被除 HTTP GET 以外的其他任何 HTTP 動詞所使用。對象模型中 HTTP GET 和所有其他動詞之間的這種區別反映了 HTTP GET 相對於其他 HTTP 動詞的使用 頻率。WebInvokeAttribute 對象模型與 WebGetAttribute 類似,但它包含一個 名為 Method 的實例屬性。此屬性的值可以將某個特殊 HTTP 動詞與操作相關聯 。Method 屬性具有 String 類型,因此您可以將值設置為任何標准的 HTTP 動 詞,甚至是非標准的 HTTP 動詞。圖 3 闡明了如何在服務約定中使用 WebInvokeAttribute。

Figure 3 Using WebInvokeAttribute

[ServiceContract]
public interface IPictureService
{
 [OperationContract]
 [WebGet (UriTemplate = "picture/{pictureId}")]
 Stream GetPicture(String pictureId);

 [OperationContract]
  [WebGet(UriTemplate = "picture/t/{pictureId}")]
  Stream GetPictureThumbnail(String pictureId);

  [OperationContract]
 [WebInvoke(UriTemplate="update", Method="POST")]
 void UpdatePictureInfo(PictureInfo info);
}

UpdatePictureInfo 方法擁有一個 PictureInfo 類型的參數。在運行時,PictureInfo 對象的序列化版本是 HTTP POST 消息的 負載。通過這種方式傳遞數據,可以讓應用程序傳輸 URI 中無法表達的復雜數 據類型。

.NET Framework 3.5 中的 WCF 還可以使與 HTTP 標頭交互變 得很簡便。請求和響應 HTTP 標頭是通過 System.ServiceModel.Web.WebOperationContext 類型提供的。 WebOperationContext 類型是對 System.ServiceModel.OperationContext 類型 (在 .NET Framework 3.0 的 WCF 中引入)的擴展,並且它的使用模式相似。 兩者都適用於服務對象實現的內部。WebOperationContext 類型提供了一些成員 ,它們簡化了讀取或設置 HTTP 標頭值,並且簡化了檢索與訪問服務對象所用的 URI 相關的信息。HTTP 標頭以集合的形式存儲,最常用的標頭則作為單獨的屬 性提供。下例表明如何通過為 HTTP 響應設置 Content-Type 標頭,使用 WebOperationContext 類型沿用 Web 的數據模型:

public Stream GetPicture(string pictureId)
{
 // retrieve the Stream (omitted)
 Stream stream;

 // set the Content-Type to image/jpeg
  WebOperationContext.Current.OutgoingResponse.ContentType =
   "image/jpeg";

 return stream;
}

綁定和承載

至此,您已了解如何將 URI 段映射到應用程 序功能、如何將操作映射到 HTTP 動詞,以及如何與 HTTP 標頭交互。現在,讓 我們來看看如何將這些功能整合到一個運行的服務中去。為此,您需要先了解 WCF 中更多的新類型。

.NET Framework 3.0 中的 WCF 引入了綁定這個 概念,即對傳輸和終結點協議的一種抽象。.NET Framework 3.0 附帶了多種綁 定,支持各種傳輸和協議選擇。

.NET Framework 3.5 中的 WCF 包含一 種新的綁定,名為 System.ServiceModel.WebHttpBinding。這種綁定是對 Web 原則的抽象,它所遵循的使用模型與 .NET Framework 3.0 中的綁定類型相同, 因此可以像其他綁定一樣將其添加到終結點。

.NET Framework 3.0 中的 WCF 還引入了終結點行為這個概念。行為是一種擴展消息傳遞基礎結構執行路徑 的方式。.NET Framework 附帶了多種行為,要自己創建行為也十分容易。

.NET Framework 3.5 中的 WCF 包含了一種新的終結點行為,名為 System.ServiceModel.Description.WebHttpBehavior。此行為可以執行多種任 務。對於接收應用程序而言,它的任務之一是設置篩選基礎結構,以確保將收到 的消息分派到服務對象上相應的方法。在 .NET Framework 3.0 中,WCF 使用 SOAP Action 和目標地址的組合作為調度鍵。WebHttpBehavior 設置的篩選機制 是對現有篩選機制的一種擴展,目的是使用 UriTemplate 匹配和 HTTP 動詞。

圖 4 顯示了如何使用 WebHttpBinding 和 WebHttpBehavior 來構建利 用 Web 原則的接收應用程序。這種方法的優點是,您可以將這些終結點之一添 加到現有的 ServiceHost 中,這樣您最終將得到一個 ServiceHost,它不僅有 SOAP/WS-* 終結點,同時也有 REST 終結點。

Figure 4 Using WebHttpBinding and WebHttpBehavior

ServiceHost host = new ServiceHost(typeof(IPictureContract),
  new Uri ("http://localhost:5000"));
// instantiate a WebHttpBinding
WebHttpBinding binding = new WebHttpBinding();

// add an endpoint, using the WebHttpBinding
ServiceEndpoint ep = host.AddServiceEndpoint(
  typeof(IPictureContract), binding, String.Empty);

// add the WebHttpBehavior to the endpoint
ep.Behaviors.Add(new WebHttpBehavior());

// open the ServiceHost to start listening
host.Open();

發送應用程序遵循相同的使用模 型,但應將 WebHttpBehavior 添加到 ChannelFactory<T> 對象上的終結 點行為集合中。根據典型的 WCF 慣例,也可以在配置文件中使用這些選項。

.NET Framework 3.5 中的 WCF 使得這個模型更加容易使用,在某些情 況下,您無需添加 WebHttpBinding 或 WebHttpBehavior。新的 API 包含了兩 種類型以實現此目的:System.ServiceModel.Web.WebServiceHost 和 System.ServiceModel.Web.WebServiceHostFactory。WebServiceHost 類型可以 自動將 WebHttpBehavior 添加到所有終結點,並在運行時執行一些額外的驗證 ,以確保所有的終結點都與該行為兼容。這就省去了將 WebHttpBehavior 添加 到終結點這個步驟。

WebServiceHostFactory 類型適用於 IIS 承載的情 形,這樣就不需要命令性或配置文件承載信息。.NET Framework 3.0 中的 WCF 引入了 .svc 文件,作為在 IIS 中承載 WCF 服務的激活目標。這些文件包含了 一些指令,類似於 ASP.NET 中的頁面指令。將 WebServiceHostFactory 添加到 .svc 文件指令的 Factory 屬性會創建一個 ServiceHost、添加一個終結點(與 WebHttpBinding 使用適當的約定)、將 WebHttpBehavior 添加到該終結點,然 後打開 ServiceHost:

<%@ ServiceHost
  Language="C#"
 Service="PictureService"
 Factory="System.ServiceModel.Web.WebServiceHostFactory" %>

服務的 web.config 文件不包含任何與 WCF 相關的條目。

新的整合 API

請想象一個 RSS 源。如果您和我一樣,就會立即 想到新聞源或博客。整合(RSS 和 ATOM 是整合格式)能夠表達的不止是這些。 簡單地說,整合的內容就是表達一組數據的方式。這組數據實際上可以是任何內 容:悉尼方圓 50 英裡范圍內居住的袋熊的數量、最近 10 張超過 100 美元的 采購單,或是 Contoso 上個月生產的回飛棒的數量。

.NET Framework 3.5 充分支持整合內容的創建和使用。它支持 RSS 2.0 和 ATOM 1.0 格式的創 建及使用、支持添加整合擴展的各種方式,甚至還支持實現其他格式的功能。編 程模型避免了開發人員直接處理整合格式細節,從而使其易於使用。

在 3.5 版之前,.NET Framework 一直沒有一種標准的方式來創建或使用整合的內 容。雖然新的整合功能由 WCF 小組編寫,但它並不依賴於 WCF。事實上,所有 與整合相關的類型都是 System.Syndication 命名空間的一部分,雖然它們位於 System.ServiceModel.Web.dll 程序集中。您可以從任何承載了 AppDomain (ASP.NET、WPF 應用程序、NT 服務等)的進程使用 .NET Framework 3.5 的整 合功能。這個功能意味著您可以通過任何傳輸(而不僅僅是 HTTP)提供或使用 整合的內容。然而,當與 WCF 中的 HTTP 編程模型結合後,也可以將整合添加 到現有的 SOAP/WS-* 服務中。

新的整合 API 包含了一些類型,它們可 以抽象單獨的整合源及其中的項目,還有一些類型可以將該源轉換為特定的格式 。System.Syndication.SyndicationFeed 類型是整合源的一種中立格式的表現 形式。SyndicationFeed 包含一系列 SyndicationItem 對象。不含一組 SyndicationItem 對象的 SyndicationFeed 就像是一個沒有豌豆的豆莢,因為 SyndicationItem 對象就是源中項目的表現形式。

用一組 SyndicationItem 對象填充 SyndicationFeed 後, SyndicationFeedFormatter<T> 可以將該源轉換成特定的格式。 SyndicationFeedFormatter<T> 可派生出兩種類型:Rss20FeedFormatter 和 Atom10FeedFormatter。顧名思義,這些類型可以將 SyndicationFeed 的實 例分別轉換為 RSS 2.0 和 ATOM 1.0 格式。

創建 SyndicationFeed

創建 SyndicationFeed 對象的方法有兩種。您可以實 例化對象並手動填充其成員,或者也可以從現有的源來填充整個 SyndicationFeed。這兩種方法都非常簡單,同時還可以避免開發人員直接處理 特定傳輸格式的瑣碎細節。下面的代碼演示了如何手動構建 SyndicationFeed 對象。

復制代碼

SyndicationFeed feed = new SyndicationFeed();

feed.Title.Text = "The Cybertopian Chronicle";

Title 僅僅是眾多可以設置的屬性之一,因此請查看 文檔以便了解其他可以設置的屬性。

很多情況下,您想要讀取一個現有 的源,並根據該源的內容做一些事情。在新的整合 API 中,您可以實例化一個 SyndicationFeed,並自動從現有的源對其狀態進行填充。這時,您只需要一個 現有源的 URI,或是一個准備好讀取源的 XmlReader。下面的代碼顯示了如何連 接到 Web 上的一個現有源,並從中提取信息:

Uri feedUri = new Uri("http://blogs.msdn.com/justinjsmith/atom.xml");
SyndicationFeed feed = SyndicationFeed.Load(feedUri);
Console.WriteLine(feed.Title.Text);

// outputs "The Cybertopian Chronicle"

SyndicationItem 類型包含了超 過 35 個成員。許多這些成員都是與設置或檢索字段(如項目標識符、最後更新 時間、發表日期、標題或實際內容)相關的屬性。還有許多成員則是為了方便擴 展 SyndicationItem 中存儲的內容。對 RSS 和 ATOM 的擴展(Microsoft 簡單 列表擴展、Yahoo Media RSS、GeoRSS 等)有很多,SyndicationFeed 和 SyndicationItem 均可擴展為包含任何現有的 RSS 或 ATOM 擴展。

源可 以有許多項目,對於大型源來說,不能一次加載所有項目。SyndicationFeed 解 決了這個情況,它將其 SyndicationItem 對象集公開為一個 IEnumerable<SyndicationItem>。這種實現使處理大量 SyndicationItem 對象更為方便,因為它充分利用了 .NET Framework 2.0 的迭代器功能。用 LINQ 也可以遍歷一組 SyndicationItem 對象。這就大大減少了從源提取信息所 需的代碼量。

整合 API 定義了多個類型,它們可以將 SyndicationFeed 轉換為 RSS 2.0 和 ATOM 1.0 格式。事實上,您可以構建 SyndicationFeed, 用 SyndicationItem 對象填充它,然後將該源公開為 RSS 和 ATOM。圖 5 演示 了如何檢索一個 ATOM 1.0 源、將其轉換為 RSS 2.0,然後將新的 RSS 表示輸 出到控制台。

Figure 5 Transforming a Feed

// read an ATOM feed
Uri feedUri = new Uri ("http://blogs.msdn.com/justinjsmith/atom.xml");
SyndicationFeed feed = SyndicationFeed.Load(feedUri);

// transform it to RSS
Rss20FeedFormatter formatter = new Rss20FeedFormatter(feed);
XmlWriter writer = XmlWriter.Create (Console.Out, null);

// write it to the Console
formatter.WriteTo(writer);
writer.Flush();

在 WCF 中將整合 API 與 HTTP 編程模型配合使用時,就可以公開來自自定義 URI 的源 ,並根據 URI 的構成返回 RSS 或者 ATOM。圖 6 顯示了如何在服務約定中定義 一個操作,該操作將使用已收到的 HTTP GET 中的一個查詢字符串參數來返回 RSS 或 ATOM 源。請注意操作約定中 SyndicationFeedFormatter<SyndicationFeed> 的使用。 Rss20FeedFormatter 和 Atom10FeedFormatter 都派生於 SyndicationFeedFormatter<TSyndicationFeed>。

Figure6Exposing a Feed from a Customized URI

[ServiceKnownType(typeof(Atom10FeedFormatter))]
[ServiceKnownType(typeof(Rss20FeedFormatter))]
[ServiceContract]
interface IPictureService {
 [OperationContract]
  [WebGet(UriTemplate="Pictures?format={format}")]
  SyndicationFeedFormatter<SyndicationFeed> Feed(String format);
}
class PictureService : IPictureService {
  public SyndicationFeedFormatter<SyndicationFeed> Feed(String format){
  // create the syndication feed
   SyndicationFeed feed = new SyndicationFeed();
  // add the items to the feed (omitted)
  // check the argument & return the right format
  if(format.ToLower() == "rss"){
   return new Rss20FeedFormatter(feed);
  }
  return new Atom10FeedFormatter(feed);
 }
}

總結

總的來說,您已了解了 HTTP 傳輸的一些基礎知 識、它如何與 Web 原則相關聯、如何使用 WCF 將這些原則結合到您的應用程序 中,以及如何使用新的整合 API 來提供和使用 RSS 以及 ATOM 源。為了進一步 演示這些新功能,您可以在一個名為 PictureServices 的示例應用程序(網址 為 www.cloudsamples.net/pictureservices)中看到所有功能一起運行。您可 以在線運行這個示例、浏覽其源代碼並下載整個示例。圖 7 顯示了運行中的 PictureServices。

Figure 7The PictureServices Feed

簡言之, PictureServices 可以從本地計算機或 Flickr 源檢索圖片。該應用程序使用一 個簡單的提供程序模型,目前有三個提供程序:Windows 桌面搜索、文件系統上 的文件夾,以及 Flickr。一旦 PictureServices 從某個提供程序檢索到文件, 它便會整合這些圖片,並且在本地提供它們。您可以在浏覽器中單擊一個源,然 後檢索各個圖片。示例中還有許多內容,請盡情探索吧。有關本文所述技術的詳 細信息鏈接,請參閱“其他資源”側欄。

Justin Smith 是 Microsoft 一名專門從事 Web 服務的技術專家。他致力於研究 WCF 和 BizTalk 服務。Justin 也是“Inside Windows Communication Foundation” (Windows Communication Foundation 內幕)(Microsoft Press, 2007) 一書 的作者,並經常在軟件開發會議上發表演講。您可以在 blogs.msdn.com/justinjsmith 閱讀他的博客。

原文地址:http://msdn.microsoft.com/zh-cn/magazine/cc135976.aspx

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved