Microsoft .NET 框架和 Visual Studio.NET 中的 SOAP
2024-07-10 12:59:41
供稿:網友
 
摘要:關于 .net remoting、asp.net web services 和 atl web services 中 soap 功能的討論。
目錄
簡介
將 soap 用作 web 開發工具
將 soap 用作組件開發工具
將 soap 用作 atl 開發工具
總結
簡介
microsoft® .net 框架和 microsoft® visual studio.net 利用 xml 和 soap 技術,使開發人員能夠創建廣泛的解決方案。soap 是一個簡單、輕便、并在業界獲得廣泛支持的協議,適用于各種各樣的應用,它與 .net 框架的結合簡單而合乎自然。
從底層開始,soap 的設計目標就是使之成為一種非常簡單的協議,能夠以各種不同的方式滿足各種不同的需求。除了 microsoft,已有許多公司實際應用 soap,例如 ibm、develop mentor 和 userland。
在使用 soap 的體系中,有若干種關鍵技術。在創建基于 soap 的解決方案時,每種技術都會解決開發人員的一些共同問題。這些技術分別屬于 .net remoting、asp.net web services 和 atl web services,它們具有許多共同的技術特點: 
用于消息生成和使用的 xml。
符合 soap 1.1 規范,包括第 5 節 soap 編碼,這使 soap 應用之間具有很好的互操作性。
xml 保真性(非第 5 節 soap 編碼),用于完全斷開的模型。
wsdl(xml 方案的一種形式),用于提供說明。
可用無狀態編程模型擴展系統。
使用 visual studio.net 的良好開發環境。 
asp.net web services 和 .net remoting 還共享下列技術: 
xcopy 系統部署。
system.net,進行網絡通訊時,無論在服務器還是客戶端它都運行良好。
公共語言運行時可在受控代碼和線程緩沖池中重用。
提供強大的 soap 支持,例如 soap 頭和單向消息等特性。
能夠與 c#、visual basic.net 或任何符合 cls 規范的語言(如 cobol、python、 componentpascal 等等)配合使用來編寫應用程序。 
除了以上列出的共同特點和技術以外,asp.net web services、.net remoting 和 atl web services 還分別為開發人員提供了許多特有的功能,下面這些內容有助于開發人員在生成應用程序時把握正確的方向。
如果您要生成 .asp 應用程序,asp.net web services:
允許與 asp.net http 運行時緊密集成。
鼓勵開發人員著重于運用 xsd 數據類型來提供應用程序。
在 visual studio.net 中提供強大的設計支持。 
如果您要生成 mts/com+ 應用程序,.net remoting:
提供全面的受控代碼類型系統的網絡保真性。
提供在網絡上通過引用來傳遞對象的功能,并且可返回到特定進程中的特定對象。
提供二進制通訊能力。 
如果您要生成 atl/c++ 應用程序,atl server:
提供靈活并且可控的本機 (c++) 解決方案。
建立于 atl server isapi web 應用體系機構之上(利用線程緩沖池、緩存,等等)。 
將 soap 用作 web 開發工具
asp.net web services 提供了 rad 方式,以供快速創建和使用 web 服務。這些服務寬松地組合在一起,并可與 asp.net 高度集成。asp.net web services 是 web 開發人員在 internet 上提供 web 服務的首選方法,它的目標是提供快速、簡便、性能優越的 soap 服務。
asp.net web services 可以和 asp.net http 引擎深入集成,這使得熟悉 microsoft web 開發技術的開發人員能夠方便地生成和使用基于 soap 的 web 服務。
asp.net 以 .asmx 文件提供對 web services 的支持。.asmx 文件是與 .aspx 文件相似的文本文件。這些文件可以是包含 .aspx 文件的 asp.net 應用程序的一部分。它們可以使用 uri 尋址方式,這和 .aspx 文件相同。
以下是一個非常簡單的 .asmx 文件示例:
<%@ webservice language="c#" class="helloworld" %>
using system;
using system.web.services;
public class helloworld : webservice {
 [webmethod] public string sayhelloworld() {
 return "hello world";
 }
}
這個文件以 asp.net 指示的 web service 開始,并將語言設置為 c#(也可以將語言設置為 microsoft visual basic®、c 或大約 30 種第三方語言中的任何一種)。然后,它將導入名稱空間 system.web.services。這個名稱空間是必要的,您必須在文件中包括它。下一步,聲明 helloworld 類。這個類從基類 webservice 導出。最后,任何要作為服務的一部分來訪問的方法在它們的簽名之前將具有自定義屬性 [webmethod],在 visual basic 中則為“<webmethod()>”。
要使這個服務生效,可以將文件命名為 helloworld.asmx,然后將它放在虛擬目錄 bar 中的服務器 foo 上。使用幾乎任何兼容 html 3.2 或更高版本的瀏覽器,都可以輸入 url http://foo/bar/helloworld.asmx 來顯示這個 web service 的公用方法(標有 webmethod 屬性),以及那些可用來調用這些方法的協議,例如 soap 或 http get。如果在 internet explorer 地址欄中輸入 http://foo/bar/helloworld.asmx?sdl,基于服務說明語言 (wsdl) 語法,將產生與 xml 文件相同的信息。這個 wsdl 文件由訪問服務的客戶使用,并且非常重要。
訪問 web serivces
除了使開發人員能夠創建 web services 的技術之外,microsoft .net 框架還提供了一套用來“使用”(即以客戶端身份訪問)web services 的成熟工具與代碼。因為 web services 基于簡單對象訪問協議 (soap) 和 http 等開放協議,所以這種客戶端技術也可以用于使用非 asp.net web services。
sdk 中有一種稱為 webserviceutil.exe 的工具(在 vs ide 中使用“add web reference...”選項時自動生效)。這個程序可用于下載 web service 的 wsdl 說明,然后創建表示這個服務的地址的代理類。例如,您可以輸入:
webserviceutil /c:proxy /pa:http://somedomain.com/somefolder/helloworld.asmx?sdl
然后,系統將創建稱為 helloworld.cs 的代理類。
這個類與前面創建的類看起來非常相似。它包括稱為 sayhelloworld 的方法,該方法返回字符串。將這個代理類編譯到應用程序中,然后調用其方法,結果是代理類在 http 上打包 soap 請求,并接收 soap 編碼的回應,然后封送為一個字符串。
從客戶端來看,代碼非常簡單:
dim myhelloworld as new helloworld()
dim sreturn as string = myhelloworld.sayhelloworld()
返回值將是“hello world”。
將 soap 用作組件開發工具
創建分布式應用程序時,如果需要高度控制性并要求能夠選擇系統耦合程度,那么可以使用 microsoft .net remoting。
microsoft .net remoting 還提供了與公共語言運行時的深入集成,并且為開發人員提供了全面的跨連接類型系統保真性。這包括構造函數、委托、重載方法、通過值和引用傳遞對象、類的層次結構、接口、方法、屬性、字段,以及通過可插入通道、分布式標識、激活、租用生存期和 callcontext(獨立于參數的 soap 頭中的流對象)在連接上的應用程序 (web services) 之間進行 marshal by value(制作副本)以及 marshal by ref(傳遞 objref)。
使用 .net remoting,開發人員可以從任何進程提供 remoting 終結點,包括控制臺應用、gui 應用、nt service 和 iis。在任何使用有效加載編碼(在產品中提供了可插入序列化格式化程序以及 soap 和二進制格式化程序)通過可插入通道進行的任何傳輸過程中都會出現這種情況。soap=http+xml,同時完全支持 http 和 smtp 上的 soap 1.1,這十分令人滿意。
我們可以獲得 wsdl 支持來說明 web service 并保證運行時類型系統的完全保真性。.net remoting 提供了 .net sdk 的 soapsuds 工具,可以從元數據生成受控類和 com 對象的服務說明。soapsuds 工具也使用服務說明并生成元數據和代理。開發人員可以使用密集偵聽模型,將自己的操作作為應用程序入站和出站消息流插入。想更為深入的開發人員則可以采用使用套接字的二進制編碼 tcp 通道。
.net remoting 使受控組件、本機 com/com+ 組件以及接受服務的組件(使用 com+ 服務的受控組件)遠程化。soap、二進制以及任何一種可插入通道和格式上都可能出現這些情況。
樣例:soap 受控代碼事件 
下列代碼演示如何在兩個應用程序之間引發受控代碼事件。客戶端有一個本地對象,注冊為接收遠程對象的事件通知。客戶端呼叫服務器對象時,就引發事件,產生對客戶端本地對象的回叫。
服務器端
zap.cs
using system;
namespace zap
{
 // 定義事件參數
 public class greetingeventargs : eventargs
 {
 public greetingeventargs(string greeting)
 {
 this.greeting = greeting;
 }
 public string greeting;
 }
 // 定義事件
 public delegate void greetingevent(object sender, 
greetingeventargs e);
 // 定義服務
 public class waz : marshalbyrefobject
 {
 // 客戶端將預定和取消預定此事件
 public event greetingevent greeting;
 // 由客戶端遠程調用的方法
 public void hellomethod(string greeting)
  {
 console.writeline("received string {0}", greeting);
 // 將字符串打包到 greetingeventargs 中
 greetingeventargs e = new greetingeventargs(greeting);
 // 引發事件
 if (greeting != null)
 {
 greeting(this, e);
 }
 }
 }
}
host.cs
using system;
using system.io;
using system.runtime.remoting;
using system.runtime.remoting.channels.http;
public class host
{
 public static void main(string[] args)
 {
 // 手動加載 http 通道。
 // 這也可以在 remoting 配置文件中完成。
 channelservices.registerchannel(new httpchannel(999));
 // 注冊服務器類型。
 // 這也可以在 remoting 配置文件中完成。
 remotingservices.registerwellknowntype(
 "zap", // 程序集
 "zap.waz", // 完整的類名
 "host/waz.soap", // uri
 wellknownobjectmode.singleton); // 對象模式
 // 完成操作,等候用戶退出
 console.writeline("主機已經準備好處理遠程消息。");
 console.writeline("請按 enter 鍵退出");
 string keystate = console.readline();
 }
}
客戶端
client.cs
using system;
using system.runtime.remoting;
using system.runtime.remoting.channels.http;
using zap;
// 將對象按引用本地封送到要引發的事件
public class baz : marshalbyrefobject
{
 public void greetinghandler(object sender, greetingeventargs e)
 {
 console.writeline("greetinghandler 回叫: 問候: {0}/n", 
 e.greeting);
 }
}
public class client
{
 public static void main(string[] args)
 {
 baz baz = new baz();
 // 這也可以在 remoting 配置文件中完成。
 // 注冊 http 通道
 channelservices.registerchannel(new httpchannel(0));
 // 獲取 soap url 代理
 waz waz = (waz)activator.getobject(
 typeof(waz),
 "http://localhost:999/host/waz.soap"
 );
 // 預定事件: 通過 soap 進行
 waz.greeting += new greetingevent(baz.greetinghandler);
 for (int i = 0; i < 5; i++)
 {
 // 通過 soap 向 waz 發送
 waz.hellomethod("bill" + " " + i);
 }
 // 取消預定事件: 通過 soap 進行
 waz.greeting -= new greetingevent(baz.greetinghandler);
 }
}
makefile
makefile
all: host.exe zap.dll client.exe
host.exe: host.cs
 csc /r:system.runtime.remoting.dll host.cs
zap.dll: zap.cs
 csc /t:library -out:zap.dll zap.cs
 
client.exe: zap.dll client.cs
 csc /r:system.runtime.remoting.dll /r:zap.dll client.cs
在一個窗口中啟動 host.exe 文件,然后在另一個窗口中啟動 client.exe 文件。您將會看到事件被引發回到客戶端。
這是諸多 .net remoting 應用程序中的一個小例子。.net remoting 提供了網絡上的完全 clr 受控代碼類型系統,它還是優秀的 soap 服務器和客戶端,因為它完全符合 soap 1.1 規范。
將 soap 用作 atl 開發工具
atl server web services 為 c++ 開發人員提供了在本機代碼中創建和使用 web services 的簡便方式。atl server 是 c++ 開發人員在 internet 上提供和使用 web services 的首選方法,其設計目的是為包含 soap 的 web 應用提供快速、輕便和高度靈活的程序庫。
atl server 之所以稱為 atl,是因為它體現了同時追求高性能和靈活性的 atl 目標。例如,您可以很容易地拋開 atl server http 模型,編寫您自己的調度程序,同時仍然獲得 atl server 封送/協議代碼的好處。
atl server web services 使用與 com 相似的語法說明接口,便于目前的 atl 開發人員學習。這種與 com 相似的語法允許開發人員輕而易舉地將對象同時以 com 對象和 web service 方式提供。
屬性的引入大大簡化了代碼,使它對于非 atl 開發人員也很容易。atl server 具有和其他所有 .net web services 進行互操作的能力,這對那些在一個應用程序中使用多種技術的開發人員來說十分方便。
接口:新的 __interface 關鍵字使開發人員很容易創建 com 對象或 web services 接口。
[
 uuid("d7dae6fd-aebb-4579-bd8d-866f74139501"), 
 object
]
__interface iweb_service_exampleservice
{
 [id(1)] hresult helloworld([in] bstr bstrinput, [out, retval] bstr *bstroutput);
};
這是一個運用 atl server 定義 web service 接口的例子。通過 c++ 屬性的運用,嵌入式 idl 屬性和新的 __interface 關鍵字、atl server web service 接口看起來和新的屬性化的 com 接口非常相似。這里的 web service 接口樣例 iweb_service_exampleservice 僅實現一個方法 helloworld。helloworld 用 bstr 作為輸入并返回 bstr 作為輸出。
請求處理程序:請求處理程序是一個 c++ 類,該類通過處理程序映射來提供,并且具有通過替代方法映射來提供的方法。處理程序映射只是文字標簽與類名稱的映射,而方法映射是類中文字標簽與方法的映射。
 [
 request_handler(name="default",sdl="genweb_service_exampleservicesdl"),
 soap_handler(
 name="web_service_exampleservice", 
 namespace="urn:web_service_exampleservice",
 protocol="soap"
 )
]
class cweb_service_exampleservice:
 public iweb_service_exampleservice
{
public:
 
 [ soap_method ]
 hresult helloworld(bstr bstrinput, bstr *bstroutput)
 {
 ccombstr bstrout(l"hello ");
 bstrout += bstrinput;
 bstrout += l"!";
 *bstroutput = bstrout.detach();
 
 return s_ok;
 }
}; 
atl server 請求處理程序模型與 web 應用和 web services 非常相似。圖 1 顯示了處理請求的模型:
圖 1. atl server 請求處理模型
http request 進入 iis,將請求(基于 url 及其擴展)映射到適當的 isapi dll。然后,isapi dll 把在請求中指定的處理程序(即在標簽或查詢參數中指定的處理程序)映射到適當的 application dll。application dll 再將這個處理程序映射到 c++ 對象。在這個模型(atl server 模型)中,web 應用程序和 web service 的唯一差別在于最后一步。使用 web services,c++ 對象能夠解碼/編碼 soap(當編譯器解析 soap_handler 屬性時,它會插入執行此操作的代碼)。
您可以理解,這個類是從我們的接口繼承過來的,并且我們使用 [soap_method] 屬性指示將由 helloworld 方法來處理 soap 請求。實現這種方法和實現任何其他 c++ 方法是一樣的。
這個 soap_handler 屬性還確保自動生成有效說明服務的 wsdl。web service 的用戶使用這個對服務的說明(格式為 xml/wsdl),確保他們能夠以正確的格式發送/接收正確的數據。
通過 atl server 使用 web services
通過 atl server 使用 web services 相對來說是個比較簡單的操作。開發人員只需使用 “add web reference” 對話框,將它指向 .disco 文件,然后指向 wsdl,這和使用其他類型的 web 引用一樣。這個對話框在后臺運行在 web service 的 wsdl 上的 sproxy.exe 實用程序(對于非本機的 .net web services 有另外一個實用程序)。
該操作將創建 web service 代理文件,包含要求利用所請求的 web service 的全部 c++ 代碼。使用 wsdl 中的信息,代理生成器能夠判斷 web service 要接收到的數據以及它要返回給客戶端的數據。這就允許代理生成器創建可以和 web service“交談”的頭文件。
您只需創建自己的 web service 類(如在生成的頭文件中查找到的一樣)的實例,并且使用合適的方法即可,例如:
cweb_service_exampleserviceservice myservice;
ccombstr bstrout;
ccombstr bstrin(l"world");
myservice.helloworld ( bstrin ,&bstrout,);
wprintf(bstrout);
現在,您就已經有一個基本的 atl server web service 和 atl server web service consumer 了。
總結
本文的主要目的是對 .net 框架和 visual studio.net 中的 soap 功能作一個總體的介紹。其次,就如何創建使用 soap 的應用程序,給用戶一些有益的指導。