Created
September 20, 2012 17:54
-
-
Save mfcollins3/3757366 to your computer and use it in GitHub Desktop.
This Gist demonstrates how to use WCF with MSMQ to handle dead letters or poison messages.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Client | |
{ | |
using System; | |
using System.ServiceModel; | |
using Contracts; | |
internal class ClientProgram | |
{ | |
public static void Main(string[] args) | |
{ | |
ChannelFactory<ISayHelloService> channelFactory = null; | |
ISayHelloService service = null; | |
ServiceHost deadLetterServiceHost = null; | |
try | |
{ | |
#if false | |
// Just for reference purposes, you can use this code if you | |
// want messages to go to the system's dead letter queue. | |
var netMsmqBinding = new NetMsmqBinding(NetMsmqSecurityMode.None) | |
{ DeadLetterQueue = DeadLetterQueue.System, TimeToLive = TimeSpan.FromSeconds(20.0) }; | |
#else | |
var netMsmqBinding = new NetMsmqBinding(NetMsmqSecurityMode.None) | |
{ | |
DeadLetterQueue = DeadLetterQueue.Custom, | |
CustomDeadLetterQueue = new Uri("net.msmq://localhost/private/wcftestdeadletter"), | |
TimeToLive = TimeSpan.FromMinutes(2.0) | |
}; | |
#endif | |
var remoteAddress = new EndpointAddress("net.msmq://localhost/private/wcftest"); | |
channelFactory = new ChannelFactory<ISayHelloService>(netMsmqBinding, remoteAddress); | |
channelFactory.Open(); | |
var baseAddress = new Uri("net.msmq://localhost/private"); | |
deadLetterServiceHost = new ServiceHost(typeof(SayHelloDeadLetterService), baseAddress); | |
netMsmqBinding = new NetMsmqBinding(NetMsmqSecurityMode.None); | |
deadLetterServiceHost.AddServiceEndpoint(typeof(ISayHelloService), netMsmqBinding, "/wcftestdeadletter"); | |
deadLetterServiceHost.Open(); | |
service = channelFactory.CreateChannel(); | |
var clientChannel = service as IClientChannel; | |
if (CommunicationState.Opened != clientChannel.State) | |
{ | |
clientChannel.Open(); | |
} | |
Console.Error.WriteLine("Enter a name to send. Enter a blank line to exit."); | |
while (true) | |
{ | |
var name = Console.ReadLine(); | |
if (string.IsNullOrWhiteSpace(name)) | |
{ | |
break; | |
} | |
service.SayHello(name); | |
} | |
} | |
finally | |
{ | |
var clientChannel = service as IClientChannel; | |
if (null != clientChannel && CommunicationState.Opened == clientChannel.State) | |
{ | |
clientChannel.Close(); | |
clientChannel.Dispose(); | |
} | |
if (null != channelFactory && CommunicationState.Opened == channelFactory.State) | |
{ | |
channelFactory.Close(); | |
} | |
if (null != deadLetterServiceHost && CommunicationState.Opened == deadLetterServiceHost.State) | |
{ | |
deadLetterServiceHost.Close(); | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Contracts | |
{ | |
using System.ServiceModel; | |
[ServiceContract] | |
public interface ISayHelloService | |
{ | |
[OperationContract(IsOneWay = true)] | |
void SayHello(string to); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Client | |
{ | |
using System; | |
using System.ServiceModel; | |
using Contracts; | |
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)] | |
internal class SayHelloDeadLetterService : ISayHelloService | |
{ | |
public void SayHello(string to) | |
{ | |
Console.Error.WriteLine("DEAD LETTER: {0}", to); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Service | |
{ | |
using System; | |
using System.ServiceModel; | |
using Contracts; | |
[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)] | |
internal class SayHelloPoisonMessageService : ISayHelloService | |
{ | |
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] | |
public void SayHello(string to) | |
{ | |
Console.Error.WriteLine("POISON MESSAGE: {0}", to); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Service | |
{ | |
using System; | |
using System.ServiceModel; | |
using Contracts; | |
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] | |
internal class SayHelloService : ISayHelloService | |
{ | |
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] | |
public void SayHello(string to) | |
{ | |
if (to.Equals("john", StringComparison.OrdinalIgnoreCase)) | |
{ | |
Console.Error.WriteLine("ERROR: John is not welcome."); | |
throw new Exception("John is not welcome."); | |
} | |
Console.Out.WriteLine("Hello, {0}!", to); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Service | |
{ | |
using System; | |
using System.ServiceModel; | |
using Contracts; | |
internal class ServiceProgram | |
{ | |
public static void Main(string[] args) | |
{ | |
ServiceHost serviceHost = null; | |
ServiceHost poisonMessageHost = null; | |
try | |
{ | |
var baseAddress = new Uri("net.msmq://localhost/private"); | |
serviceHost = new ServiceHost(typeof(SayHelloService), baseAddress); | |
var netMsmqBinding = new NetMsmqBinding(NetMsmqSecurityMode.None) | |
{ | |
ReceiveRetryCount = 1, | |
ReceiveErrorHandling = ReceiveErrorHandling.Move, | |
MaxRetryCycles = 1, | |
RetryCycleDelay = TimeSpan.FromSeconds(10.0) | |
}; | |
serviceHost.AddServiceEndpoint(typeof(ISayHelloService), netMsmqBinding, "/wcftest"); | |
serviceHost.Open(); | |
poisonMessageHost = new ServiceHost(typeof(SayHelloPoisonMessageService)); | |
netMsmqBinding = new NetMsmqBinding(NetMsmqSecurityMode.None); | |
poisonMessageHost.AddServiceEndpoint( | |
typeof(ISayHelloService), netMsmqBinding, new Uri("net.msmq://localhost/private/wcftest;poison")); | |
poisonMessageHost.Open(); | |
Console.Error.WriteLine("The service is listening for requests. Press Enter to exit."); | |
Console.In.ReadLine(); | |
} | |
catch (Exception ex) | |
{ | |
Console.Error.WriteLine("\n{0}\n\nPress Enter to exit.", ex); | |
Console.In.ReadLine(); | |
} | |
finally | |
{ | |
if (null != serviceHost && CommunicationState.Opened == serviceHost.State) | |
{ | |
serviceHost.Close(); | |
} | |
if (null != poisonMessageHost && CommunicationState.Opened == poisonMessageHost.State) | |
{ | |
poisonMessageHost.Close(); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment