Tutorial: Personalizar la generación de descripciones de servicio y clases de proxy

Este tema es específico de una tecnología heredada. Ahora, los servicios Web XML y los clientes de servicios Web XML deben crearse con Windows Communication Foundation.

La generación de la descripción del servicio y clases de proxy de un servicio Web creada utilizando ASP.NET se puede extender a través de la creación e instalación de una extensión de formato de descripción de servicio (SDFE). Específicamente, un SDFE puede agregar los elementos XML a la descripción del servicio (el documento del lenguaje de descripción de servicios Web (WSDL) para un servicio Web) y agregar los atributos personalizados a un método que comunica con un servicio Web.

SDFE son especialmente útiles cuando una extensión SOAP se debe ejecutar con un servicio Web y sus clientes; ninguna información sobre las extensiones SOAP se ha colocado de forma predeterminada en la descripción del servicio ni en las clases de proxy generadas para él. Un ejemplo de una extensión SOAP que debe ejecutarse tanto en el cliente como en el servidor es una extensión SOAP de cifrado. Si una extensión SOAP de cifrado se ejecuta en el servidor para cifrar la respuesta de SOAP, el cliente debe ejecutar la extensión SOAP para descifrar el mensaje. Un SDFE puede agregar los elementos a la descripción del servicio para informar a los clientes de que debe ejecutarse una extensión SOAP y de que el SDFE puede extender el proceso de generación de clase de proxy para agregar un atributo personalizado a la clase de proxy, lo cual provoca que la clase ejecute la extensión SOAP. En este tutorial se describen las tareas siguientes:

  1. Definir el XML para agregarlo a la descripción del servicio.

  2. Crear una clase SDFE mediante una derivación de la clase ServiceDescriptionFormatExtension.

  3. Escribir el código para extender el proceso de generación de la descripción del servicio.

  4. Escribir el código para extender el proceso de generación de clase de proxy.

  5. Configurar el SDFE para que se ejecute en el cliente y en el servidor.

Definir el XML y crear la clase SDFE

Los ejemplos de código en este tutorial implican una clase ServiceDescriptionFormateExtension``YMLOperationBinding para una clase SoapExtension``YMLExtension. El código completo aparece en el tema Cómo: Personalizar la generación de descripciones de servicio y clases de proxy (Código de ejemplo).

Para definir el XML para agregarlo a la descripción del servicio.

  1. Decídase por el XML para agregarlo a la descripción del servicio.

    El ejemplo de código siguiente es la parte de una descripción del servicio a la que el SDFE del ejemplo agrega los elementos XML. Específicamente, el SDFE del ejemplo declara yml de prefijo de espacio de nombres XML en el elemento de raíz definitions de un documento WSDL y aplica ese espacio de nombres al elemento (y elementos secundarios) yml:action que aparece para enlazar los elementos operation.

    <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. Cree una clase que derive a partir de ServiceDescriptionFormatExtension.

    Al utilizar Visual Studio .NET, agregue una referencia al ensamblado System.Web.Services. Añada también una instrucción using o Imports para el espacio de nombres System.Web.Services.Description al archivo.

    En el siguiente ejemplo de código se crea la clase YMLOperationBinding, que deriva de ServiceDescriptionFormatExtension.

    Public Class YMLOperationBinding
        Inherits ServiceDescriptionFormatExtension
    
    public class YMLOperationBinding : ServiceDescriptionFormatExtension
    
  3. Aplique XmlFormatExtensionAttribute a la clase.

    Este atributo especifica la copia intermedia del proceso de generación de la descripción del servicio, conocido como un punto de la extensión, en el que el SDFE se ejecuta. La tabla siguiente enumera los puntos de extensión definidos y los elementos XML del WSDL generados durante cada punto. Para el punto de la extensión especificado, el elemento WSDL correspondiente se vuelve el elemento primario del elemento que se agrega.

    Punto de extensión Descripción

    ServiceDescription

    Corresponde al elemento raíz definitions de un documento WSDL.

    Types

    Corresponde al elemento types agregado por el elemento definitions de raíz.

    Binding

    Corresponde al elemento binding agregado por el elemento definitions de raíz.

    OperationBinding

    Corresponde al elemento operation agregado por el elemento binding .

    InputBinding

    Corresponde al elemento input agregado por el elemento operation .

    OutputBinding

    Corresponde al elemento output agregado por el elemento operation .

    FaultBinding

    Corresponde al elemento fault agregado por el elemento operation .

    Port

    Corresponde al elemento port agregado por el elemento service .

    Operation

    Corresponde al elemento operation agregado por el elemento portType .

    Al aplicar XmlFormatExtensionAttribute a la clase, también especifica el nombre del elemento XML y el espacio de nombres XML para contener los elementos XML para agregar a la descripción del servicio.

    El ejemplo de código siguiente especifica que el SDFE YMLOperationBinding agrega un elemento XML denominado <action xmlns="https://www.contoso.com/yml">OperationBinding a la descripción del servicio durante el punto de extensión . Para obtener este ejemplo, el espacio de nombres XML https://www.contoso.com/yml se especifica después, cuando el campo YMLOperationBinding.YMLNamespace se agrega a la clase.

    <XmlFormatExtension("action", YMLOperationBinding.YMLNamespace, _
                        GetType(OperationBinding))> _
    Public Class YMLOperationBinding
        Inherits ServiceDescriptionFormatExtension
    
    [XmlFormatExtension("action", YMLOperationBinding.YMLNamespace,
                        typeof(OperationBinding))]
    public class YMLOperationBinding : ServiceDescriptionFormatExtension
    
  4. Opcionalmente, aplique XmlFormatExtensionPrefixAttribute a la clase para asociar el prefijo del espacio de nombres XML al espacio de nombres XML utilizado por el SDFE.

    El ejemplo de código siguiente especifica que el prefijo de espacio de nombres XML yml está asociado al espacio de nombres https://www.contoso.com/yml en el elemento definitions de la descripción del servicio. Además, el prefijo se utiliza en elementos agregados por el SDFE en lugar del espacio de nombres. Por consiguiente, el elemento XML agregado a la descripción del servicio en el paso 3 utiliza ahora el prefijo de espacio de nombres y así el elemento agregado es <yml:action> en lugar de <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. Agregue propiedades públicas y campos a la clase que representa el XML para ser agregado al documento WSDL. El ejemplo de código siguiente agrega una propiedad pública Reverse que se serializa en un elemento <yml:Reverse>value</yml:Reverse> en el WSDL.

    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; }
    }
    

Extender la generación de la descripción del servicio y proxy de cliente

Para extender el proceso de generación de WSDL, derive una clase de la clase SoapExtensionReflector. Para extender el proceso de generación de proxy de cliente, derive una clase de la clase SoapExtensionImporter.

Para extender el proceso de generación de la descripción del servicios

  1. Cree una clase que derive de SoapExtensionReflector.

    En el siguiente ejemplo de código se crea la clase TraceReflector, que se deriva de SoapExtensionReflector.

    Public Class YMLReflector
        Inherits SoapExtensionReflector
    
    public class YMLReflector : SoapExtensionReflector
    
  2. Invalide el método ReflectMethod, al que se llama durante la generación de descripción de servicio para cada método de servicio Web.

    En el ejemplo de código siguiente que invalida ReflectMethod.

    Public Overrides Sub ReflectMethod()
    
    public override void ReflectMethod()
    
  3. Obtenga el valor de la propiedad ReflectionContext de la clase SoapExtensionReflector para obtener una instancia de ProtocolReflector.

    La instancia de ProtocolReflector proporciona los detalles sobre el proceso de la generación de WSDL para el método actual de servicio Web. En el ejemplo de código siguiente se obtiene el valor de la propiedad ReflectionContext.

    Dim reflector As ProtocolReflector = ReflectionContext
    
    ProtocolReflector reflector = ReflectionContext;
    
  4. Agregue código para rellenar el SDFE.

    El ejemplo de código siguiente agrega el XML definido por el SDFE a la descripción del servicio si YMLAttribute se aplica a un método de servicio Web.

    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. Agregue el SDFE a la colección Extensions de la propiedad que representa el punto de la extensión que el SDFE está ampliando.

    El siguiente ejemplo de código agrega el SDFE YmlOperationBinding al punto de extensión OperationBinding.

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

Para extender el proceso de generación de clase de proxy

  1. Cree una clase que derive de SoapExtensionImporter.

    Public Class YMLImporter
        Inherits SoapExtensionImporter
    
    public class YMLImporter : SoapExtensionImporter
    
  2. Reemplace el método ImportMethod .

    Se llama el ImportMethod durante la generación de la clase de proxy para cada operación definida en una descripción del servicio. Para los servicios Web creados mediante ASP.NET, cada método de servicio Web se le asigna a una operación para cada protocolo compatible en la descripción del servicio.

    Public Overrides Sub ImportMethod(ByVal metadata As _
                                      CodeAttributeDeclarationCollection)
    
    public override void ImportMethod(CodeAttributeDeclarationCollection
                                      metadata)   
    
  3. Obtenga el valor de la propiedad ImportContext de SoapExtensionImporter para obtener una instancia de SoapProtocolImporter.

    La instancia de SoapProtocolImporter proporciona los detalles sobre el proceso de generación de código para el método actual que comunica con un método de servicio Web. En el ejemplo de código siguiente se obtiene el valor de la propiedad ImportContext.

    Dim importer As SoapProtocolImporter = ImportContext
    
    SoapProtocolImporter importer = ImportContext;  
    
  4. Agregue el código para aplicar o modificar los atributos a un método en la clase de proxy que comunique con un servicio Web.

    ImportMethod pasa un argumento de tipo CodeAttributeDeclarationCollection, que representa la colección de atributos que se aplican al método que comunica con el método de servicio Web. El ejemplo de código siguiente agrega YMLAttribute a la colección, que hace que la extensión SOAP YML se ejecute con el método cuando la descripción del servicio contiene el XML adecuado.

    ' 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);
       }
    }
    

Configurar el SDFE

Para configurar el SDFE se necesitan los archivos de configuración de edición del servicio Web y del cliente.

Configurar el SDFE para ejecutarse con un servicio Web

  1. Instale el ensamblado que contiene el SDFE en una carpeta accesible.

    A menos que el SDFE se requiera para varias aplicaciones web, instale el SDFE en la carpeta \bin de la aplicación web que hospeda el servicio Web.

  2. Agregue un elemento <serviceDescriptionFormatExtensionTypes> (elemento) con un elemento add y especifique el nombre y ensamblado que contiene el SDFE al archivo Web.config para la aplicación web.

    El ejemplo de código siguiente configura el SDFE Sample.YMLOperationBinding para que se ejecute con todos los servicios Web afectados por el archivo Web.config. El elemento add completo debería estar en una línea.

    <system.web>
       <webServices>
          <serviceDescriptionFormatExtensionTypes>
             <add type="Sample.YMLOperationBinding,Yml,
                  Version=1.0.0.0,Culture=neutral,
                  PublicKeyToken=6e55c64c6b897b30"/>
          </serviceDescriptionFormatExtensionTypes>
       </webServices>
    </system.web>
    
  3. Agregue un elemento <soapExtensionReflectorTypes> (elemento) con un elemento add y especifique el nombre y ensamblado de la clase que extiende el proceso de generación de la descripción del servicio al archivo Web.config para la aplicación web.

    El ejemplo de código siguiente configura el Sample.YMLReflector para que se ejecute con todos los servicios Web afectados por el archivo Web.config. El elemento add completo debería estar en una línea.

    <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>
    

Configurar el SDFE para ejecutarse con un cliente de servicio Web

  1. Instale el ensamblado que contiene el SDFE en la caché de ensamblados global.

    Para instalarse, el ensamblado debe ser con nombre seguro. Para obtener más información sobre cómo crear un ensamblado con nombre seguro, vea Crear y utilizar ensamblados con nombre seguro. Para obtener más información sobre cómo se instala un ensamblado, vea Instalar un ensamblado en la caché de ensamblados global.

  2. Agregue un elemento <serviceDescriptionFormatExtensionTypes> (elemento) con un elemento add y especifique el nombre y ensamblado que contiene el SDFE al archivo Machine.config .

    El ejemplo de código siguiente configura el SDFE Sample.YMLOperationBinding para ejecutarlo cuando se generen las clases de proxy para los servicios Web en el equipo.

    <system.web>
       <webServices>
          <serviceDescriptionFormatExtensionTypes>
             <add type="Sample.YMLOperationBinding,Yml,
                  Version=1.0.0.0,Culture=neutral,
                  PublicKeyToken=6e55c64c6b897b30"/>
          </serviceDescriptionFormatExtensionTypes>
       </webServices>
    </system.web>
    
  3. Agregue un elemento <soapExtensionImporterTypes> (elemento) con un elemento add y especifique el nombre y ensamblado de la clase que extiende el proceso de generación de clase de proxy al archivo Machine.config.

    El ejemplo de código siguiente configura el SDFE Sample.YMLImporter para ejecutarlo cuando se generen las clases de proxy para los servicios Web en el equipo.

    <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(es-es,VS.100).gifNota:
    Una aplicación cliente que comunica con el servicio Web utiliza el método generado en la clase de proxy, por lo que si un SDFE agrega un atributo que reside en un ensamblado del que no se notifica la aplicación cliente, se genera un error del compilador. Para resolver el error del compilador, agregue una referencia al ensamblado que contiene el atributo si utiliza Visual Studio .NET o agregue el ensamblado a la línea de comandos del compilador en caso de utilizar la compilación de la línea de comandos.

Vea también

Tareas

Tutorial: Personalizar la generación de descripciones de servicio y clases de proxy

Referencia

XmlFormatExtensionAttribute
XmlFormatExtensionPrefixAttribute
XmlFormatExtensionPointAttribute

Conceptos

Modificación de mensajes SOAP con extensiones SOAP