+ All Categories
Home > Documents > MSMQ and WCF Integration - Walkthrough

MSMQ and WCF Integration - Walkthrough

Date post: 24-Oct-2014
Category:
Upload: samozasega
View: 345 times
Download: 10 times
Share this document with a friend
Description:
SOA-izing MSMQ with WCF (and Why it’s Worth it)
Popular Tags:
27
SOA-izing MSMQ with WCF (and Why it’s Worth it) Microsoft Message Queuing (MSMQ) is an incredibly robust, time-tested messaging server that fulfills a critical role in any communications platform. What it doesn’t do however, is play well in a service oriented world. MSMQ applications and their developers must be fully aware of the queue’s they’re communicating with and hand-craft messages to be sent on the wire. In a Service Oriented Architecture (SOA) world, we don’t think in terms of message in queues, we think in terms of business operations allowing developers to focus on what’s most important…business operations. Centering application development around these operations enables us to be flexible with not only with our implementations, but also our communication partners. In addition, the extensibility mechanisms provided when we integrate MSMQ with Windows Communication Foundation (WCF) are extremely powerful and enable MSMQ developers to do things they never could before. During the following walk-thru you’ll: 1. Get the feel for an existing System.Messaging (MSMQ) demo application 2. Implement the equivalent application using WCF Queuing (MSMQ + WCF) 3. Integrate the beta version of the MSMQ Chunking Channel Sample into your application enabling you to send messages > 4mb in size over MSMQ 4. Use the MSMQ Integration binding to send messages from the original System.Messaging sender to a new WCF receiver for processing Getting Started Launching the demo app 1. Since were going to be launch a WCF service that utilizes HTTP port 80, we need to make sure the user were launching the service as has access to that port. There are two ways to achieve that: a. Explicitly grant permission to this user via a URL ACL. i. From a command line with administrative permission run: 1. netsh http add urlacl url=http://+:80/ user=DOMAIN\user ii. Example:
Transcript
Page 1: MSMQ and WCF Integration - Walkthrough

SOA-izing MSMQ with WCF (and Why it’s Worth it)

Microsoft Message Queuing (MSMQ) is an incredibly robust, time-tested messaging server that fulfills a critical role in any communications

platform. What it doesn’t do however, is play well in a service oriented world. MSMQ applications and their developers must be fully aware of

the queue’s they’re communicating with and hand-craft messages to be sent on the wire. In a Service Oriented Architecture (SOA) world, we

don’t think in terms of message in queues, we think in terms of business operations allowing developers to focus on what’s most

important…business operations. Centering application development around these operations enables us to be flexible with not only with our

implementations, but also our communication partners. In addition, the extensibility mechanisms provided when we integrate MSMQ with

Windows Communication Foundation (WCF) are extremely powerful and enable MSMQ developers to do things they never could before.

During the following walk-thru you’ll:

1. Get the feel for an existing System.Messaging (MSMQ) demo application

2. Implement the equivalent application using WCF Queuing (MSMQ + WCF)

3. Integrate the beta version of the MSMQ Chunking Channel Sample into your application enabling you to send messages > 4mb in size

over MSMQ

4. Use the MSMQ Integration binding to send messages from the original System.Messaging sender to a new WCF receiver for processing

Getting Started

Launching the demo app 1. Since we’re going to be launch a WCF service that utilizes HTTP port 80, we need to make sure the user we’re launching the service as

has access to that port. There are two ways to achieve that:

a. Explicitly grant permission to this user via a URL ACL.

i. From a command line with administrative permission run:

1. netsh http add urlacl url=http://+:80/ user=DOMAIN\user

ii. Example:

Page 2: MSMQ and WCF Integration - Walkthrough

1. netsh http add urlacl url=http://+:80/ user=.\justinw

b. Run Visual Studio with administrative credentials.

2. Open the Visual Studio project that you downloaded for this walk-thru and build it.

3. Hit F5 to run the server side of the application.

4. Find the client side executable of the application in its output directory and run it:

a. "c:\Users\justinwi\Documents\Visual Studio 2005\Projects\MSMQ-WCF-Walk-Thru\Client\bin\Debug\

MSMQChunkingChannelDemo⌂-Client.exe"

Use the app 1. What does it do?

a. Click the “Start Watching” button on the Server to start it watching for orders from the client.

b. Drag any image onto the “Drop Picture Here” text in the Client.

Page 3: MSMQ and WCF Integration - Walkthrough

c. Click the “Send with WCF over HTTP” button to submit the order to the server, note the image shows up on the server side

application and the “Received with WCF over HTTP” button is selected (faint blue outline).

Page 4: MSMQ and WCF Integration - Walkthrough
Page 5: MSMQ and WCF Integration - Walkthrough

d. Drag another image onto the client and click the “Send with MSMQ” button. Note the image shows up on the server and the

“Received with MSMQ” button is selected.

2. Send with no WCF end-point

a. Stop the order watchers on the Server by clicking the “Stop Watching” button.

b. Drag another picture on the Client.

c. Click the “Send with WCF over HTTP” button and wait approx. 5 seconds and you’ll get an error saying that the remote endpoint

is not available. That’s one of the tricky points about non-durable web services – if the service isn’t available to process a

request, it is immediately rejected.

3. Send with MSMQ

a. MSMQ’s asynchronous and durable message patterns solve this problem.

b. With the Server’s watchers stop, send the same image above by clicking the “Send with MSMQ” button on the Client. Note the

lack of an error.

c. Now start the watchers on the Server and see that the image has been successfully transmitted.

4. Send large messages

a. MSMQ works great in the disconnected scenario, but it has its own set of limitations. Try sending an image from the “Big

Images” directory in the “Sample Images” folder that’s greater than 4mb in size using the “Send with MSMQ” button on the

client.

b. You’ll see an “Insufficient Resources” error occur because MSMQ cannot send payloads great than 4mb in size.

c. Attempting to send the same image via the WCF over HTTP button, while the watchers are started of course, will work despite

the large message size.

5. The best of both worlds

a. During this lab we’ll combine the strengths of MSMQ and WCF to enable disconnected communication and overcome MSMQ’s

max message size limitation.

b. We’ll also see how easy it is to use WCF endpoints to talk to existing MSMQ applications to enable a gradual introduction of WCF

into your applications.

6. Note: nothing happens when you click the MSMQ + WCF button on the Client

a. That’s what you’ll be implementing!

Page 6: MSMQ and WCF Integration - Walkthrough

Look at the design Before we start coding, let’s look at the design really quickly so you know what’s going on. There are three major types you care about:

OrderInfo, IOrderSubmitter, and OrderWatcher. The OrderInfo object contains the image sent from the client to the server, IOrderSubmitters

send the orders from the client and OrderWatchers receive the orders on the sever side. Details:

1. OrderInfo object (using the Visual Studio link on the desktop, find this file using the solution explorer - CommonResources\OrderInfo.cs)

Page 7: MSMQ and WCF Integration - Walkthrough

a. OrderInfo is a simple, user defined, compound object consisting of an image and a string

Page 8: MSMQ and WCF Integration - Walkthrough

i. Marked as serializable and denotes datamebers so System.Messagaing and WCF can serialize the object respectively

ii. Also has a helper property which converts the image to/from a byte[]

b. OrderInfo is Submitted by IOrderSubmitters (on the client-side) and processed by OrderWatchers (on the server-side)

2. Client side

a. IOrderSubmitter (Client\IOrderSubmitter.cs)

i. Generic interface for objects that submit orders

ii. Two implementations of this interface so far – the WCFHTTPSubmitter (associated with the “Send with WCF over HTTP”

button) & MSMQ (associated with the “Send with MSMQ” button)

iii. You’ll write a third one that does WCF over MSMQ

b. Each order submitter is associated with a button. When a button is clicked, the corresponding order submitter is created and

used to send the an order

c. The IOrderSubmitter interface makes it easy to add/enable new buttons on the client

3. Server side

a. OrderWatcher (Server\OrderWatcher.cs)

i. Base class with three methods

1. OnOrderFound –

a. raises the OrderFound event to signify the order watcher has found an order

2. WatchForOrders –

a. used to tell an order watcher to start watching

b. takes a string denoting which machine they should watch on

c. invoked when you click “start watching”

d. Must be implemented by derived classes

3. StopWatchingForOrders

a. used to stop watchers

b. invoked when you click “stop watching” button

c. Must be implemented by derived classes

ii. Two implementations so far

1. WCF over HTTP

2. MSMQ using System.Messaging

3. You’ll write the third – WCF over MSMQ

Page 9: MSMQ and WCF Integration - Walkthrough

b. The OrderWatcher class makes it easy to define new OrderWatchers in the service application that can all be started/stopped at

the same time.

Look at the code Now let’s dive into the existing code.

1. MSMQ Submitter (Client\MSMQSubmitter.cs)

a. Invoked when the “Send with MSMQ” button is clicked on the client

b. Creates a message and sends to a queue on the machine mentioned in the textbox

2. MSMQ Watcher (Server\MSMQOrderWatcher.cs)

a. Started when the “Start watchers” button is clicked (WatchForOrders)

i. Creates a message pump that looks for messages and checks a state variable to determine whether or not it should keep

polling

b. When a message is found, raises the OrderFound event

3. WCF Watcher

a. Contract definition (CommonResources\ServiceContracts.cs)

i. Contracts are used by WCF to define the operations offered by a web service. A “calculator service” for example might

define several operations like Add, Subtract, Multiple, etc.

ii. For our services, we’ve got just one operation which clients will invoke - “SubmitOrder”.

1. Takes a OrderInfo, returns nothing

iii. The ServiceContract attribute denotes this is a contract that defines operations

iv. The OperationContract denotes this is an operation that clients can invoke on any service that implements it

b. Contract implementation (Server\WCFHTTPOrderWatcher.cs)

i. Here we define a service that implements our order contract. We also derive it from the OrderWatcher class so it can

process orders and provide them to the server UI when it gets them

ii. OrderWatcher methods

1. WatchForOrders

a. Defines a service binding

i. Describes the “channel stack” to use for communication as well as customizes it appropriately.

Page 10: MSMQ and WCF Integration - Walkthrough

ii. Increases the max message size the service can receive since we’re sending large amounts of

data.

b. Creates a ServiceHost object – responsible for starting, stopping the service

c. Defines an endpoint address that clients will communicate with it

d. Starts the service

2. StopWatching

a. Stops the service

iii. IWCFHTTPOrderWatcher method

1. SubmitOrder

a. Invoked when a client invokes the service’s SubmitOrder method

b. Simply raises the OrderFound event

4. WCFHTTPOrderSubmitter (Client\WCFHTTPSubmitter.cs)

a. Constructor

i. Define the endpoint we can communicate with the server on (where we send data)

ii. Define our binding that describes our communication mechanisms (how we send data)

iii. Create a channelFactory – an object that will create communication channels for us

iv. Create a communication channel

b. SubmitOrder

i. Use our communication channel to submit an order

Takeaways 1. You now understand the architecture of the demo application

2. You can see some similarities between MSMQ and WCF

a. Both have clients and servers (i.e. senders and receivers)

b. Can both communicate using user-defined types

c. Are both very easy to use to send information with (submitter implementations are very simple)

3. MSMQ and WCF differences

a. In MSMQ you think about queues and send messages

i. WCF you define operations and invoke them

Page 11: MSMQ and WCF Integration - Walkthrough

ii. Enables you to design your applications in terms of business operations and doesn’t tie you to a certain technology or

implementation of your operation

b. MSMQ’s communication is asynchronous and durable

i. WCF client must be in contact with service endpoint in order to communicate

ii. We’ll address this difference very shortly by combining WCF and MSMQ

c. MSMQ requires you to implement a “message pump” polling for messages and doing the right thing when they come in

i. WCF implements the “message pump” logic for you. All you have to do is do the right thing once a message comes in

4. Enough talk…let’s write some code!

Implementing a Durable, Service-Oriented, Order Processor

Now let’s combine the power of MSMQ with the flexibility of WCF to make a durable, asynchronous, service-oriented version of our order

processing application.

Create a new service contract

1. Copy the following code into CommonResources\ServiceContracts.cs below the definition for IWCFHTTPOrderContract but within the

namespace scope

[ServiceContract]

public interface IQueuingOrderContract

{

// Queued operations must be marked as one-way since

// two-way communication doesn't make sense for disconnected

// applications

[OperationContract(IsOneWay = true)]

void SubmitOrder(OrderInfo order);

Page 12: MSMQ and WCF Integration - Walkthrough

}

a. Note the only difference between this contract and the IWCFHTTPOrderContract is that this one has the IsOneWay property set

to true indicating communication will be from the client to the server, but not vice-versa. This is typical for disconnected or

asynchronous communication where the client and server may not be available at the same time.

2. Define a class that implements your new contract

a. Open the file Server\WCFQueuingOrderWatcher.cs and paste the following

[ServiceBehavior]

public class WCFQueuingOrderWatcher : OrderWatcher, IQueuingOrderContract

{

private ServiceHost serviceHost = null;

public override void WatchForOrders(string server)

{

Uri serviceUri = new Uri("net.msmq://" + CommonHelpers.NormalizeServerNameForURI(server) +

DemoConstants.QUEUING_ENDPOINT_SUFFIX);

NetMsmqBinding serviceBinding = new NetMsmqBinding();

serviceBinding.Security.Transport.MsmqAuthenticationMode = MsmqAuthenticationMode.None;

serviceBinding.Security.Transport.MsmqProtectionLevel = System.Net.Security.ProtectionLevel.None;

serviceBinding.MaxReceivedMessageSize = DemoConstants.MAX_MESSAGE_SIZE;

serviceBinding.ReaderQuotas.MaxArrayLength = DemoConstants.MAX_ARRAY_SIZE;

serviceHost = new ServiceHost(typeof(WCFQueuingOrderWatcher));

serviceHost.AddServiceEndpoint(typeof(IQueuingOrderContract), serviceBinding, serviceUri);

serviceHost.Open();

}

public override void StopWatchingForOrders()

{

if (serviceHost != null)

{

serviceHost.Close();

}

}

Page 13: MSMQ and WCF Integration - Walkthrough

[OperationBehavior(TransactionScopeRequired = true)]

public void SubmitOrder(OrderInfo order)

{

OnOrderFound(order);

}

}

3. Points of interest

a. The ServiceBehavior attribute denotes this class defines the behavior of a service operation

b. WCFQueuingOrderWatcher derives from OrderWatcher (like the WCFHTTPOrderWatcher did) and from our newly created

IQueuingOrderContract

c. The only other difference between this OrderWatcher and the WCFHTTPOrderWatcher is the definition of the binding and the

endpoint used for communication.

i. In this case, we use the Net.MSMQ binding and Uri format. We also turn off security since MSMQ is running in

workgroup mode.

ii. This is where all the MSMQ magic happens, from here on out this service will rely on MSMQ for all of its communication

mechanisms enabling a durable, asynchronous, service-oriented, application

Define a client that will invoke your service’s operation 1. Open Client\WCFQueuingSubmitter.cs and paste the following code within the namespace scope

class WCFQueuingSubmitter : IOrderSubmitter

{

IQueuingOrderContract channel = null;

public WCFQueuingSubmitter(string server)

{

EndpointAddress endpointAddress = new EndpointAddress(new Uri("net.msmq://" +

CommonHelpers.NormalizeServerNameForURI(server) + DemoConstants.QUEUING_ENDPOINT_SUFFIX));

NetMsmqBinding clientBinding = new NetMsmqBinding();

clientBinding.Security.Transport.MsmqAuthenticationMode = MsmqAuthenticationMode.None;

clientBinding.Security.Transport.MsmqProtectionLevel = System.Net.Security.ProtectionLevel.None;

Page 14: MSMQ and WCF Integration - Walkthrough

ChannelFactory<IQueuingOrderContract> channelFactory = new

ChannelFactory<IQueuingOrderContract>(clientBinding, endpointAddress);

channel = channelFactory.CreateChannel();

}

#region IOrderSubmitter Members

public void SubmitOrder(OrderInfo order)

{

if (channel != null)

{

channel.SubmitOrder(order);

}

}

#endregion

}

2. Note this client is almost identical to our WCFHTTPSubmitter, the only differences again are the binding and the endpoint Uri and that

the channel we use is of type IQueuingOrderContract.

Enable your new code 1. Client-side

a. Add the following code within the definition of the MCCButton_Click method in Client\ClientWindow.xaml\Window1.xaml.cs

SubmitOrder(new WCFQueuingSubmitter(ServerTextBox.Text));

b. This code will create a new WCFQueuingSubmitter and will use it to submit and order to any machine indicated in the server

name text box whenever the bottommost button is clicked

2. Server-side

a. Find the definition of the InitializeOrderWatchers method within Server\ServerWindow.xaml\Window1.xaml.cs

b. Add the following code to add your WCFQueuingWatcher to the server’s list of OrderWatchers and to associate it with the

bottommost button in the server UI

Page 15: MSMQ and WCF Integration - Walkthrough

watchers.Add(new WCFQueuingOrderWatcher());

watcherTypeButtons.Add(typeof(WCFQueuingOrderWatcher), MCCButton);

c. Now an instance of your WCFQueuingOrderWatcher will be instructed to start and stop as appropriate when the “Start/Stop

Watching” button is clicked in the server UI.

d. You’ll also see that when you send an order using your WCFQueuingSubmitter, the bottommost button on the server will be

highlighted once the order has been received.

Try it out! 1. Take your new durable, service oriented, order processor for a test drive by building it and using the desktop shortcuts to launch the

applications.

a. Be sure to stop all instances of the Server and Client application that are running before building otherwise you’ll get build

failures.

2. Some things to try using your newly functioning “Send with MSMQ + WCF” button:

a. Try submitting orders (drag and image onto the client and click the “Send with MSMQ + WCF” button) when the server isn’t

watching, then start watching

i. Note that scenario won’t work if you try it with the “Send with WCF over HTTP” button

b. Stop the watchers again and submitting lots of orders (hit the button several times) and then look inside MSMQ’s

“WCFQueuingOrders” queue

i. Start->Right click Computer->Manage

ii. Computer Management->Services and Applications->Message Queuing->Private Queues->WCFQueuingOrders-

>Queue messages

Page 16: MSMQ and WCF Integration - Walkthrough

iii. You should see a message for each of the orders you submitted in the queue

iv. Start the server watching for orders and refresh your view on the MSMQ queue (F5) to see the messages disappear

c. Try to send to send an order with an image > 4mb in it (from the “Big Images” directory) using the MSMQ + WCF button

Page 17: MSMQ and WCF Integration - Walkthrough

i. You’ll get an error, similar to the one you get if you use the MSMQ only button

ii. In the next section you’ll see how to overcome MSMQ’s 4mb message size limitation through WCF!

Takeaways 1. Using MSMQ via WCF is as easy as using any other WCF transport mechanism and enables SOA-centric MSMQ solutions

2. WCF benefits greatly from MSMQ integration, adding durability where previously there was none

Overcoming MSMQ’s 4mb Message Size Limitation

As you saw in the last section, MSMQ makes WCF more durable, but WCF makes MSMQ more flexible. Flexible enough to overcome MSMQ’s

long-standing 4mb maximum message size limitation. In this section you’ll see how to use a custom channel sample to augment the capabilities

of MSMQ using WCF’s built-in extensibility model.

What is chunking? 1. When you really need to send large messages over MSMQ, the best way to do so is to break the messages into multiple “chunks”,

each of which is less than 4mb, on the client side and reassemble the chunks on the server side

2. The following exercise demonstrates how to use the Beta version of our new MSMQ Chunking Channel sample. In the near future

we hope to release a sample WCF chunking channel you can use as a reference for your large message scenarios. Sign-up for alerts

on our blog to get notified when the source code is available http://blogs.msdn.com/motleyqueue.

3. The sample chunking channel handles all of the hard work of breaking the messages apart and reassembling for you. All you need to

do is invoke your service operations just like you normally would with WCF.

Define your chunking-enabled service contract 4. Copy the following code into CommonResources\ServiceContracts.cs below the definition for IQueuingOrderContract

Page 18: MSMQ and WCF Integration - Walkthrough

[ServiceContract]

public interface IChunkingOrderContract

{

// Queued operations must be marked as one-way since

// two-way communication doesn't make sense for disconnected applications.

// Operations must also be marked with the ChunkingBehavior attribute to denote

// chunking should be performed. Also chunking operations must utilize streams

[OperationContract(IsOneWay = true)]

[ChunkingBehavior(ChunkingAppliesTo.Both)]

void SubmitOrder(Stream order);

}

5. Note there is a new ChunkingBehavior attribute on the operation and the SubmitOrder method now takes a stream instead of an

OrderInfo object.

6. The new chunking behavior attribute signifies that this operation supports chunking

7. We need to use the stream type because the chunking channel supports streaming, in other words, the ability to receive and process

some of the information before all of it is available. For example if you sent a 50 page document using the MSMQ Chunking Channel

sample, you could begin processing the first page even before the last page had arrived.

Define an OrderWatcher that implements the service contract 8. Paste the following code within the namespace scope of Server\MSMQChunkingChannelOrderWatcher.cs

[ServiceBehavior]

public class MSMQChunkingChannelOrderWatcher : OrderWatcher, IChunkingOrderContract

{

private ServiceHost serviceHost = null;

public override void WatchForOrders(string server)

{

Uri serviceUri = new Uri("net.msmq://" + CommonHelpers.NormalizeServerNameForURI(server) +

DemoConstants.QUEUING_ENDPOINT_SUFFIX);

MSMQChunkingBinding serviceBinding = new MSMQChunkingBinding();

serviceHost = new ServiceHost(typeof(MSMQChunkingChannelOrderWatcher));

serviceHost.AddServiceEndpoint(typeof(IChunkingOrderContract), serviceBinding, serviceUri);

Page 19: MSMQ and WCF Integration - Walkthrough

serviceHost.Open();

}

public override void StopWatchingForOrders()

{

if (serviceHost != null)

{

serviceHost.Close();

}

}

[OperationBehavior(TransactionScopeRequired = true)]

public void SubmitOrder(Stream orderStream)

{

OrderInfo orderInfo = new OrderInfo("test", BuildBitmap(orderStream));

OnOrderFound(orderInfo);

}

private Bitmap BuildBitmap(Stream stream)

{

MemoryStream ms = new MemoryStream();

byte[] buffer = new byte[4096];

// The stream given to our service operation is buffered, so we need

// to read everything from it before we can build our bitmap

int count = 0;

while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)

{

ms.Write(buffer, 0, count);

}

return new Bitmap(ms);

}

}

9. Points of interest

Page 20: MSMQ and WCF Integration - Walkthrough

a. The primary difference between this OrderWatcher and the WCFQueuingOrderWatcher is the use of the

MSMQChunkingBinding, as opposed to the NetMSMQBinding.

b. You’ll also notice there’s a new OperationBehavior attribute on the SubmitOrder method. This ensure SubmitOrder is

always executed under a transaction guaranteeing even if there’s a service failure once your OrderWatcher starts utilizing

the stream handed in, all of the chunks in your stream will be put back into MSMQ’s queue to be received the next time

your service starts up. This enables end-to-end durability of arbitrarily large messages, a first for MSMQ and WCF.

c. The BuildBitmap method is a simple helper method which builds a bitmap from the stream given to SubmitOrder.

Define a service that will implement your new OrderWatcher 10. Paste the following code inside the namespace scope of Client\MSMQChunkingChannelSubmitter.cs

class MSMQChunkingChannelSubmitter : IOrderSubmitter

{

IChunkingOrderContract channel = null;

public MSMQChunkingChannelSubmitter(string server)

{

EndpointAddress endpointAddress = new EndpointAddress(new Uri("net.msmq://" +

CommonHelpers.NormalizeServerNameForURI(server) + DemoConstants.QUEUING_ENDPOINT_SUFFIX));

MSMQChunkingBinding clientBinding = new MSMQChunkingBinding();

ChannelFactory<IChunkingOrderContract> channelFactory = new

ChannelFactory<IChunkingOrderContract>(clientBinding, endpointAddress);

channel = channelFactory.CreateChannel();

}

#region IOrderSubmitter Members

public void SubmitOrder(OrderInfo order)

{

if (channel != null)

{

MemoryStream ms = new MemoryStream();

order.Picture.Save(ms, order.Picture.RawFormat);

Page 21: MSMQ and WCF Integration - Walkthrough

ms.Position = 0;

channel.SubmitOrder(ms);

}

}

#endregion

}

11. Points of interest

a. Note how similar the definition for this client is to the other WCF IOrderSubmitter implementers, only the binding is

different

b. SubmitOrder is slightly different in that it converts the order’s image into a stream before invoking SubmitOrder

Enable your new code 12. Client-side

a. Replace the definition of the MCCButton_Click method in Client\ClientWindows.xaml\Window1.xaml.cs with

SubmitOrder(new MSMQChunkingChannelSubmitter(ServerTextBox.Text));

b. This code will create a new MSMQChunkingChannelSubmitter and will use it to submit an order to any machine indicated in

the server name text box when the MSMQ + WCF button is clicked

13. Server-side

a. Find the definition of the InitializeOrderWatchers method within Server\ServerWindow.xaml\Window1.xaml.cs

b. Replace the instances of WCFQueuingOrderWatcher with MSMQChunkingChannelOrderWatcher so the method looks like

private void InitializeOrderWatchers()

{

// Add each of our types of order watchers

watchers.Add(new MSMQOrderWatcher());

watcherTypeButtons.Add(typeof(MSMQOrderWatcher), MQButton);

watchers.Add(new WCFHTTPOrderWatcher());

watcherTypeButtons.Add(typeof(WCFHTTPOrderWatcher), WCFButton);

Page 22: MSMQ and WCF Integration - Walkthrough

watchers.Add(new MSMQChunkingChannelOrderWatcher());

watcherTypeButtons.Add(typeof(MSMQChunkingChannelOrderWatcher), MCCButton);

// Set the shared static event handler for the order watchers

OrderWatcher.OrderFound += new EventHandler(OrderFound);

}

1. Now an instance of your MSMQChunkingChannelOrderWatcher will be instructed to start and stop as appropriate

when the “Start/Stop Watching” button is clicked in the server UI.

2. You’ll also see that when you send an order using your MSMQChunkingChannelSubmitter, the bottommost button

on the server will be highlighted once the order has been received

Try it out! 14. You can now send durable orders from your client to your server that are larger than 4mb!

15. With your watchers stopped, send a large messages and then take a look at MSMQ’s WCFQueuingOrders queue

a. Start->Right click Computer->Manage

b. Computer Management->Services and Applications->Message Queuing->Private Queues->WCFQueuingOrders->Queue

messages

c. You’ll see far more messages than the one you submitted an order for. That’s because the chunking channel broke up the

large messages into smaller ones

16. Now start the order watchers on the Server

a. You’ll see the large messages delivered

b. In MSMQ’s MMC select the WCFQueuingOrders queue and hit F5 to refresh and you’ll see a subqueue under the

WCFQueuingOrders queue. That’s because the MSMQChunkingChannel sorts each of the message chunks from large

messages into their respective subqueues to enable multiple senders and guarantee durability until all of the chunks have

arrived on the destination machine.

17. Note this Beta version of the sample has a race condition exposed by sending several large messages sequentially. This issue will be

resolved before we release the final version of the sample.

Page 23: MSMQ and WCF Integration - Walkthrough

Takeaways 18. You can now send arbitrarily large messages over MSMQ by leveraging the MSMQ Chunking Channel sample

19. WCF’s extensibility model makes it possible to add major functional improvements to your communication mechanisms without

fundamentally changing the implementation of your business operations. Note this MSMQ Chunking Channel sample’s functionality

was enabled entirely out-of-the-box with no changes required in the underlying MSMQ or WCF platforms.

Implement a WCF Service that Interoperates with a System.Messaging client

Now that you’ve seen a bit of the power WCF can offer MSMQ, let’s walk through an MSMQ/WCF interoperability scenario so you can see how

easy it is to start using WCF today.

MSMQ Interoperability 1. With no changes at all to our MSMQChunkingSubmitter, we can replace our purely System.Messaging-based MSMQOrderWatcher

with a WCF service that can receive and process MSMQ messages.

2. This exercise will demonstrate the ease with which you can start integrating WCF with your existing applications even if you’re

unable to modify your senders and receivers simultaneously

Define your MSMQ integration service contract 3. Copy the following code into CommonResources\ServiceContracts.cs below the definition for IChunkingOrderContract

[ServiceContract]

[ServiceKnownType(typeof(OrderInfo))]

public interface IIntegrationOrderContract

{

// Queued operations must be marked as one-way since

// two-way communication doesn't make sense for disconnected applications

[OperationContract(IsOneWay = true, Action = "*")]

Page 24: MSMQ and WCF Integration - Walkthrough

void SubmitOrder(MsmqMessage<OrderInfo> order);

}

4. Note SubmitOrder takes a new parameter of type MSMQMessage<OrderInfo>. This enables the WCF channel to provide the same

level of serialization and ease of use the System.Messaging does in a service-oriented way.

5. There’s also a new ServiceKnownType attribute that defines the type of object this service operation supports

6. Finally the Action = “*” parameter to the OperationContract attribute ensures whenever an implementation of an

IIntegrationOrderContract is invoked, it will always invoke the SubmitOrder operation. This is required because native MSMQ

messages don’t have the typical headers WCF messages do indicating which service operation should be invoked. Without those

headers there’s no way for WCF to determine which operation should be invoked so we need to make its choice simple and only

provide one operation per contract.

Define an OrderWatcher that implements the service contract 7. Paste the following code within the namespace scope of Server\MSMQWCFIntegrationOrderWatcher.cs

[ServiceBehavior]

public class MSMQWCFIntegrationOrderWatcher : OrderWatcher, IIntegrationOrderContract

{

private ServiceHost serviceHost = null;

public override void WatchForOrders(string server)

{

Uri serviceUri = new Uri("msmq.formatname:DIRECT=OS:" +

CommonHelpers.NormalizeServerNameForURI(server) + DemoConstants.MSMQ_ORDER_QUEUE);

MsmqIntegrationBinding serviceBinding = new MsmqIntegrationBinding();

serviceBinding.Security.Transport.MsmqAuthenticationMode = MsmqAuthenticationMode.None;

serviceBinding.Security.Transport.MsmqProtectionLevel = System.Net.Security.ProtectionLevel.None;

serviceBinding.MaxReceivedMessageSize = DemoConstants.MAX_MESSAGE_SIZE;

serviceBinding.SerializationFormat = MsmqMessageSerializationFormat.Binary;

serviceHost = new ServiceHost(typeof(MSMQWCFIntegrationOrderWatcher));

serviceHost.AddServiceEndpoint(typeof(IIntegrationOrderContract), serviceBinding, serviceUri);

Page 25: MSMQ and WCF Integration - Walkthrough

serviceHost.Open();

}

public override void StopWatchingForOrders()

{

if (serviceHost != null)

{

serviceHost.Close();

}

}

[OperationBehavior(TransactionScopeRequired = true)]

public void SubmitOrder(MsmqMessage<OrderInfo> msg)

{

OnOrderFound(msg.Body);

}

}

8. Note the use of the MsmqIntegrationBinding instead of the NetMSMQBinding. This binding enables communication between WCF

and native MSMQ or System.Messaging applications.

9. We also need to set one more property on the Integration binding that we didn’t set on the NetMSMQ binding – the

SerializationFormat. Since we are sending messages from the System.Messaging client using the Binary formatter, we need to tell

our integration binding how to deserialize them.

10. Also note how easy it is to get the OrderInfo object from the msg object in the SubmitOrder method. Since the MsmqMessage is

strongly typed, the Body property automatically returns an object of type OrderInfo.

Define a client that will invoke your new service 11. You’re in luck, you’ve already got one! The MSMQSubmitter will already be able to utilize your new service.

Enable your new code 12. Client-side

a. No changes necessary!

13. Server-side

Page 26: MSMQ and WCF Integration - Walkthrough

a. Find the definition of the InitializeOrderWatchers method within Server\ServerWindow.xaml\Window1.xaml.cs

b. Replace the instances of MSMQOrderWatcher with MSMQWCFIntegrationOrderWatcher so the method looks like:

private void InitializeOrderWatchers()

{

// Add each of our types of order watchers

watchers.Add(new MSMQWCFIntegrationOrderWatcher());

watcherTypeButtons.Add(typeof(MSMQWCFIntegrationOrderWatcher), MQButton);

watchers.Add(new WCFHTTPOrderWatcher());

watcherTypeButtons.Add(typeof(WCFHTTPOrderWatcher), WCFButton);

watchers.Add(new MSMQChunkingChannelOrderWatcher());

watcherTypeButtons.Add(typeof(MSMQChunkingChannelOrderWatcher), MCCButton);

// Set the shared static event handler for the order watchers

OrderWatcher.OrderFound += new EventHandler(OrderFound);

}

Try it out! 14. Build your solution and run the client and server from the desktop shortcuts

15. You’ll now see that orders submitted from your purely System.Messaging submitter can now be processed by a WCF service

16. Note you still get all the durability guarantees that MSMQ offers however you won’t be able to leverage the large message

functionality enabled by the MSMQ Chunking Channel Sample.

Takeaways 17. Integrating WCF with your existing MSMQ applications and enabling them to co-exist is a piece of cake

Conclusion

Page 27: MSMQ and WCF Integration - Walkthrough

During this walk-thru you did a lot of cool stuff. You combined the durability of MSMQ with the service-oriented flexibility of WCF. You utilized

WCF’s extensibility model to overcome inherent limitations in your underlying platform and you easily integrated a pure MSMQ client with a

WCF service. You now know a little more about the major benefits you get when you start leverage WCF with your MSMQ solutions.

For more information on MSMQ and/or WCF check out the following:

MSMQ Website – www.microsoft.com/msmq

WCF Queuing - http://msdn2.microsoft.com/en-us/library/ms789048.aspx

Motley Queüe (Microsoft Queuing Blog) - http://blogs.msdn.com/motleyqueue


Recommended