wcf confirmation

WCF y confirmaciones: ¿tengo que devolver un ''OK lo tengo'' al cliente?



confirmation (4)

Hay dos maneras en que puede hacer esto: devolver un valor de su llamada wcf indicando éxito o falla, o asumir el éxito y usar una devolución de llamada para avisarle al cliente si hay un problema.

Mi preferencia sería usar una llamada de servicio unidireccional con un servicio dúplex y usar un contrato de devolución de llamada para que el servicio notifique al cliente de una falla. Hay una buena descripción de los contratos de devolución de llamada aquí y aquí .

Creo que obtendrá una arquitectura más agradable y asíncrona si sigue la segunda ruta, pero para las aplicaciones simples, devolver el éxito o el fracaso puede ser más fácil.

Si tengo cientos / miles de computadoras cliente con WCP en mi servidor, ¿debería responder con un mensaje de tipo ''200 OK'' indicando que he recibido los datos y los he almacenado en el archivo db con éxito?

¿Esto ya está incorporado en WCF?


Sea predeterminado, su servicio devolverá un mensaje de "OK" al cliente (incluso si su método de servicio especifica un tipo de devolución anulada) a menos que se genere una excepción. El cliente esperará hasta que reciba este mensaje antes de continuar con su vida.

Por lo tanto, según su pregunta, obtiene el comportamiento que desea de forma predeterminada.

Si no quiere eso, estaría de acuerdo con Whisk y marcaría su operación como One Way (una configuración en su contrato de operación).

¡Buena suerte!


Creo que la pregunta podría usar un poco más de elaboración para responder correctamente. Primario, ¿qué tipo de enlace estás usando actualmente?

Si está utilizando un enlace que admite confiabilidad, y solo quiere asegurarse, desde el lado del cliente, que el servidor efectivamente recibió el mensaje, entonces solo active la confiabilidad y estará listo. Con esto encendido, WCF, bajo el capó automáticamente, tendrá cada lado de la conversación diciendo: "¿Lo tienes?" "Lo tengo. ¿Lo tienes?" "Entiendo."


Hay tres patrones de mensajes mencionados aquí:

  1. Solicitud-respuesta sincrónica
  2. Envío asincrónico (disparar y olvidar con servicio unidireccional)
  3. Solicitud-respuesta asincrónica (llamada de servicio dúplex con servicio unidireccional)

Los tres muestran un comportamiento de mensajería diferente, y el patrón que se utilizará debe elegirse en función de sus necesidades.

Para su requisito de devolver un éxito al cliente cuando los datos se han conservado en la base de datos, las opciones 1 o 3 son apropiadas.

Opción 1

Esta es la configuración por defecto.

Esto devuelve una respuesta 200 en la misma conexión http una vez que el servicio ha completado todas sus tareas. Esto significa que las llamadas al servicio se bloquearán mientras se espera la respuesta; su cliente se bloqueará hasta que el servicio haya escrito en la base de datos y hecho todo lo que necesita.

opcion 2

Devuelve una respuesta 202 siempre que la capa de transporte y la capa de infraestructura de mensajería tengan éxito. El 202 devuelto indica que el mensaje ha sido aceptado. Desde el http rfc :

La solicitud se ha aceptado para su procesamiento, pero el procesamiento no se ha completado. (...) La respuesta 202 es intencionalmente no comprometida.

Esto significa que su cliente continuará la ejecución tan pronto como la infraestructura del servicio haya iniciado con éxito el servicio, y no recibirá información sobre si la llamada a la base de datos tuvo éxito o no.

Opción 3

De forma similar a la opción 2, la respuesta es un http 202, no un 200, pero ahora cuando llama al servicio del cliente, proporciona un objeto InstanceContext que especifica un objeto para manejar la devolución de llamada. El cliente recupera el control y un nuevo hilo espera asincrónicamente la respuesta del servicio informándole de éxito o fracaso.

A continuación hay más información sobre la implementación de estos patrones en WCF. Después de escribirlo, es bastante largo, pero hay un par de comentarios útiles, así como el código.

Como mencionó Whisk, Juval Lowy tiene un artículo que cubre mucho este detalle (¡y más!) Aquí

Opción 1

Este es el comportamiento predeterminado en WCF, por lo que no debería necesitar hacer nada: funciona con muchos enlaces diferentes, incluidos wsHttpBinding y basicHttpBinding.

Una cosa a tener en cuenta es que el comportamiento descrito con su cliente colgando esperando que ocurra la respuesta 200, incluso si tiene una Operación nula así:

[ServiceContract] interface IMyServiceContract { [OperationContract] void DoSomeThing(InputMessage Message); }

opcion 2

Para establecer una operación como unidireccional, simplemente decore de la siguiente manera:

[ServiceContract] interface IMyServiceContract { [OperationContract(IsOneWay = true)] void DoSomeThing(InputMessage Message); }

Los métodos decorados de esta manera solo deben tener un tipo de vacío de retorno. Una sorpresa es que el servicio se compilará felizmente y no obtendrá una excepción que indique que la configuración del servicio no es válida hasta que se conecte.

Opción 3

El código de interfaz para crear un servicio de devolución de llamada dúplex es:

[ServiceContract(CallbackContract = typeof(IMyContractCallback))] interface IMyContract { [OperationContract(IsOneWay=true)] void DoSomeThing(InputMessage Message); } public interface IMyContractCallback { [OperationContract(IsOneWay = true)] void ServiceResponse(string result); }

Y en el lado del cliente necesita algo así como para configurar la devolución de llamada:

public class CallbackHandler : IMyContractCallback { #region IEchoContractCallback Members public void ServiceResponse(string result) { //Do something with the response } #endregion } // And in the client when you set up the service call: InstanceContext instanceContext = new InstanceContext(new CallbackHandler()); MyContractClient client = new MyContractClient(instanceContext); InputMessage msg = new InputMessage(); client.DoSomething(msg);

En el servicio, quizás tengas algún código como:

class MyContractImplementation : IMyContract { public void DoSomeThing(MyMessage Message) { string responseMessage; try { //Write to the database responseMessage = "The database call was good!"; } catch (Exception ex) { responseMessage = ex.Message; } Callback.ServiceResponse(responseMessage); } }

Una cosa importante a tener en cuenta, que me sorprendió al principio, es tener cuidado con las excepciones. Si tu:

  • Consuma una excepción, no recibirá una advertencia del error (pero la devolución de llamada ocurrirá)

  • Lanza una excepción no controlada, el servicio finalizará y el cliente ni siquiera recibirá la devolución de llamada.

Esa es una gran desventaja de este método en comparación con la Opción 1, la Opción 1 devolverá la excepción cuando se produzca una excepción no controlada.