逐步解說:自訂服務描述和 Proxy 類別的產生
本主題專門說明舊有技術。 應該使用下列建立 XML Web Service 及 XML Web Service 用戶端: Windows Communication Foundation.
透過建立和安裝服務描述格式延伸 (SDFE) 可以擴充 Web 服務 (使用 ASP.NET 所建立) 的服務描述和 Proxy 類別產生作業。具體來說,SDFE 可以將 XML 項目新增至服務描述 (即 Web 服務的 Web 服務描述語言 (WSDL) 文件),並將自訂屬性新增至與 Web 服務通訊的方法。
當 SOAP 擴充功能必須搭配 Web 服務及其用戶端一起執行時,SDFE 會特別有用;根據預設,並不會將 SOAP 擴充功能的資訊放在產生的相關服務描述或 Proxy 類別中。必須同時在用戶端和伺服器上執行的 SOAP 擴充功能例子,就是加密 SOAP 擴充功能。如果加密 SOAP 擴充功能會在伺服器上執行以加密 SOAP 回應,用戶端就必須執行 SOAP 擴充功能才能解密訊息。SDFE 可以將項目新增至服務描述來通知用戶端務必執行 SOAP 擴充功能,而且 SDFE 也可以擴充 Proxy 類別產生處理序,將自訂屬性新增至 Proxy 類別,以促使這個類別執行 SOAP 擴充功能。本逐步解說將示範下列工作:
定義要新增至服務描述的 XML。
透過衍生自 ServiceDescriptionFormatExtension 類別的方式建立 SDFE 類別。
撰寫程式碼以擴充服務描述產生處理序。
撰寫程式碼以擴充 Proxy 類別產生處理序。
將 SDFE 設定為可以在用戶端和伺服器上執行。
定義 XML 和建立 SDFE 類別
本逐步解說中的程式碼範例中,包含 SoapExtension
類別 YMLExtension
的 ServiceDescriptionFormateExtension
類別 YMLOperationBinding
。HOW TO:自訂服務描述和 Proxy 類別的產生 (範例程式碼) 主題中會提供完整的程式碼。
若要定義要新增至服務描述的 XML
決定要新增至服務描述的 XML。
下列程式碼範例是範例 SDFE 將 XML 項目新增至服務描述的部分。具體來說,範例 SDFE 會在 WSDL 文件的根 definitions 項目中宣告 XML 命名空間前置詞
yml
,然後將該命名空間套用至出現在繫結 operation 項目中的yml:action
項目 (和子項目)。<definitions ... xmlns:yml="https://www.contoso.com/yml" > ... <binding name="HelloWorldSoap" type="s0:HelloWorldSoap"> <soap:binding transport="https://schemas.xmlsoap.org/soap/http" style="document" /> <operation name="SayHello"> <soap:operation soapAction="http://tempuri.org/SayHello" style="document" /> <yml:action> <yml:Reverse>true</yml:Reverse> </yml:action> </operation> ... </binding> ... </definitions>
建立衍生自 ServiceDescriptionFormatExtension 的類別。
使用 Visual Studio .NET 時,請新增 System.Web.Services 組件的參考。同時還要在檔案中新增 System.Web.Services.Description 命名空間的 using 或 Imports 陳述式。
下列程式碼範例會建立
YMLOperationBinding
類別,這個類別是衍生自 ServiceDescriptionFormatExtension。Public Class YMLOperationBinding Inherits ServiceDescriptionFormatExtension
public class YMLOperationBinding : ServiceDescriptionFormatExtension
將 XmlFormatExtensionAttribute 套用至類別。
這個屬性會指定 SDFE 執行時所在的服務描述產生處理序階段 (稱為擴充點)。下表列出已定義的擴充點以及在各個點上產生的 WSDL XML 項目。對已指定的擴充點來說,對應的 WSDL 項目會成為所新增項目的父代。
擴充點 描述 ServiceDescription
對應到 WSDL 文件的根 definitions 項目。
Types
對應到根 definitions 項目所括住的 types 項目。
Binding
對應到根 definitions 項目所括住的 binding 項目。
OperationBinding
對應到 binding 項目所括住的 operation 項目。
InputBinding
對應到 operation 項目所括住的 input 項目。
OutputBinding
對應到 operation 項目所括住的 output 項目。
FaultBinding
對應到 operation 項目所括住的 fault 項目。
Port
對應到 service 項目所括住的 port 項目。
Operation
對應到 portType 項目所括住的 operation 項目。
將 XmlFormatExtensionAttribute 套用至類別時,您還要指定 XML 項目名稱和 XML 命名空間,以便用來包含要新增至服務描述的 XML 項目。
下列程式碼範例會指定
YMLOperationBinding
SDFE 要在 OperationBinding 擴充點上將 XML 項目<action xmlns="https://www.contoso.com/yml">
新增至服務描述。這個範例會在稍後將YMLOperationBinding.YMLNamespace
欄位新增至類別時,指定 XML 命名空間https://www.contoso.com/yml
。<XmlFormatExtension("action", YMLOperationBinding.YMLNamespace, _ GetType(OperationBinding))> _ Public Class YMLOperationBinding Inherits ServiceDescriptionFormatExtension
[XmlFormatExtension("action", YMLOperationBinding.YMLNamespace, typeof(OperationBinding))] public class YMLOperationBinding : ServiceDescriptionFormatExtension
或者,也可以將 XmlFormatExtensionPrefixAttribute 套用至類別,讓 XML 命名空間前置詞與 SDFE 使用的 XML 命名空間產生關聯。
下列程式碼範例會指定將服務描述之 definitions 項目中的
https://www.contoso.com/yml
命名空間與yml
XML 命名空間前置詞產生關聯。此外,還會在 SDFE 新增的項目中使用前置詞,而不在命名空間中使用。因此,在步驟 3 中新增至服務描述的 XML 項目現在會使用命名空間前置詞,所以新增的項目是<yml:action>
,而不是<action xmlns="https://www.contoso.com/yml">
。<XmlFormatExtension("action", YMLOperationBinding.YMLNamespace, _ GetType(OperationBinding)), _ XmlFormatExtensionPrefix("yml", YMLOperationBinding.YMLNamespace)> _ Public Class YMLOperationBinding Inherits ServiceDescriptionFormatExtension
[XmlFormatExtension("action", YMLOperationBinding.YMLNamespace, typeof(OperationBinding))] [XmlFormatExtensionPrefix("yml", YMLOperationBinding.YMLNamespace)] public class YMLOperationBinding : ServiceDescriptionFormatExtension
將公用屬性和欄位新增至代表要在 WSDL 文件中新增之 XML 的類別。下列程式碼範例會新增已序列化為 WSDL 內之
<yml:Reverse>value</yml:Reverse>
項目的Reverse
公用屬性。Private _reverse As Boolean <XmlElement("Reverse")> _ Public Property Reverse() As Boolean Get Return _reverse End Get Set(ByVal Value As Boolean) _reverse = Value End Set End Property
private Boolean reverse; [XmlElement("Reverse")] public Boolean Reverse { get { return reverse; } set { reverse = value; } }
擴充服務描述和用戶端 Proxy 的產生
若要擴充 WSDL 產生處理序,請從 SoapExtensionReflector 類別衍生類別。若要擴充用戶端 Proxy 產生處理序,請從 SoapExtensionImporter 類別衍生類別。
若要擴充服務描述產生處理序
建立衍生自 SoapExtensionReflector 的類別。
下列程式碼範例會建立
TraceReflector
類別,這個類別是衍生自 SoapExtensionReflector。Public Class YMLReflector Inherits SoapExtensionReflector
public class YMLReflector : SoapExtensionReflector
覆寫 ReflectMethod 方法,在每個 Web 服務方法的服務描述產生期間將會呼叫這個方法。
下列程式碼範例會覆寫 ReflectMethod。
Public Overrides Sub ReflectMethod()
public override void ReflectMethod()
取得 SoapExtensionReflector 類別的 ReflectionContext 屬性值,以取得 ProtocolReflector 的執行個體。
ProtocolReflector 的執行個體會提供有關目前 Web 服務方法之 WSDL 產生處理序的詳細資訊。下列程式碼範例會取得 ReflectionContext 屬性的值。
Dim reflector As ProtocolReflector = ReflectionContext
ProtocolReflector reflector = ReflectionContext;
新增要填入 SDFE 的程式碼。
如果將
YMLAttribute
套用至 Web 服務方法,下列程式碼範例便會將 SDFE 定義的 XML 新增至服務描述。Dim attr As YMLAttribute = _ reflector.Method.GetCustomAttribute(GetType(YMLAttribute)) ' If the YMLAttribute has been applied to this Web service ' method, adds the XML defined in the YMLOperationBinding class. If (Not attr Is Nothing) Then Dim yml As YMLOperationBinding = New YMLOperationBinding() yml.Reverse = Not attr.Disabled
YMLAttribute attr = (YMLAttribute) reflector.Method.GetCustomAttribute(typeof(YMLAttribute)); // If the YMLAttribute has been applied to this Web service // method, adds the XML defined in the YMLOperationBinding class. if (attr != null) { YMLOperationBinding yml = new YMLOperationBinding(); yml.Reverse = !(attr.Disabled);
將 SDFE 新增至代表擴充點 (SDFE 正在擴充) 之屬性的 Extensions 集合。
下列程式碼範例會將
YmlOperationBinding
SDFE 新增至 OperationBinding 擴充點。reflector.OperationBinding.Extensions.Add(yml)
reflector.OperationBinding.Extensions.Add(yml);
若要擴充 Proxy 類別產生處理序
建立衍生自 SoapExtensionImporter 的類別。
Public Class YMLImporter Inherits SoapExtensionImporter
public class YMLImporter : SoapExtensionImporter
覆寫 ImportMethod 方法。
在為服務描述中定義的各項作業產生 Proxy 類別時,會呼叫 ImportMethod。對使用 ASP.NET 建立的 Web 服務來說,每個 Web 服務方法會對應到服務描述中每個受支援之通訊協定的作業。
Public Overrides Sub ImportMethod(ByVal metadata As _ CodeAttributeDeclarationCollection)
public override void ImportMethod(CodeAttributeDeclarationCollection metadata)
取得 SoapExtensionImporter 的 ImportContext 屬性值,以取得 SoapProtocolImporter 的執行個體。
SoapProtocolImporter 的執行個體會提供有關目前與 Web 服務方法通訊之方法的程式碼產生處理序的詳細資訊。下列程式碼範例會取得 ImportContext 屬性的值。
Dim importer As SoapProtocolImporter = ImportContext
SoapProtocolImporter importer = ImportContext;
新增程式碼,以便將屬性套用至目前與 Web 服務進行通訊之 Proxy 類別中的方法,或為此方法修改屬性。
ImportMethod 會傳入一個型別為 CodeAttributeDeclarationCollection 的引數,這個型別代表已套用至與 Web 服務方法通訊之方法的屬性集合。下列程式碼範例會新增
YMLAttribute
至集合,這將促使YML
SOAP 擴充功能在服務描述包含適當 XML 時與方法一起執行。' Checks whether the XML specified in the YMLOperationBinding is in the ' service description. Dim yml As YMLOperationBinding = _ importer.OperationBinding.Extensions.Find( _ GetType(YMLOperationBinding)) If (Not yml Is Nothing) Then ' Only applies the YMLAttribute to the method when the XML should ' be reversed. If (yml.Reverse) Then Dim attr As CodeAttributeDeclaration = New _ CodeAttributeDeclaration(GetType(YMLAttribute).FullName) attr.Arguments.Add(New CodeAttributeArgument(New _ CodePrimitiveExpression(True))) metadata.Add(attr) End If End If
// Checks whether the XML specified in the YMLOperationBinding is // in the service description. YMLOperationBinding yml = (YMLOperationBinding) importer.OperationBinding.Extensions.Find( typeof(YMLOperationBinding)); if (yml != null) { // Only applies the YMLAttribute to the method when the XML should // be reversed. if (yml.Reverse) { CodeAttributeDeclaration attr = new CodeAttributeDeclaration(typeof(YMLAttribute).FullName); attr.Arguments.Add(new CodeAttributeArgument(new CodePrimitiveExpression(true))); metadata.Add(attr); } }
設定 SDFE
設定 SDFE 時必須同時編輯 Web 服務和用戶端上的組態檔。
若要將 SDFE 設定為與 Web 服務一起執行
將包含 SDFE 的組件安裝在可存取的資料夾中。
除非有多個 Web 應用程式需要使用 SDFE,否則請將 SDFE 安裝在裝載 Web 服務之 Web 應用程式的 \bin 資料夾。
在 Web 應用程式的 Web.config 檔案中,新增具有 add 項目的 <serviceDescriptionFormatExtensionTypes> 項目 項目,並指定名稱和含有 SDFE 的組件。
下列程式碼範例會將
Sample.YMLOperationBinding
SDFE 設定為與所有受 Web.config 檔案影響的 Web 服務一起執行。完整的 add 項目必須在同一行。<system.web> <webServices> <serviceDescriptionFormatExtensionTypes> <add type="Sample.YMLOperationBinding,Yml, Version=1.0.0.0,Culture=neutral, PublicKeyToken=6e55c64c6b897b30"/> </serviceDescriptionFormatExtensionTypes> </webServices> </system.web>
在 Web 應用程式的 Web.config 檔案中,新增具有 add 項目的 <soapExtensionReflectorTypes> 項目 項目,並指定擴充服務描述產生處理序之類別的名稱和組件。
下列程式碼範例會將
Sample.YMLReflector
設定為與所有受 Web.config 檔案影響的 Web 服務一起執行。完整的 add 項目必須在同一行。<system.web> <webServices> <serviceDescriptionFormatExtensionTypes> <add type="Sample.YMLOperationBinding,Yml, Version=1.0.0.0,Culture=neutral, PublicKeyToken=6e55c64c6b897b30"/> </serviceDescriptionFormatExtensionTypes> <soapExtensionReflectorTypes> <add type="Sample.YMLReflector,Yml, Version=1.0.0.0,Culture=neutral, PublicKeyToken=6e55c64c6b897b30"/> </soapExtensionReflectorTypes> </webServices> </system.web>
若要將 SDFE 設定為與 Web 服務用戶端一起執行
將含有 SDFE 的組件安裝在全域組件快取中。
若要安裝組件,則組件必須使用強式名稱。如需詳細資訊建立強式名稱的組件,請參閱建立和使用強式名稱的組件。如需詳細資訊安裝組件,請參閱將組件安裝到全域組件快取。
在 Machine.config 檔案中,新增具有 add 項目的 <serviceDescriptionFormatExtensionTypes> 項目 項目,並指定名稱和含有 SDFE 的組件。
下列程式碼範例會將
Sample.YMLOperationBinding
SDFE 設定為每當在電腦上產生 Web 服務的 Proxy 類別時就執行。<system.web> <webServices> <serviceDescriptionFormatExtensionTypes> <add type="Sample.YMLOperationBinding,Yml, Version=1.0.0.0,Culture=neutral, PublicKeyToken=6e55c64c6b897b30"/> </serviceDescriptionFormatExtensionTypes> </webServices> </system.web>
在 Machine.config 檔案中,新增具有 add 項目的 <soapExtensionImporterTypes> 項目 項目,並指定擴充 Proxy 類別產生處理序之類別的名稱和組件。
下列程式碼範例會將
Sample.YMLImporter
設定為每當在電腦上產生 Web 服務的 Proxy 類別時就執行。<system.web> <webServices> <serviceDescriptionFormatExtensionTypes> <add type="Sample.YMLOperationBinding,Yml, Version=1.0.0.0,Culture=neutral, PublicKeyToken=6e55c64c6b897b30"/> </serviceDescriptionFormatExtensionTypes> <soapExtensionImporterTypes> <add type="Sample.YMLImporter,Yml, Version=1.0.0.0,Culture=neutral, PublicKeyToken=6e55c64c6b897b30"/> </soapExtensionImporterTypes> </webServices> </system.web>
注意: 與 Web 服務進行通訊的用戶端應用程式會使用 Proxy 類別中產生的方法,因此,如果 SDFE 新增位於組件中的屬性,而未告知用戶端應用程式此情況,就會產生編譯器錯誤。若要解決編譯器錯誤,請新增含有該屬性之組件的參考 (使用 Visual Studio .NET 編譯時),或將組件新增至編譯器命令列 (使用命令列編譯時)。
另請參閱
工作
參考
XmlFormatExtensionAttribute
XmlFormatExtensionPrefixAttribute
XmlFormatExtensionPointAttribute