Introducción a Windows Communication Foundation
PARTE 5
Otras Facilidades de WCF
Transacciones
WCF nos brinda la posibilidad de realizar transacciones con los servicios. Estas transacciones pueden también ser distribuidas, cuando se comparten con más de un servicio.
Para habilitar las transacciones:
- Necesitamos utilizar un Binding adecuado
- Seleccionar el protocolo (WS-AtomicTransacction , OLE Transactions)
- Es posible configurar Timeouts y Niveles de Aislamiento utilizando parámetros de ServiceBehavior
- Habilitar las funcionalidades de transacciones y el comportamiento al completarse la transacción utilizando parámetros de OperationBehavior
- Podemos tener acceso al contexto de la transacción mediante la propiedad “Transaction.Current”
Ejemplo de Transacción:
En el servicio:
[ServiceContract(SessionMode = SessionMode.Required)]
[BindingRequirements(
TransactionFlowRequirements = RequirementsMode.Required)]
public interface IClienteManager
{
[OperationContract()]
[TransactionFlow(TransactionFlowOption.Allowed)]
List<Cliente> DameClientes();
[OperationContract()]
[TransactionFlow(TransactionFlowOption.Allowed)]
void ModificarCliente(int id,
string nuevoNombre, string nuevoApellido);
[OperationContract()]
Cliente BuscarCliente(int id);
}
[ServiceBehavior(TransactionIsolationLevel =
System.Transactions.IsolationLevel.ReadUncommitted,
InstanceContextMode = InstanceContextMode.Single)]
public class ClienteManager : IClienteManager
{
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
public void ModificarCliente(int id, <
span class="kwrd">string nuevoNombre, string nuevoApellido)
{
...
}
}
En el cliente:
try
{
using (TransactionScope tx = new
TransactionScope(TransactionScopeOption.Required))
{
//código de la transacción
tx.Complete();
}
}
catch(Exception e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
Modo de transmisión
Buffer vs Stream: si los mensajes se envían utilizando buffer (patrón duplex) el receptor los aloja en un buffer en memoria hasta que se complete la transmisión y no es posible acceder a los datos hasta que el mensaje sea recibido completamente. En cambio si utilizamos un stream (request-reply) los headers se colocan en un buffer y el body se expone como stream para que pueda ser accedido en partes pequeñas mientras aún se está transmitiendo. Se puede utilizar stream como parámetro o devolverlo como resultado y es ideal para la transmisión de mensajes grandes. Por defecto http, tcp/ip y named pipes utilizan buffer. Este modo de trasferencia se especifica al crear el objeto binding de nuestro endpoint.
Ejemplo:
TcpTransportBindingElement transporte = new TcpTransportBindingElement();
transporte.TransferMode = TransferMode.Streamed;
BinaryMessageEncodingBindingElement codificador = new
BinaryMessageEncodingBindingElement();
CustomBinding binding = new CustomBinding(codificador, transporte);
Ejemplo por archivo de configuración:
<customBinding>
<binding name="streamBinding">
<binaryMessageEncoding />
<tcpTransport transferMode=”Streamed” />
</binding>
</customBinding>
Restricciones derivadas de utilizar transferencias del tipo Stream:
- En el contrato el parámetro o resultado stream debe ser un subtipo de Sytem.IO.Stream o implementar IXmlSerializable.
- Mensajes confiables, transacciones y la seguridad a nivel de mensaje SOAP dependen de una transmisión tipo buffer.
- Los Encabezados (headers) SOAP siempre utilizan buffer y no deben superar la propiedad MaxBufferSize.
El ejemplo que mostramos a continuación es una implementación de streaming que permite escuchar música desde un cliente. La música es publicada por un servicio de WCF.
Ejemplo del Servicio:
[ServiceContract(Namespace = "Test", SessionMode = SessionMode.Allowed)]
public interface IStream
{
[OperationContract()]
Stream Escuchar(string archivo);
[OperationContract()]
List<string> DameTemas();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class StreamMusica : IStream
{
[OperationBehavior()]
public Stream Escuchar(string archivo)
{
string mainPath = @".\Temas\";
mainPath += archivo;
FileStream fs = new FileStream(mainPath,
FileMode.Open, FileAccess.Read);
return fs;
}
[OperationBehavior()]
public List<string> DameTemas()
{
string mainPath = @".\Temas\";
List<string> temas = new List<string>();
foreach (string archivo in Directory.GetFiles(mainPath,"*.wav"))
{
string nombre = Path.GetFileName(archivo);
temas.Add(nombre);
}
return temas;
}
}
App.Config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="NewBehavior">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="NewBinding0" maxBufferSize="65536"
maxReceivedMessageSize="65536"
messageEncoding="Mtom" transferMode="Streamed" />
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="NewBehavior"
name="StreamService.StreamMusica">
<endpoint address="Stream" binding="basicHttpBinding"
bindingConfiguration="NewBinding0"
name="ServiceEndpoint" contract="StreamService.IStream" />
<host>
<baseAddresses>
<add baseAddress="http://master3:8888/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
Ejemplo del Cliente:
private void PLAYBUTTON_Click(object sender, EventArgs e)
{
#region Validar
if (!ValidarArchivo())
{
MsgHelper.ShowError("Debe seleccionar un archivo.");
return;
}
#endregion Validar
try
{
proxy = new StreamClient();
Player.Stream = proxy.Escuchar(bs.Current.ToString());
proxy.Close();
PLAYBUTTON.Enabled = false;
STOPBUTTON.Enabled = true;
Player.Play();
}
catch (Exception x)
{
MsgHelper.ShowError(x.Message);
}
}
Glosario
WCF = Windows Communication Foundation.
MSMQ = Microsoft Message Queuing.
OS = Orientación a Servicios.
OO = Orientación a Objetos.
MTOM = Message Transmission Optimization Mechanism de SOAP.
WSDL = Web Service Description Language.
XSD = XML Schema Definition.
SOAP = Simple Object Access Protocol.
X.509 = Standard de certificados para firmar documentos y garantizar la seguridad en las comunicaciones.
SDK: Software Development Kit (SDK).
Referencias
Programming Indigo, David Pallman, 2005.
MSDN, Windows Communication Foundation, http://msdn2.microsoft.com/en-us/library/ms735119.aspx
MSDN Magazine, Learn The ABCs Of Programming Windows Communication Foundation, http://msdn.microsoft.com/msdnmag/issues/06/02/WindowsCommunicationFoundation/
WCF
wcf