Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En el ejemplo MessageCorrelation se muestra cómo una aplicación Message Queuing (MSMQ) puede enviar un mensaje MSMQ a un servicio de Windows Communication Foundation (WCF) y cómo se pueden correlacionar los mensajes entre las aplicaciones remitente y receptora en un escenario de solicitud/respuesta. En este ejemplo se usa la vinculación msmqIntegrationBinding. El servicio en este caso es una aplicación de consola autohospedada para permitirle observar el servicio que recibe mensajes en cola. k
El servicio procesa el mensaje recibido del remitente y envía un mensaje de respuesta al remitente. El remitente correlaciona la respuesta que recibió a la solicitud que envió originalmente. Las MessageID propiedades y CorrelationID del mensaje se usan para correlacionar los mensajes de solicitud y respuesta.
El contrato de servicio IOrderProcessor define una operación de servicio unidireccional que sea adecuada para su uso cuando se coloque en la cola. Un mensaje MSMQ no tiene un encabezado Action, por lo que no es posible asignar mensajes MSMQ diferentes a contratos de operación automáticamente. Por lo tanto, solo puede haber un contrato de operación en este caso. Si desea definir más contratos de operación en el servicio, la aplicación debe proporcionar información sobre qué encabezado del mensaje MSMQ (por ejemplo, la etiqueta o correlationID) se puede usar para decidir qué contrato de operación se va a enviar.
El mensaje MSMQ tampoco contiene información sobre los encabezados que se asignan a los distintos parámetros del contrato de operación. Por lo tanto, solo puede haber un parámetro en el contrato de operación. El parámetro es de tipo MsmqMessage<T>, que contiene el mensaje MSMQ subyacente. El tipo "T" de la MsmqMessage<T> clase representa los datos que se serializan en el cuerpo del mensaje MSMQ. En este ejemplo, el tipo PurchaseOrder se serializa en el cuerpo del mensaje MSMQ.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[ServiceKnownType(typeof(PurchaseOrder))]
public interface IOrderProcessor
{
[OperationContract(IsOneWay = true, Action = "*")]
void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);
}
La operación de servicio procesa el pedido de compra y muestra el contenido del pedido de compra y su estado en la ventana de la consola de servicio.
OperationBehaviorAttribute configura la operación que dar de alta en una transacción con la cola y marcar la transacción como completada cuando vuelve la operación.
PurchaseOrder contiene los detalles del pedido que debe procesar el servicio.
// Service class that implements the service contract.
public class OrderProcessorService : IOrderProcessor
{
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
public void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> ordermsg)
{
PurchaseOrder po = (PurchaseOrder)ordermsg.Body;
Random statusIndexer = new Random();
po.Status = PurchaseOrder.OrderStates[statusIndexer.Next(3)];
Console.WriteLine("Processing {0} ", po);
//Send a response to the client that the order has been received
// and is pending fulfillment.
SendResponse(ordermsg);
}
private void SendResponse(MsmqMessage<PurchaseOrder> ordermsg)
{
OrderResponseClient client = new OrderResponseClient("OrderResponseEndpoint");
//Set the correlation ID such that the client can correlate the response to the order.
MsmqMessage<PurchaseOrder> orderResponseMsg = new MsmqMessage<PurchaseOrder>(ordermsg.Body);
orderResponseMsg.CorrelationId = ordermsg.Id;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
client.SendOrderResponse(orderResponseMsg);
scope.Complete();
}
client.Close();
}
}
El servicio usa un cliente OrderResponseClient personalizado para enviar el mensaje MSMQ a la cola. Dado que la aplicación que recibe y procesa el mensaje es una aplicación MSMQ y no una aplicación WCF, no hay ningún contrato de servicio implícito entre las dos aplicaciones. Por lo tanto, no podemos crear un proxy mediante la herramienta Svcutil.exe en este escenario.
El proxy personalizado es prácticamente idéntico para todas las aplicaciones WCF que usan la vinculación msmqIntegrationBinding para enviar mensajes. A diferencia de otros servidores proxy, no incluye una gama de operaciones de servicio. Solo es una operación de envío de mensajes.
[System.ServiceModel.ServiceContractAttribute(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface IOrderResponse
{
[System.ServiceModel.OperationContractAttribute(IsOneWay = true, Action = "*")]
void SendOrderResponse(MsmqMessage<PurchaseOrder> msg);
}
public partial class OrderResponseClient : System.ServiceModel.ClientBase<IOrderResponse>, IOrderResponse
{
public OrderResponseClient()
{ }
public OrderResponseClient(string configurationName)
: base(configurationName)
{ }
public OrderResponseClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress address)
: base(binding, address)
{ }
public void SendOrderResponse(MsmqMessage<PurchaseOrder> msg)
{
base.Channel.SendOrderResponse(msg);
}
}
El servicio se hospeda en sí mismo. Al utilizar el transporte de integración de MSMQ, se debe crear con antelación la cola utilizada. Esto se puede hacer manualmente o a través del código. En este ejemplo, el servicio contiene System.Messaging código para comprobar la existencia de la cola y crearlo si es necesario. El nombre de la cola se lee del archivo de configuración.
public static void Main()
{
// Get the MSMQ queue name from application settings in configuration.
string queueName =
ConfigurationManager.AppSettings["orderQueueName"];
// Create the transacted MSMQ queue if necessary.
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName, true);
// Create a ServiceHost for the OrderProcessorService type.
using (ServiceHost serviceHost = new
ServiceHost(typeof(OrderProcessorService)))
{
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.ReadLine();
// Close the ServiceHost to shutdown the service.
serviceHost.Close();
}
}
La cola MSMQ a la que se envían las solicitudes de pedido se especifica en la sección appSettings del archivo de configuración. Los puntos de conexión de cliente y servicio se definen en la sección system.serviceModel del archivo de configuración. Ambos especifican el enlace msmqIntegrationBinding.
<appSettings>
<add key="orderQueueName" value=".\private$\Orders" />
</appSettings>
<system.serviceModel>
<client>
<endpoint name="OrderResponseEndpoint"
address="msmq.formatname:DIRECT=OS:.\private$\OrderResponse"
binding="msmqIntegrationBinding"
bindingConfiguration="OrderProcessorBinding"
contract="Microsoft.ServiceModel.Samples.IOrderResponse">
</endpoint>
</client>
<services>
<service
name="Microsoft.ServiceModel.Samples.OrderProcessorService">
<endpoint address="msmq.formatname:DIRECT=OS:.\private$\Orders"
binding="msmqIntegrationBinding"
bindingConfiguration="OrderProcessorBinding"
contract="Microsoft.ServiceModel.Samples.IOrderProcessor">
</endpoint>
</service>
</services>
<bindings>
<msmqIntegrationBinding>
<binding name="OrderProcessorBinding" >
<security mode="None" />
</binding>
</msmqIntegrationBinding>
</bindings>
</system.serviceModel>
La aplicación cliente utiliza System.Messaging para enviar un mensaje duradero y transaccional a la cola. El cuerpo del mensaje contiene el pedido de compra.
static void PlaceOrder()
{
//Connect to the queue
MessageQueue orderQueue =
new MessageQueue(
ConfigurationManager.AppSettings["orderQueueName"])
// Create the purchase order.
PurchaseOrder po = new PurchaseOrder();
po.CustomerId = "somecustomer.com";
po.PONumber = Guid.NewGuid().ToString();
PurchaseOrderLineItem lineItem1 = new PurchaseOrderLineItem();
lineItem1.ProductId = "Blue Widget";
lineItem1.Quantity = 54;
lineItem1.UnitCost = 29.99F;
PurchaseOrderLineItem lineItem2 = new PurchaseOrderLineItem();
lineItem2.ProductId = "Red Widget";
lineItem2.Quantity = 890;
lineItem2.UnitCost = 45.89F;
po.orderLineItems = new PurchaseOrderLineItem[2];
po.orderLineItems[0] = lineItem1;
po.orderLineItems[1] = lineItem2;
Message msg = new Message();
msg.UseDeadLetterQueue = true;
msg.Body = po;
//Create a transaction scope.
using (TransactionScope scope = new
TransactionScope(TransactionScopeOption.Required))
{
// Submit the purchase order.
orderQueue.Send(msg, MessageQueueTransactionType.Automatic);
// Complete the transaction.
scope.Complete();
}
//Save the messageID for order response correlation.
orderMessageID = msg.Id;
Console.WriteLine("Placed the order, waiting for response...");
}
La cola MSMQ desde la que se reciben las respuestas de pedido se especifica en una sección appSettings del archivo de configuración, como se muestra en la siguiente configuración de ejemplo.
Nota:
El nombre de la cola utiliza un punto (.) para el equipo local y separadores con barra diagonal inversa en su ruta de acceso. La dirección del punto de conexión de WCF especifica un esquema msmq.formatname y usa "localhost" para el equipo local. Un nombre de formato bien formado sigue a msmq.formatname en el URI de acuerdo con las guías de MSMQ.
<appSettings>
<add key=" orderResponseQueueName" value=".\private$\Orders" />
</appSettings>
La aplicación cliente guarda el messageID del mensaje de solicitud de pedido que envía al servicio y espera una respuesta del servicio. Una vez que llega una respuesta en la cola, el cliente la correlaciona con el mensaje de pedido que envió mediante la correlationID propiedad del mensaje, que contiene el messageID del mensaje de pedido que el cliente envió al servicio originalmente.
static void DisplayOrderStatus()
{
MessageQueue orderResponseQueue = new
MessageQueue(ConfigurationManager.AppSettings
["orderResponseQueueName"]);
//Create a transaction scope.
bool responseReceived = false;
orderResponseQueue.MessageReadPropertyFilter.CorrelationId = true;
while (!responseReceived)
{
Message responseMsg;
using (TransactionScope scope2 = new
TransactionScope(TransactionScopeOption.Required))
{
//Receive the Order Response message.
responseMsg =
orderResponseQueue.Receive
(MessageQueueTransactionType.Automatic);
scope2.Complete();
}
responseMsg.Formatter = new
System.Messaging.XmlMessageFormatter(new Type[] {
typeof(PurchaseOrder) });
PurchaseOrder responsepo = (PurchaseOrder)responseMsg.Body;
//Check if the response is for the order placed.
if (orderMessageID == responseMsg.CorrelationId)
{
responseReceived = true;
Console.WriteLine("Status of current Order: OrderID-{0},Order
Status-{1}", responsepo.PONumber, responsepo.Status);
}
else
{
Console.WriteLine("Status of previous Order: OrderID-{0},Order
Status-{1}", responsepo.PONumber, responsepo.Status);
}
}
}
Al ejecutar el ejemplo, las actividades de cliente y servicio se muestran en las ventanas de servicio y consola de cliente. Puede ver que el servicio recibe mensajes del cliente y envía una respuesta al cliente. El cliente muestra la respuesta recibida del servicio. Presione Entrar en cada ventana de la consola para cerrar el servicio y el cliente.
Nota:
Este ejemplo requiere la instalación de Message Queuing (MSMQ). Consulte las instrucciones de instalación de MSMQ en la sección Vea también.
Configuración, compilación y ejecución del ejemplo
Asegúrese de que ha realizado el procedimiento de instalación única para los ejemplos de Windows Communication Foundation.
Si el servicio se ejecuta primero, comprobará que la cola está presente. Si la cola no está presente, el servicio creará uno. Puede ejecutar primero el servicio para crear la cola o puede crear uno a través del Administrador de colas de MSMQ. Siga estos pasos para crear una cola en Windows 2008.
Abra el Administrador del servidor en Visual Studio 2012.
Expanda la pestaña Características.
Haga clic con el botón derecho en Cola de mensajes privados y seleccione Nuevo, Cola privada.
Active la casilla Transaccional.
Escriba
ServiceModelSamplesTransactedcomo nombre de la nueva cola.
Para compilar el código C# o Visual Basic .NET Edition de la solución, siga las instrucciones de Building the Windows Communication Foundation Samples.
Para ejecutar el ejemplo en una configuración de un solo equipo, siga las instrucciones de Ejecución de los ejemplos de Windows Communication Foundation.
Ejecución del ejemplo entre equipos
Copie los archivos del programa de servicio desde la carpeta \service\bin\, que está dentro de la carpeta específica del idioma, al equipo de servicio.
Copie los archivos de programa cliente de la carpeta \client\bin\, en la carpeta específica del idioma, en el equipo cliente.
En el archivo Client.exe.config, cambie orderQueueName para especificar el nombre del equipo de servicio en lugar de ".".
En el archivo Service.exe.config, cambie la dirección del punto de conexión de cliente para especificar el nombre del equipo cliente en lugar de ".".
En el equipo de servicio, inicie Service.exe desde una ventana de comandos.
En el equipo cliente, inicie Client.exe desde un símbolo del sistema.