演练:自定义服务说明和代理类的生成

本主题专门介绍一项旧有技术。现在应通过使用以下链接来创建 XML Web 服务和 XML Web 服务客户端: Windows Communication Foundation.

通过创建和安装服务说明格式扩展 (SDFE) 可为使用 ASP.NET 创建的 Web 服务扩展服务说明和代理类的生成。特别需要说明的是,SDFE 可向服务说明(Web 服务的 Web 服务描述语言 (WSDL) 文档)中添加 XML 元素,还可以向与 Web 服务进行通信的方法添加自定义特性。

SDFE 在 SOAP 扩展必须与 Web 服务及其客户端同时运行时非常有用;默认情况下,不会将有关 SOAP 扩展的信息放置在为其生成的服务说明或代理类中。必须在客户端和服务器上同时运行的 SOAP 扩展的一个示例是加密 SOAP 扩展。如果在服务器上执行加密 SOAP 扩展以对 SOAP 响应进行加密,客户端必须使 SOAP 扩展运行才能对消息进行解密。SDFE 可向服务说明中添加元素以通知客户端必须运行 SOAP 扩展,SDFE 还可以扩展代理类生成过程,以向代理类添加自定义特性,这将导致该类运行 SOAP 扩展。本演练演示了下列任务:

  1. 定义要添加到服务说明中的 XML。

  2. 通过从 ServiceDescriptionFormatExtension 类派生来创建 SDFE 类。

  3. 编写代码以扩展服务说明生成过程。

  4. 编写代码以扩展代理类生成过程。

  5. 将 SDFE 配置为同时在客户端和服务器上运行。

定义 XML 和创建 SDFE 类

此演练中的代码示例涉及用于 SoapExtensionYMLExtensionServiceDescriptionFormateExtensionYMLOperationBinding。主题如何:自定义服务说明和代理类的生成(示例代码)中显示了完整代码。

定义要添加到服务说明中的 XML

  1. 确定要添加到服务说明中的 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>
    
  2. 创建一个从 ServiceDescriptionFormatExtension 派生的类。

    使用 Visual Studio .NET 时,添加一个对 System.Web.Services 程序集的引用。还要为 System.Web.Services.Description 命名空间向文件中添加 usingImports 语句。

    下面的代码示例创建从 ServiceDescriptionFormatExtension 派生的 YMLOperationBinding 类。

    Public Class YMLOperationBinding
        Inherits ServiceDescriptionFormatExtension
    
    public class YMLOperationBinding : ServiceDescriptionFormatExtension
    
  3. 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
    
  4. 也可以将 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 
    
  5. 将公共属性和字段添加到表示要添加到 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 类派生一个类。

扩展服务说明生成过程

  1. 创建一个从 SoapExtensionReflector 派生的类。

    下面的代码示例创建从 SoapExtensionReflector 派生的 TraceReflector 类。

    Public Class YMLReflector
        Inherits SoapExtensionReflector
    
    public class YMLReflector : SoapExtensionReflector
    
  2. 重写 ReflectMethod 方法,在每个 Web 服务方法的服务说明生成过程中会调用该方法。

    下面的代码示例重写 ReflectMethod

    Public Overrides Sub ReflectMethod()
    
    public override void ReflectMethod()
    
  3. 获取 SoapExtensionReflector 类的 ReflectionContext 属性的值,以获取 ProtocolReflector 的实例。

    ProtocolReflector 的实例可为当前 Web 服务方法提供有关 WSDL 生成过程的详细信息。下面的代码示例获取 ReflectionContext 属性的值。

    Dim reflector As ProtocolReflector = ReflectionContext
    
    ProtocolReflector reflector = ReflectionContext;
    
  4. 添加代码以填充 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);
    
  5. 将 SDFE 添加到表示 SDFE 正在扩展的扩展点的属性的 Extensions 集合中。

    下面的代码示例将 YmlOperationBinding SDFE 添加到 OperationBinding 扩展点。

    reflector.OperationBinding.Extensions.Add(yml)
    
    reflector.OperationBinding.Extensions.Add(yml);
    

扩展代理类生成过程

  1. 创建一个从 SoapExtensionImporter 派生的类。

    Public Class YMLImporter
        Inherits SoapExtensionImporter
    
    public class YMLImporter : SoapExtensionImporter
    
  2. 重写 ImportMethod 方法。

    在代理类生成过程中,会为服务说明中定义的每个操作调用 ImportMethod。对于使用 ASP.NET 创建的 Web 服务,每个 Web 服务方法都会为服务说明中的每个受支持协议映射到一个操作。

    Public Overrides Sub ImportMethod(ByVal metadata As _
                                      CodeAttributeDeclarationCollection)
    
    public override void ImportMethod(CodeAttributeDeclarationCollection
                                      metadata)   
    
  3. 获取 SoapExtensionImporterImportContext 属性的值,以获取 SoapProtocolImporter 的实例。

    SoapProtocolImporter 的实例可为与 Web 服务方法通信的当前方法提供有关代码生成过程的详细信息。下面的代码示例获取 ImportContext 属性的值。

    Dim importer As SoapProtocolImporter = ImportContext
    
    SoapProtocolImporter importer = ImportContext;  
    
  4. 添加代码,以便在与 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 服务一起运行

  1. 在可访问的文件夹中安装包含 SDFE 的程序集。

    除非多个 Web 应用程序都需要使用 SDFE,否则只需将 SDFE 安装在承载 Web 服务的 Web 应用程序的 \bin 文件夹中。

  2. 将带有 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>
    
  3. 将带有 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 服务客户端一起运行

  1. 在全局程序集缓存中安装包含 SDFE 的程序集。

    若要安装程序集,该程序集必须具有强名称。有关创建具有强名称的程序集的更多信息,请参见创建和使用具有强名称的程序集。有关安装程序集的更多信息,请参见将程序集安装到全局程序集缓存中

  2. 将带有 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>
    
  3. 将带有 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>
    
    x4s9z3yc.note(zh-cn,VS.100).gif注意:
    代理类中生成的方法由与 Web 服务进行通信的客户端应用程序使用,因此,如果 SDFE 添加的特性驻留在某一程序集中且未就此向客户端应用程序发出通知,则会产生编译器错误。为了解决该编译器错误,如果使用的是 Visual Studio .NET,则可添加对包含相应特性的程序集的引用;如果使用的是命令行编译,则需将该程序集添加到编译器命令行。

另请参见

任务

演练:自定义服务说明和代理类的生成

参考

XmlFormatExtensionAttribute
XmlFormatExtensionPrefixAttribute
XmlFormatExtensionPointAttribute

概念

使用 SOAP 扩展修改 SOAP 消息