En la mayoría de los casos
WCF
permite mediante la clase
MessageContract
modificar el mensaje
soap
. Si cliente y servidor son
WCF
no debería haber problema para manipular el mensaje usando
MessageContract
y sin duda es el modo más elegante de personalizar un mensaje pero a efectos de
interoperabilidad
no es aplicable en todos los escenarios.
WCF Extensibility
proporciona herramientas con el objetivo que el desarrollador pueda personalizar el comportamiento de diversos aspectos de los servicios como seguridad, hosting, serialización, publicación de metadatos, canales...
En concreto en este artículo veremos como crear un
Message Inspector
personalizado y lo añadiremos a nuestro cliente
WCF
. El objetivo de
Message Inspector
es tener acceso a todos los mensajes de salida y entrada que procesa el cliente para manipular algún aspecto del mensaje
soap
.
En primer lugar crearemos una clase AreaTICMessageInspector:
public class AreaTICMessageInspector: IDispatchMessageInspector, IClientMessageInspector
{
public AreaTICMessageInspector()
{
}
#region IDispatchMessageInspector Members
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
{
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
}
#endregion
#region IClientMessageInspector Members
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
//Copiamos objeto request para poder modificarlo
Message newMessage = null;
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
request = buffer.CreateMessage();
//obtenemos Xml del request
XmlDocument oDoc = new XmlDocument();
using (XmlWriter writer = oDoc.CreateNavigator().AppendChild())
{
request.WriteMessage(writer);
writer.Close();
}
//Manipulamos XML mensaje
//oDoc.Nodes.Add(...) o oDoc.Nodes[0].Attributes...
//Damos el "cambiazo" de request original por el modificado
XmlNodeReader reader = new XmlNodeReader(oDoc);
newMessage = Message.CreateMessage(reader, int.MaxValue, request.Version);
request = newMessage;
return null;
}
#endregion
}
}
En el ejemplo hemos implementado el método
BeforeSendRequest
que nos permite controlar el mensaje de salida en cliente. Si queremos manipular también la respuesta tendríamos que implementar
AfterReceiveReply
.
En segundo lugar hemos de crear una clase AreaTICMessageInspector, es importante implementar la interface
IEndPointBehavior
.
namespace AreaTIC
{
[AttributeUsage(AttributeTargets.Class)]
public class AreaTICMessageInspectorBehavior : Attribute, IEndpointBehavior
{
public AreaTICMessageInspectorBehavior() : base()
{
}
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
IClientMessageInspector inspector = null;
inspector = new AreaTICMessageInspector();
clientRuntime.MessageInspectors.Add(inspector);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
//no es necesaria su implementación en cliente.
}
public void Validate(ServiceEndpoint endpoint)
{
//no es necesaria su implementación en cliente.
}
#endregion
}
}
Por último hemos de añadir en tiempo de ejecución el
EndPointBehavior
personalizado al EndPoint que usa el cliente para comunicar:
client.Endpoint.Behaviors.Add(new AreaTICMessageInspectorBehavior());
Espero que os sea útil este artículo, dentro de
areaTIC
puedes encontrar otros artículos interesantes, no dudes en consultar nuestro archivo.