Modificación de mensajes SOAP con extensiones SOAP
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.
Las extensiones SOAP permiten a los programadores aumentar la funcionalidad de un servicio Web modificando los mensajes SOAP enviados a y desde un servicio Web o un cliente de servicios Web. Por ejemplo, puede implementar un cifrado o algoritmo de compresión para ejecutarse con un servicio Web existente.
Para comprender cómo funciona una extensión SOAP, es útil primero entender la duración de un servicio Web. Para obtener más información, consulte Anatomía de la duración de un servicio web XML.
La ilustración siguiente describe las principales fases de una llamada de un cliente a un servicio Web.
Como puede ver, .NET Framework serializa y deserializa XML durante las fases en el equipo del servicio Web y en el equipo del cliente de servicios Web. Se puede insertar una extensión SOAP en la infraestructura que va a inspeccionar o modificar los mensajes SOAP antes y después de cada una de estas fases de serialización y deserialización. Por ejemplo, una extensión SOAP de cifrado podría cifrar la parte XML del mensaje SOAP después de que .NET Framework serialice los argumentos del cliente y, a continuación, podría descifrar el mensaje SOAP en el servidor web antes de que .NET Framework deserialice el mensaje SOAP. Estas fases, donde una extensión SOAP podría inspeccionar o modificar el mensaje SOAP, se define en la enumeración SoapMessageStage. En este caso, la extensión SOAP está cifrando en la fase AfterSerialize y descifrando en la fase BeforeDeserialize.
Normalmente, cuando una extensión SOAP modifica el contenido de un mensaje SOAP, las modificaciones se deben hacer en el cliente y el servidor. Es decir, si una extensión SOAP fuera ejecutarse en el cliente y cifrar el mensaje SOAP, una extensión SOAP relacionada debe descifrar el mensaje SOAP en el servidor. Si no se descifra el mensaje SOAP, la infraestructura de ASP.NET no puede deserializar el mensaje SOAP en un objeto.
Una extensión SOAP que no modifica el mensaje SOAP, como una extensión SOAP que simplemente registre mensajes SOAP, solo se puede ejecutar en el cliente o en el servidor. En este caso, el destinatario recibe el mismo mensaje SOAP si tuviera una extensión SOAP que no se estaba ejecutando y la infraestructura de ASP.NET pudiera deserializar el mensaje SOAP. Además, si la extensión SOAP no modifica el SOAP de forma que haga imposible la deserialización, la extensión SOAP no necesita ejecutarse en el cliente y en el servidor.
Extender la clase SOAPExtension
Para implementar una extensión SOAP, derive una clase de la clase SoapExtension. Habría que, o se deberían, implementar tres métodos de la clase SOAPExtension:
ChainStream, un método virtual
GetInitializer, un método abstracto con dos firmas
Initialize, un método abstracto
ProcessMessage, un método abstracto
La forma de implementar estos métodos se explica en el tema paso a paso Tutorial: Modificar el mensaje SOAP mediante las extensiones SOAP.
El método ChainStream se pasa a un objeto Stream y devuelve un objeto Stream. Cuando la extensión SOAP se ejecuta durante cada SoapMessageStage y modifica el mensaje SOAP, una extensión SOAP debería leerse de la Stream pasada en ChainStream y escribirse en la Stream devuelta por ChainStream. Por consiguiente, es importante asignar dentro del método ChainStream ambas referencias Stream a las variables miembro.
La clase que deriva de SoapExtension usa los métodos GetInitializer e Initialize para inicializar los datos internos, basados en el servicio Web o el método de servicio Web al que se aplica. Por ejemplo, una extensión SOAP que registra el mensaje SOAP enviado a y desde un método de servicio Web podría inicializar el nombre de un archivo para guardar la información de registro (basándose en el nombre del servicio Web o el método de servicio Web con el que se está ejecutando la extensión SOAP).
En qué punto la infraestructura de servicios Web llama al método GetInitializer y qué parámetros se pasan al método depende de cómo se configure la extensión SOAP, como se ve a continuación:
Si la extensión SOAP se configura mediante un atributo, la infraestructura de los servicios Web llama al method la primera vez que se tiene acceso al servicio Web GetInitializer.
Si la extensión SOAP se configura en un archivo de configuración, la infraestructura de los servicios Web llama a GetInitializer solo la primera vez que se tiene acceso a todo el servicio Web.
La infraestructura de los servicios Web almacena en memoria caché el objeto que devuelve el método GetInitializer. A continuación, cada vez que la extensión SOAP se ejecuta con ese servicio Web o método de servicio Web, la infraestructura pasa el objeto inicializador al método Initialize.
El método ProcessMessage realiza el procesamiento extendido real más allá del procesamiento SOAP estándar. Cada vez que la infraestructura de los servicios Web llama a ProcessMessage, pasa (como un argumento) una instancia de una clase derivada de SoapMessage que contiene información sobre el mensaje SOAP en esa fase determinada. Si la extensión SOAP se está ejecutando con un servicio Web, se pasa un objeto SoapServerMessage. Si la extensión SOAP se está ejecutando con un cliente de servicios Web, se pasa un objeto SoapClientMessage.
Excepciones y extensiones de SOAP
Las extensiones de SOAP nunca deben iniciarse a si mismas. Pueden, sin embargo, agregar información de excepciones a la propiedad Exception en el objeto SoapMessage pasado en el método ProcessMessage.
También pueden actuar como controladores de excepciones en toda la aplicación con la misma facilidad para capturar todas las excepciones en la aplicación para la que se instale la extensión SOAP y realizar algunas acciones incluida la modificación del error de SOAP devuelto.
Orden en el que se invocan los métodos de extensión SOAP
Ahora que ha examinado los métodos que invalida una extensión SOAP, vea cuándo la infraestructura de los servicios Web invoca los métodos de extensión SOAP durante toda la invocación de un método de servicio Web. Los pasos siguientes suponen que la extensión SOAP se está ejecutando en el cliente y en el servidor. Si la extensión SOAP no se está ejecutando en el cliente y en el servidor, .NET Framework omite los pasos asociados a la extensión SOAP que se ejecuta en cada uno.
En el lado del cliente se prepara un mensaje de solicitud
Un cliente invoca un método en la clase de proxy.
En el cliente se crea una nueva instancia de la extensión SOAP.
Si es la primera vez que ha ejecutado esta extensión SOAP con este servicio Web en el cliente, se invoca el método GetInitializer en la extensión SOAP que se ejecuta en el cliente.
Se invoca el método Initialize.
Se invoca el método ChainStream.
Se invoca el método ProcessMessage con el valor de SoapMessageStage establecido en BeforeSerialize.
ASP.NET en el equipo cliente serializa los argumentos del método de servicio Web en XML.
Se invoca el método ProcessMessage con el valor de SoapMessageStage establecido en AfterSerialize.
ASP.NET en el equipo cliente envía el mensaje SOAP a través de la red al servidor web que hospeda el servicio Web.
En el lado del servidor se recibe un mensaje de solicitud y se prepara una respuesta
ASP.NET en el servidor web recibe el mensaje SOAP.
En el servidor web se crea una nueva instancia de la extensión SOAP.
En el servidor web, si es la primera vez que se ha ejecutado esta extensión SOAP con este servicio Web en el lado del servidor, se invoca el método GetInitializer en la extensión SOAP que se ejecuta en el servidor.
Se invoca el método Initialize.
Se invoca el método ChainStream.
Se invoca el método ProcessMessage con el valor de SoapMessageStage establecido en BeforeDeserialize.
ASP.NET deserializa los argumentos dentro de XML.
Se invoca el método ProcessMessage con el valor de SoapMessageStage establecido en AfterDeserialize.
ASP.NET crea una nueva instancia de la clase que implementa el servicio Web e invoca el método de servicio Web, pasando los argumentos deserializados. Este objeto reside en el mismo equipo que el servidor web.
El método de servicio Web ejecuta su código, estableciendo finalmente el valor devuelto y los parámetros out.
Se invoca el método ProcessMessage con el valor de SoapMessageStage establecido en BeforeSerialize.
ASP.NET en el servidor web serializa el valor devuelto y los parámetros out en XML.
Se invoca el método ProcessMessage con el valor de SoapMessageStage establecido en AfterSerialize.
ASP.NET envía el mensaje de respuesta SOAP a través de la red al cliente de servicios Web.
En el lado del cliente se recibe un mensaje de respuesta
ASP.NET en el equipo cliente recibe el mensaje SOAP.
Se invoca el método ProcessMessage con el valor de SoapMessageStage establecido en BeforeDeserialize.
ASP.NET deserializa el XML en el valor devuelto y los parámetros out.
Se invoca el método ProcessMessage con el valor de SoapMessageStage establecido en AfterDeserialize.
ASP.NET pasa el valor devuelto y los parámetros out a la instancia de la clase de proxy.
El cliente recibe el valor devuelto y los parámetros out.
Implementar la extensión SOAP
Hay dos maneras de ejecutar una extensión SOAP en un cliente o en una aplicación de servidor. Primero, puede configurar la aplicación para ejecutar la extensión. Para configurar su extensión SOAP para que se ejecute en todos los métodos web en todos los servicios Web, sobre todo vroot, modifique la sección <soapExtensionTypes> (Elemento) del archivo Web.config. El código siguiente muestra que el valor del atributo type debe estar en una línea e incluir el nombre completo de la extensión, además de la versión, la referencia cultural y el token de clave pública del ensamblado firmado.
<configuration>
<system.web>
<webServices>
<soapExtensionTypes>
<add type="Contoso.MySoapExtension, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
priority="1" group="0"/>
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
Segundo, puede crear un atributo personalizado que se aplique a un método de servicio Web. Para crear el atributo personalizado, cree una clase que derive de SoapExtensionAttribute. Para obtener detalles sobre cómo crear un atributo personalizado, consulte Cómo: Implementar una extensión SOAP. Para obtener más información sobre cómo crear atributos personalizados, consulte Crear atributos personalizados.
Nota: |
---|
Al implementar una extensión SOAP, existe la posibilidad de que se pueda intentar un ataque por denegación de servicio (DOS) si su extensión usa XmlTextReader para leer el flujo de datos. Una forma de evitar este tipo de ataque es asegurarse que la propiedad ProhibitDtd está establecida en true. |
Prioridades y grupos de prioridades
Usando los atributos o la configuración, se puede asignar una prioridad a las extensiones SOAP que las ayude a determinar el orden relativo de ejecución cuando se configuran varias extensiones SOAP para ejecutarse con un método de servicios Web XML. Cuanto más alta sea la prioridad de una extensión SOAP con mayor probabilidad se ejecutará en el mensaje SOAP que se está enviando o recibiendo a través de la red. Las extensiones SOAP pertenecen a uno de tres grupos de prioridades. Dentro de cada grupo, la propiedad priority distingue cada miembro. Cuanto más baja es la propiedad priority, más alta es la prioridad relativa (0 es la más alta).
Los tres grupos de prioridades relativas para extensiones SOAP son: extensiones SOAP configuradas mediante un atributo y extensiones SOAP especificadas en el archivo de configuración con un valor group de 0 o 1. Sus prioridades se ordenan de la forma siguiente:
Grupo de prioridades máximas: extensiones SOAP configuradas mediante un archivo de configuración con un valor group de 0.
Grupo de prioridades medio: extensiones SOAP configuradas mediante un atributo.
Grupo de prioridades mínimas: extensiones SOAP configuradas mediante un archivo de configuración con un valor group de 1.
El ejemplo de código siguiente es un archivo de configuración que especifica que la extensión SOAP Logger.LoggerExtension
se ejecuta dentro del grupo de prioridades relativas 0
y tiene una prioridad de 1
.
<configuration>
<system.web>
<webServices>
<soapExtensionTypes>
<add type="Logger.LoggerExtension,logger"
priority="1"
group="0" />
</soapExtensionTypes>
</webServices>
</system.web>
</configuration>
Vea también
Tareas
Cómo: Implementar una extensión SOAP
Referencia
SoapExtension
SoapExtensionAttribute
SoapMessageStage
LogicalMethodInfo
Conceptos
Modificación de mensajes SOAP con extensiones SOAP
Anatomía de la duración de un servicio web XML
Generar clientes de servicios web XML