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.
El ejemplo Session muestra cómo enviar y recibir un conjunto de mensajes relacionados en la comunicación en cola a través del transporte de Message Queuing (MSMQ). El ejemplo usa el enlace netMsmqBinding. El servicio es una aplicación de consola autohospedada que le permite observar el servicio que recibe los mensajes en cola.
Nota:
El procedimiento de instalación y las instrucciones de compilación de este ejemplo se encuentran al final de este tema.
En la comunicación con colas, el cliente se comunica con el servicio mediante una cola. Más precisamente, el cliente envía mensajes a una cola. El servicio recibe mensajes de la cola. El servicio y el cliente no necesitan ejecutarse simultáneamente para comunicarse mediante una cola.
A veces, un cliente envía un conjunto de mensajes relacionados entre sí en un grupo. Cuando los mensajes se deben procesar juntos o en un orden especificado, se puede usar una cola para agruparlos, para su procesamiento mediante una sola aplicación receptora. Esto es especialmente importante cuando hay varias aplicaciones receptoras en un grupo de servidores y es necesario asegurarse de que la misma aplicación receptora procesa un grupo de mensajes. Las sesiones en cola son un mecanismo que se usa para enviar y recibir un conjunto relacionado de mensajes que deben procesarse a la vez. Las sesiones en cola necesitan que una transacción exhiba este patrón.
En el ejemplo, el cliente envía un número de mensajes al servicio como parte de una sesión dentro del ámbito de una sola transacción.
El contrato de servicio es IOrderTaker, que define un servicio unidireccional adecuado para su uso con colas. El SessionMode usado en el contrato que se muestra en el código de ejemplo siguiente indica que los mensajes forman parte de la sesión.
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface IOrderTaker
{
[OperationContract(IsOneWay = true)]
void OpenPurchaseOrder(string customerId);
[OperationContract(IsOneWay = true)]
void AddProductLineItem(string productId, int quantity);
[OperationContract(IsOneWay = true)]
void EndPurchaseOrder();
}
El servicio define las operaciones de servicio de tal manera que la primera operación se inscribe en una transacción, pero no completa automáticamente la transacción. Las operaciones posteriores también se inscriben en la misma transacción, pero no se completan automáticamente. La última operación de la sesión completa automáticamente la transacción. Por lo tanto, se usa la misma transacción para varias invocaciones de operación en el contrato de servicio. Si cualquiera de las operaciones produce una excepción, a continuación, la transacción se revierte y la sesión se pone de nuevo en la cola. Tras completar correctamente la última operación, se confirma la transacción. El servicio usa PerSession como InstanceContextMode para recibir todos los mensajes de una sesión en la misma instancia del servicio.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class OrderTakerService : IOrderTaker
{
PurchaseOrder po;
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = false)]
public void OpenPurchaseOrder(string customerId)
{
Console.WriteLine("Creating purchase order");
po = new PurchaseOrder(customerId);
}
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = false)]
public void AddProductLineItem(string productId, int quantity)
{
po.AddProductLineItem(productId, quantity);
Console.WriteLine("Product " + productId + " quantity " +
quantity + " added to purchase order");
}
[OperationBehavior(TransactionScopeRequired = true,
TransactionAutoComplete = true)]
public void EndPurchaseOrder()
{
Console.WriteLine("Purchase Order Completed");
Console.WriteLine();
Console.WriteLine(po.ToString());
}
}
El servicio se hospeda en sí mismo. Al utilizar el transporte de MSMQ, se debe crear la cola utilizada de antemano. 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 la crea, si es necesario. El nombre de la cola se lee del archivo de configuración utilizando la clase AppSettings.
// Host the service within this EXE console application.
public static void Main()
{
// Get MSMQ queue name from app settings in configuration.
string queueName = ConfigurationManager.AppSettings["queueName"];
// Create the transacted MSMQ queue if necessary.
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName, true);
// Create a ServiceHost for the OrderTakerService type.
using (ServiceHost serviceHost = new ServiceHost(typeof(OrderTakerService)))
{
// Open the ServiceHost to create listeners and start listening for messages.
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
// Close the ServiceHost to shutdown the service.
serviceHost.Close();
}
}
El nombre de cola de MSMQ se especifica en una sección appSettings del archivo de configuración. El punto de conexión del servicio se define en la sección system.serviceModel del archivo de configuración y especifica la vinculación netMsmqBinding.
<appSettings>
<!-- Use appSetting to configure MSMQ queue name. -->
<add key="queueName" value=".\private$\ServiceModelSamplesSession" />
</appSettings>
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.OrderTakerService"
behaviorConfiguration="CalculatorServiceBehavior">
...
<!-- Define NetMsmqEndpoint -->
<endpoint address="net.msmq://localhost/private/ServiceModelSamplesSession"
binding="netMsmqBinding"
contract="Microsoft.ServiceModel.Samples.IOrderTaker" />
...
</service>
</services>
...
</system.serviceModel>
El cliente crea un ámbito de transacción. Se envían todos los mensajes en la sesión a la cola dentro del ámbito de la transacción, provocando que se trate como una unidad atómica donde todos los mensajes son correctos o se producen errores. La transacción se confirma llamando a Complete.
//Create a transaction scope.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
// Create a client with given client endpoint configuration.
OrderTakerClient client = new OrderTakerClient("OrderTakerEndpoint");
// Open a purchase order.
client.OpenPurchaseOrder("somecustomer.com");
Console.WriteLine("Purchase Order created");
// Add product line items.
Console.WriteLine("Adding 10 quantities of blue widget");
client.AddProductLineItem("Blue Widget", 10);
Console.WriteLine("Adding 23 quantities of red widget");
client.AddProductLineItem("Red Widget", 23);
// Close the purchase order.
Console.WriteLine("Closing the purchase order");
client.EndPurchaseOrder();
//Closing the client gracefully closes the connection and cleans up resources.
client.Close();
// Complete the transaction.
scope.Complete();
}
Nota:
Solo puede usar una sola transacción para todos los mensajes de la sesión y todos los mensajes de la sesión deben enviarse antes de confirmar la transacción. Al cerrar el cliente, se cierra la sesión. Por consiguiente, el cliente tiene que estar cerrado antes de que la transacción se complete para enviar todos los mensajes de la sesión a la cola.
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. Presione Entrar en cada ventana de la consola para cerrar el servicio y el cliente. Debido a que se está usando el proceso de poner en cola, el cliente y el servicio no tienen que estar activados y ejecutándose simultáneamente. Puede ejecutar el cliente, apagarlo y, a continuación, iniciar el servicio y seguir recibiendo sus mensajes.
En el cliente.
Purchase Order created
Adding 10 quantities of blue widget
Adding 23 quantities of red widget
Closing the purchase order
Press <ENTER> to terminate client.
En el servicio.
The service is ready.
Press <ENTER> to terminate service.
Creating purchase order
Product Blue Widget quantity 10 added to purchase order
Product Red Widget quantity 23 added to purchase order
Purchase Order Completed
Purchase Order: 7c86fef0-2306-4c51-80e6-bcabcc1a6e5e
Customer: somecustomer.com
OrderDetails
Order LineItem: 10 of Blue Widget @unit price: $2985
Order LineItem: 23 of Red Widget @unit price: $156
Total cost of this order: $33438
Order status: Pending
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.
Para compilar la edición de .NET de C#, C++o Visual Basic de la solución, siga las instrucciones de Creación de ejemplos de Windows Communication Foundation.
Para ejecutar el ejemplo en una configuración de una máquina única o entre máquinas, siga las instrucciones de Ejecución de los ejemplos de Windows Communication Foundation.
De forma predeterminada, con NetMsmqBinding, la seguridad de transporte está habilitada. Hay dos propiedades relevantes para la seguridad de transporte de MSMQ, es decir, MsmqAuthenticationMode y MsmqProtectionLevel. De forma predeterminada, el modo de autenticación se establece Windows en y el nivel de protección se establece en Sign. Para que MSMQ proporcione la característica de autenticación y firma, debe formar parte de un dominio y la opción de integración de Active Directory para MSMQ debe estar instalada. Si ejecuta este ejemplo en un equipo que no cumple estos criterios, recibirá un error.
Ejecución del ejemplo en un equipo unido a un grupo de trabajo
Si el equipo no forma parte de un dominio o no tiene instalada la integración de Active Directory, desactive la seguridad de transporte estableciendo el modo de autenticación y el nivel
Nonede protección en como se muestra en la siguiente configuración de ejemplo.<system.serviceModel> <services> <service name="Microsoft.ServiceModel.Samples.OrderTakerService" behaviorConfiguration="OrderTakerServiceBehavior"> <host> <baseAddresses> <add baseAddress= "http://localhost:8000/ServiceModelSamples/service"/> </baseAddresses> </host> <!-- Define NetMsmqEndpoint --> <endpoint address= "net.msmq://localhost/private/ServiceModelSamplesSession" binding="netMsmqBinding" bindingConfiguration="Binding1" contract="Microsoft.ServiceModel.Samples.IOrderTaker" /> <!-- The mex endpoint is exposed at--> <!--http://localhost:8000/ServiceModelSamples/service/mex. --> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <bindings> <netMsmqBinding> <binding name="Binding1"> <security mode="None" /> </binding> </netMsmqBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="OrderTakerServiceBehavior"> <serviceMetadata httpGetEnabled="True"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>Asegúrese de cambiar la configuración tanto en el servidor como en el cliente antes de ejecutar el ejemplo.
Nota:
Establecer el modo de seguridad en
Noneequivale a establecer MsmqAuthenticationMode, MsmqProtectionLevelyMessagela seguridad enNone.