Una vez más aquí estoy con CSF, en este caso para mostrar un sencillo ejemplo con nuestro querido y famoso amigo “Hola Mundo”.

Se trata de un ejemplo muy sencillo, concretamente de una invocación a un servicio web, haciendo uso, claro está, de una sesión de CSF.

Pasos:

  1. Manifiesto
    • Dos participantes .
      • Participante 1 (listener, consola windows).
      • Participante 2 (Web Service “HelloWorld”).
    • Dos reglas para el enrutamientos.
  2. Crear la sesión a partir del manifiesto anterior
  3. Envío asincrono del mensaje
  4. Terminar la sesión

Manifiesto estático (Manifest.xml)

1 <Session timestamp="0001-01-01T00:00:00.0000000-08:00" timeout="30" serialize="None" routeAnyAction="true" ackOnRouteMsgToParticipants="false" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://Microsoft/ConnectedServices/2006/06/Session/"> 2 <SessionName>HelloWorldAsync</SessionName> 3 <Participants> 4 <Participant timeout="30" role="Service" inChannelResponse="true" type="WebService"> 5 <ParticipantName>Listener</ParticipantName> 6 <ParticipantID>0000-0000-0000-0001</ParticipantID> 7 <ParticipantUrl>soap.tcp://csfvpc30:9001/Listener</ParticipantUrl> 8 </Participant> 9 <Participant timeout="30" role="Service" inChannelResponse="true" type="WebService"> 10 <ParticipantName>HelloWorld</ParticipantName> 11 <ParticipantID>0000-0000-0000-0002</ParticipantID> 12 <ParticipantUrl>http://tempuri.org/HelloWorld</ParticipantUrl> 13 </Participant> 14 </Participants> 15 16 <RoutingTable version="0" timestamp="0001-01-01T00:00:00.0000000-08:00"> 17 <Routes> 18 <Route> 19 <Criteria>(ACTION EQ 'http://tempuri.org/HelloWorld)</Criteria> 20 <Destination>HelloWorld[http://tempuri.org/HelloWorld]</Destination> 21 </Route> 22 23 <Route> 24 <Criteria>(ACTION EQ 'http://tempuri.org/HelloWorldResponse)</Criteria> 25 <Destination>Listener[http://elGuerre.loc/HelloWorldRespone]</Destination> 26 </Route> 27 </Routes> 28 </RoutingTable> 29 </Session>

Creación del manifiesto (SessionManifest)

1 private static SessionManifest CreateManifiest(){ 2 using (StreamReader streamReader = new StreamReader(String.Format(@"{0}\Manifest.xml", Environment.CurrentDirectory))) 3 { 4 XmlSerializer xs = XmlSerializerCache.GetXmlSerializer( 5 typeof(SessionManifest), 6 SessionMessageNames.SessionNamespace 7 ); 8 9 return (SessionManifest)xs.Deserialize(streamReader); 10 }}

Añado también los atributos empleados para que no haya ningúna confusión:

1 private static string sessionManagerAdminUri = "http://csfvpc30/Session30/SessionAdminManager.ashx"; 2 private static string sessionUri = "http://csfvpc30/Session30/Session.ashx"; 3 private static string USER = @"csfvpc30\Student"; 4 private static string PASSWORD = "pa$$word"; 5 private static string fromUri = "soap.tcp://csfvpc30:9001/Listener";

Creado el “SessionManifiest”, será necesario crear la sessión a partir del mismo. Para ello consultar el post anterior “Introducion a CSF I“.

El participante 1, es un listener cuya misión es mostrar toda aquella información en la consola de comandos. La siguiente clase crea el listener y captura la respuesta a la petición al Web Service “HelloWorld”

1 namespace HelloWorldAsync{ 2 [CsfService(Namespace = "http://elGuerre.loc/HelloWorldListener/")] 3 public class Listener 4 { 5 public Listener(string uri) 6 { 7 try 8 { 9 WSE3.Addressing.EndpointReference serviceEpr = new WSE3.Addressing.EndpointReference(new Uri(uri)); 10 WSE3.Messaging.SoapReceivers.Add(serviceEpr, this); 11 Console.WriteLine("Servicio inicializado correctamente. Endpoint: '{0}'", uri); 12 } 13 catch (Exception fault) 14 { 15 Console.WriteLine(String.Format("Fallo al añadir el servicio al endpoint {0}: {1}", uri, fault.Message)); 16 } 17 } 18 19 [Operation(Oneway = false, Action = DataTypes.Actions.HelloWorldResponse)] 20 public void SendAsync(Message message) 21 { 22 Console.WriteLine("{0}{1}{2}{3}", 23 Environment.NewLine, 24 "".PadRight(20, '-'), 25 Environment.NewLine, 26 message.BodyElement.InnerXml); 27 } 28 }}

Creada la sessión y, creado y arrancado el participante 1, se realizará el envío asíncrono. Los parámetros; from, replyTo y faultTo, se corresponden con la url del Participante 1 (fromUri) que será el encargado de capturar la respuesta así como del error si lo hubiera.

Envío Asíncrono

1 private static void SendAsync(string from, string replyTo, string faultTo, object messageData) 2 { 3 Header header = new Header(); 4 header.Addressing = new AddressingHeaders( 5 new Uri(fromUri), 6 new Uri(replyTo), 7 new Uri(faultTo)); 8 9 header.Addressing.To = new Uri(sessionUri); 10 header.Addressing.Action = action; 11 header.CsfProperties.SessionId = new Uri(sessionId); 12 13 Message message = Message.CreateMessage(header, messageData); 14 15 // Seguridad 16 message.Header.Security.Add( 17 new Microsoft.ConnectedServices.Sdk.Security.Tokens.UsernameToken(USER, PASSWORD, 18 Microsoft.ConnectedServices.Sdk.Security.Tokens.PasswordOption.SendPlainText)); 19 20 // Envío del mensaje 21 MessageSender sender = new MessageSender(); 22 sender.SendAsync(message); 23 }

Una vez finalizado el envío, sólo queda terminar la sessión si es que realmente queremos hacerlo. Para nuestros pequeños ejemplos, puede ser interesante eliminarla una vez que deje de ser usada, para así, no dejar basura excesivas sesiones creadas.

Nota: Un envío sincrono no puede ser utilizado para invocar a un Web Service estandar creado con Visual Studio. Para que esto sea posible sera necesario que este cumpla el estandar WSE. (Ya comentaré como hacerlo con otro buen ejemplo).

Pues como solemos decir; “Donde se ponga un trozo de código que se quiten todas las explicaciones del mundo“.

Espero que ahora con la practica de CSF se vea todo este “mundillo” un poquito más claro.

En sucesivos posts trataré de explicar como depurar y chequear posibles errores, temas de caché y configuración básica.

Saludos
Juanlu