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:
Definir el XML para agregarlo a la descripción del servicio.
Crear una clase SDFE mediante una derivación de la clase ServiceDescriptionFormatExtension.
Escribir el código para extender el proceso de generación de la descripción del servicio.
Escribir el código para extender el proceso de generación de clase de proxy.
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.
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>
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
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 XMLhttps://www.contoso.com/yml
se especifica después, cuando el campoYMLOperationBinding.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
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 nombreshttps://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
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
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
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()
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;
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);
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
Cree una clase que derive de SoapExtensionImporter.
Public Class YMLImporter Inherits SoapExtensionImporter
public class YMLImporter : SoapExtensionImporter
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)
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;
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 SOAPYML
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
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.
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>
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
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.
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>
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>
Nota: 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