演练:自定义服务说明和代理类的生成
通过创建和安装服务说明格式扩展 (SDFE) 可为使用 ASP.NET 创建的 Web 服务扩展服务说明和代理类的生成。 特别需要说明的是,SDFE 可向服务说明(Web 服务的 Web 服务描述语言 (WSDL) 文档)中添加 XML 元素,还可以向与 Web 服务进行通信的方法添加自定义属性。
SDFE 在 SOAP 扩展必须与 Web 服务及其客户端同时运行时非常有用;默认情况下,不会将有关 SOAP 扩展的信息放置在为其生成的服务说明或代理类中。 必须在客户端和服务器上同时运行的 SOAP 扩展的一个示例是加密 SOAP 扩展。 如果在服务器上执行加密 SOAP 扩展以对 SOAP 响应进行加密,客户端必须使 SOAP 扩展运行才能对消息进行解密。 SDFE 可向服务说明中添加元素以通知客户端必须运行 SOAP 扩展,SDFE 还可以扩展代理类生成过程,以向代理类添加自定义属性,这将导致该类运行 SOAP 扩展。 通过此演练,您将学会如何执行以下任务:
定义 XML 以添加到服务说明中。
通过从 ServiceDescriptionFormatExtension 类派生来创建 SDFE 类。
编写代码以扩展服务说明生成过程。
编写代码以扩展代理类生成过程。
将 SDFE 配置为同时在客户端和服务器上运行。
定义 XML 和创建 SDFE 类
此演练中的代码示例涉及用于 SoapExtension 类 YMLExtension 的 ServiceDescriptionFormateExtension 类 YMLOperationBinding。 主题“如何:自定义服务说明和代理类的生成(示例代码)”中显示了完整代码。
定义要添加到服务说明中的 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 语句。
下面的代码示例创建从 ServiceDescriptionFormatExtension 派生的
YMLOperationBinding
类。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 扩展点期间向服务说明中添加一个名为<action xmlns="https://www.contoso.com/yml">
的 XML 元素。 对于此示例,以后在将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 命名空间关联。
下面的代码示例指定,
yml
XML 命名空间前缀与服务说明的 definitions 元素中的https://www.contoso.com/yml
命名空间关联。 此外,该前缀还用在 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; } }
扩展服务说明和客户端代理的生成
若要扩展 WSDL 生成过程,请从 SoapExtensionReflector 类派生一个类。 若要扩展客户端代理生成过程,请从 SoapExtensionImporter 类派生一个类。
扩展服务说明生成过程
创建一个从 SoapExtensionReflector 派生的类。
下面的代码示例创建从 SoapExtensionReflector 派生的
TraceReflector
类。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);
扩展代理类生成过程
创建一个从 SoapExtensionImporter 派生的类。
Public Class YMLImporter Inherits SoapExtensionImporter
public class YMLImporter : SoapExtensionImporter
重写 ImportMethod 方法。
在代理类生成过程中,会为服务说明中定义的每个操作调用 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 服务进行通信的代理类中应用或修改某一方法的属性。
ImportMethod 传入一个 CodeAttributeDeclarationCollection 类型的参数,该参数表示应用于与 Web 服务方法进行通信的方法的属性集合。 下面的代码示例向该集合中添加一个
YMLAttribute
,这将导致在服务说明包含相应 XML 时YML
SOAP 扩展与该方法一起运行。' 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 文件夹中。
将带有 add 元素的 <serviceDescriptionFormatExtensionTypes> 元素 元素添加到 Web 应用程序的 Web.config 文件中,并指定包含 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>
将带有 add 元素的 <soapExtensionReflectorTypes> 元素 元素添加至 Web 应用程序的 Web.config 文件中,并指定扩展服务说明生成过程的类的名称和程序集。
下面的代码示例配置
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 的程序集。
若要安装程序集,该程序集必须具有强名称。 有关创建强名称程序集的详细信息,请参见创建和使用强名称程序集。 有关安装程序集的详细信息,请参见将程序集安装到全局程序集缓存中。
将带有 add 元素的 <serviceDescriptionFormatExtensionTypes> 元素 元素添加到 Machine.config 文件中,并指定包含 SDFE 的名称和程序集。
下面的代码示例将
Sample.YMLOperationBinding
SDFE 配置为在计算机上为 Web 服务生成代理类时运行。<system.web> <webServices> <serviceDescriptionFormatExtensionTypes> <add type="Sample.YMLOperationBinding,Yml, Version=1.0.0.0,Culture=neutral, PublicKeyToken=6e55c64c6b897b30"/> </serviceDescriptionFormatExtensionTypes> </webServices> </system.web>
将带有 add 元素的 <soapExtensionImporterTypes> 元素 元素添加到 Machine.config 文件中,并指定扩展代理类生成过程的类的名称和程序集。
下面的代码示例将
Sample.YMLImporter
配置为在计算机上为 Web 服务生成代理类时运行。<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 服务进行通信的客户端应用程序使用,因此,如果 SDFE 添加的属性驻留在某一程序集中且未就此向客户端应用程序发出通知,则会产生编译器错误。 为了解决该编译器错误,如果使用的是 Visual Studio .NET,则可添加对包含相应属性的程序集的引用;如果使用的是命令行编译,则需将该程序集添加到编译器命令行。
请参见
任务
参考
XmlFormatExtensionAttribute
XmlFormatExtensionPrefixAttribute
XmlFormatExtensionPointAttribute
概念
版权所有 (C) 2007 Microsoft Corporation。保留所有权利。