Showing posts with label MSMQ. Show all posts
Showing posts with label MSMQ. Show all posts

Monday, February 15, 2010

The "Fancy Proxy" - having fun with WCF - 6-DynamicDuplexProxy

A little project I was doing at home lately lead me to search for a solution to disconnected application.

In my imagination I imagined an application that knows to work both "online" and "offline"...not just that but also knows how to switch between them when needed and of course - controlled from WCF configuration or other infrastructure that will be as "transparent" as possible for the programmer who writes the application.

Sounds a little like science fiction? not quite...

Gathering information from all sort of good articles & blogs I've reach to a nice project which I've decided to share with you in a kind of tutorial structure to help who ever finds this interesting - step by step.
I know the code could & should pass a bit of polish, but hey! remember it's just an idea not production material :-)

Each step in this "tutorial" represents a step in the way for the full solution, this is only to help understand each concept seperately, feel free to jump over a few steps or go directly to the final step...

1- Simple TCP
2- Simple MSMQ
3- Simple Duplex
4- MSMQ Duplex
5- Simple Dynamic proxy
6- Dynamic & Duplex proxy

This is the final step of this tutorial.

Let's review the main modifications from previous steps and test it.

The final step shows a combination of two previously reviewed steps -
TCP-Duplex and MSMQ-Duplex.
The TCP-Duplex will work when the client is connected to the server and the MSMQ-Duplex will work when it's disconnected.
We'll start with the contract, here we can see a regular duplex contract built from two "one-way" interfaces, the 2nd interface is the callback interface of the 1st one.

[ServiceContract(CallbackContract = typeof(ISampleContractCallback))]
public interface ISampleContract
{
 [OperationContract(IsOneWay = true)]
 void GetData(Guid identifier);

 [OperationContract(IsOneWay = true)]
 void Execute(Guid identifier);
}

public interface ISampleContractCallback
{
 [OperationContract(IsOneWay = true)]
 void SendData(Guid identifier, string answer);
}


The server implementation of this contract is very simple, the only thing worth mentioning here is the 'GetCallbackChannel' call which allows us to retrieve the client's endpoint & allows the server to send back an 'answer' (see 3- Simple Duplex step for more information on this).

public void Execute(Guid identifier)
{
 Console.WriteLine("{1} recieved Execute request (id {0})", identifier, DateTime.Now);
}

public void GetData(Guid identifier)
{
 Console.WriteLine("{1} recieved GetData request (id {0})", identifier, DateTime.Now);

 ISampleContractCallback client = OperationContext.Current.GetCallbackChannel();

 //get data by identifier
 string answer = "hi! from server";

 client.SendData(identifier, answer);
}


The host didn't change much from previous steps, the only change is the call for 'AddToExistingServiceHost', this helper method adds the MSMQ-Duplex endpoint to previously configured TCP-Duplex endpoint.

private static void startListening()
{

 serviceHost = new ServiceHost(typeof(testFancyProxyServer.testFancyProxyService));

          //msmq duplex server
 DuplexMsmqServices.AddToExistingServiceHost(serviceHost,
 typeof(testFancyProxyServer.testFancyProxyService),
 typeof(ISampleContract),
 ConfigurationSettings.AppSettings["MSMQServerURI"]);


 // Open the ServiceHostBase to create listeners and start 
 // listening for messages.
 serviceHost.Open();
}


In the client we will see a proxy very similar to previous step.
The proxy here uses:

1. 'NetworkChange.NetworkAvailabilityChanged' to track the network availability.

2. DynamicTargetProxyInterceptor which wraps "Castle DynamicProxy" 'ChangeInvocationTarget' to transparently switch between the 'online' and 'offline' proxies.

/// 
/// this class intercepts each call to proxy
/// and check if it needs to switch to secondary target
/// 
public class DynamicTargetProxyInterceptor : IInterceptor
{
 private readonly T _secondaryTarget;

 public DynamicTargetProxyInterceptor(T secondaryTarget)
 {
 _secondaryTarget = secondaryTarget;
 }     

 public void Intercept(IInvocation invocation)
 {
  var primaryTarget = invocation.InvocationTarget as IProxySelectorDesicion;

  if (primaryTarget.IsOnline == false)
  {
   ChangeToSecondaryTarget(invocation);
  }
 invocation.Proceed();
 }

 private void ChangeToSecondaryTarget(IInvocation invocation)
 {
  var changeProxyTarget = invocation as IChangeProxyTarget;
  changeProxyTarget.ChangeInvocationTarget(_secondaryTarget);
 }
}


3. Nicolas Dorier's MSMQ Duplex to implement the 'offline' proxy - using the same duplex contract over MSMQ on both client & server - allowing a duplex dialog between them.

Playing a bit with previous dynamic proxy sample I've noticed that when switching from the 'offline' proxy back to previously 'used' TCP proxy I get a CommunicationException - the solution for this included registering to ICommunicationObject.Faulted event to handle this exception by recreating a new 'online' proxy:
void SampleContractProxy_Faulted(object sender, EventArgs e)
{
 ((ICommunicationObject)sender).Abort();

 if (sender is ISampleContract)
 {
  sender = CreateProxy(currentEndPoint);
 } 
}


Another modification is the 'OfflineWaitTimeOut' property which allows the proxy's consumer to wait for the MSMQ-Duplex message to arrive getting a sync-like behavior, this way the code's flow is cleaner but it has an obvious cost - the client actually waits for the answer (go figure...:-)).
Anyway, like in previous sample the proxy also contains the 'AnswerArrived' event which will trigger when the server 'answers' immediately if we set the 'OfflineWaitTimeOut' to 0 or when we reach the 'OfflineWaitTimeOut' if set (it can also be set to infinite time out - not really recommended, but the option exists..).

public string GetDataSync(Guid identifier)
{
 Console.WriteLine("enter GetDataSync {0}", DateTime.Now.ToString("hh:MM:ss"));
 GetData(identifier);

 wait4Signal();

 Console.WriteLine("leave GetDataSync {0}", DateTime.Now.ToString("hh:MM:ss"));

 return Answer;
}

public void SendData(Guid identifier, string answer)
{
 wait4Event.Set();
 Answer = answer;

 //this event can be usefull to recieve answers
 //in offline mode when time-out is defined
 if (AnswerArrived != null)
 {
  AnswerArrived(this, new AnswerArrivedArgs(identifier, answer));
 }
}

private void wait4Signal()
{
 if (wait4Event == null)
 { 
  wait4Event = new ManualResetEvent(false);
 }

 wait4Event.WaitOne(offlineWaitTimeOut);
 wait4Event.Reset();
}


Testing the solution...

Looking at the proxy's consumer code:

- We create two proxies one represents the 'online' endpoint & the other one the 'offline' endpoint.
- We send both to the 'DynamicTargetProxyFactory'.
- We call the server's methods in a loop while connecting and disconnecting from the network.
public class testFancyProxyConsumer
{
 private const string ONLINE_ENDPOINT = "Online";
 private const string OFFLINE_ENDPOINT = "Offline";

 private SampleContractProxy onlineProxy;
 private SampleContractProxy offlineProxy;
 private ISampleContractSync proxy;
 private DynamicTargetProxyFactory dp;


 public void Run()
 {
  onlineProxy = new SampleContractProxy(ONLINE_ENDPOINT, true);
  offlineProxy = new SampleContractProxy(OFFLINE_ENDPOINT, true);

  offlineProxy.OfflineWaitTimeOut = 1000;
  offlineProxy.AnswerArrived += new SampleContractProxy.AnswerArrivedHandler(offlineProxy_AnswerArrived);


  dp = new DynamicTargetProxyFactory(onlineProxy, offlineProxy);

  proxy = dp.GetCurrentTarget();

  Guid testGuid;

  for (int i = 0; i < 10; i++)
  {
   testGuid = Guid.NewGuid();

   proxy.Execute(testGuid);
 
   Console.WriteLine(string.Format("{1} excute {0}", testGuid, DateTime.Now));

   Console.WriteLine(string.Format("{3} GetDataSync {0} on '{1}' proxy result:{2}",
      testGuid, proxy.CurrentEndPoint,
      proxy.GetDataSync(testGuid), DateTime.Now));


   Console.ReadLine();
  }
 }

 private void offlineProxy_AnswerArrived(object sender, AnswerArrivedArgs args)
 {
  Console.WriteLine("answer finally arrived, identifier={0}, answer={1}", args.Identifier, args.Answer);
 }
}
The result: The proxy handles everything and switches between the two proxies, the proxy's consumer doesn't need to do anything about this nor it notices the switches and even more important - all calls reached the server - isn't it a fancy proxy ??! :-) That's it on this subject. Feel free to ask or comment... Diego PS: Source Download

Friday, February 5, 2010

The "Fancy Proxy" - having fun with WCF - 5-Simple DynamicProxy

This article is part of The "Fancy Proxy" tutorial - implementing a few advance ideas in WCF in one solution.

This is the 5th step - Simple DynamicProxy.

The plot thickens..

As mentioned before one of our main goals is to develop a proxy that can work both when the server is connected & disconnected.
We saw clues for the main idea in previous articles of this tutorial.
On "Online mode" the application will work with using regular TCP connection.
On "Offline mode" it will use MSMQ-Duplex.
But how can we identify the need for the switch between them? how can we change between them? can we make the change transparent for the proxy consumer??

The best solution I found for this is using a wonderfull design pattern called - dynamic proxy - this pattern allows us to include dynamic behavior around an object, yet neither change the object's existing code nor its interface
In a previous article of mine I've explored a use of this pattern building a
transverse application policy (AOP – Aspect Orient Programming in .NET).

This design pattern is nicely implemented in a free & open source library called "Castle DynamicProxy" written by a group called "Castle Project".
If you want to read more about the uses of this library, I recommend Krzysztof Koźmic's blog (Castle Dynamic Proxy tutorial).

Back to our little project, we'll start exploring the use of dynamic proxy relevant for the previously mentioned goal.

1st we'll look at the contract..simple as in previous samples:

[ServiceContract]
public interface ISampleContract
{
[OperationContract(IsOneWay=true)]
void Execute(Guid identifier);
}


Host stays the same, the server could not be simpler:


public class testFancyProxyService:ISampleContract
{
#region ISampleContract Members

public void Execute(Guid identifier)
{
Console.WriteLine("recieved Execute request (id {0})", identifier);
}

#endregion
}


In server's (and client's) app.config we will add two endpoints, TCP for the 'online mode' and MSMQ for the 'offline mode':


<endpoint name="Online"
address="net.tcp://localhost:8080/testFancyProxy" binding="netTcpBinding"
bindingConfiguration=""
contract="testFancyProxyContracts.ISampleContract" />
...
<endpoint name="Offline"
address="net.msmq://localhost/private/testFancyProxy"
binding="netMsmqBinding" bindingConfiguration="NoMSMQSecurity"
contract="testFancyProxyContracts.ISampleContract" />


Now lets look at real point of this article, in the client side I've written a new interface & two classes (besides the references to "Castle dynamic proxy" of course).
The interface IProxySelectorDesicion speaks for itself:

public interface IProxySelectorDesicion
{
bool IsOnline { get; }
}


The 'DynamicTargetProxyFactory' receives in it's ctor two objects, in our case the first one will represent the 'online' proxy & the second the 'offline'.


///
/// builds the transparent proxy
/// and registers the relevant interceptor
///

///
public class DynamicTargetProxyFactory
{
private readonly IProxySelectorDesicion _primaryTarget;
private readonly T _secondaryTarget;
private ProxyGenerator _generator;

public DynamicTargetProxyFactory(IProxySelectorDesicion primaryTarget,
T secondaryTarget)
{
_primaryTarget = primaryTarget;
_secondaryTarget = secondaryTarget;
_generator = new ProxyGenerator();
}
...


This class is also responssible to register the interceptor, the interceptor that will later let us "inject" our code to message chain.


...
public T GetCurrentTarget()
{
var interceptor = new DynamicTargetProxyInterceptor(_secondaryTarget);
object target = _generator.CreateInterfaceProxyWithTargetInterface(typeof(T), _primaryTarget, interceptor);
return (T)target;
}
...


The 2nd class is the acutal interceptor I've called 'DynamicTargetProxyInterceptor'. As you can see next, the interceptor checks on every intercept if primaryTarget.IsOnline (primaryTarget in our case will be the 'online mode' proxy)and if the answer is 'no' it uses 'ChangeInvocationTarget' method to switch to the secondary target (in our case the 'offline mode' proxy).
ain't that cool?! :-)


///
/// this class intercepts each call to proxy
/// and check if it needs to switch to secondary target
///

public class DynamicTargetProxyInterceptor : IInterceptor
{
private readonly T _secondaryTarget;

public DynamicTargetProxyInterceptor(T secondaryTarget)
{
_secondaryTarget = secondaryTarget;
}

public void Intercept(IInvocation invocation)
{
var primaryTarget = invocation.InvocationTarget as IProxySelectorDesicion;
if (primaryTarget.IsOnline == false)
{
ChangeToSecondaryTarget(invocation);
}
invocation.Proceed();
}

private void ChangeToSecondaryTarget(IInvocation invocation)
{
var changeProxyTarget = invocation as IChangeProxyTarget;
changeProxyTarget.ChangeInvocationTarget(_secondaryTarget);
}
}


Now lets look at the proxy, this time I've used the "Add service reference.." on Visual Studio & just expanded it using parallel partial class.
This class implements 'IProxySelectorDesicion' and registers to 'NetworkAvailabilityChanged' event to be update the network availability status.


public partial class SampleContractClient : IProxySelectorDesicion
{
private bool isOnline;

public SampleContractClient(string endpointConfigurationName, bool dummy)
: base(endpointConfigurationName)
{
bool connected = NetworkInterface.GetIsNetworkAvailable();
UpdateConnectionStatus(connected);

NetworkChange.NetworkAvailabilityChanged += OnAvaiabilityChanged;
}

#region IProxySelectorDesicion Members

public bool IsOnline
{
get { return isOnline; }
}
#endregion

private void OnAvaiabilityChanged(object sender, NetworkAvailabilityEventArgs args)
{
UpdateConnectionStatus(args.IsAvailable);
}

private void UpdateConnectionStatus(bool connected)
{
isOnline = connected;
}
}


Finally let's look at the consumer, here we can see we construct two proxies (offline/online) send them both to the 'DynamicTargetProxyFactory' and execute...
The 'DynamicTargetProxyFactory' will handle everything and change between this two proxies depending on the network availability :-)


public class testFancyProxyConsumer
{
private const string ONLINE_ENDPOINT = "Online";
private const string OFFLINE_ENDPOINT = "Offline";

private SampleContractClient onlineProxy;
private SampleContractClient offlineProxy;
private ISampleContract proxy;
private DynamicTargetProxyFactory dp;


public void Run()
{
onlineProxy = new SampleContractClient(ONLINE_ENDPOINT, true);
offlineProxy = new SampleContractClient(OFFLINE_ENDPOINT, true);

dp = new DynamicTargetProxyFactory(onlineProxy, offlineProxy);

proxy = dp.GetCurrentTarget();

proxy.Execute(Guid.NewGuid());
}
}


Testing...

To test the switch between proxies, we will do the following steps:
1. Put the server on different machine (don't forget to open the server queue & change the client config to point the server machine).
2. Add a console.writeline on the proxy's desicion in Intercept method in DynamicTargetProxyInterceptor and the 'proxy.Execute' in a loop.
3. Start the server.
4. Disconnect the client from the network.
5. Run the application in the client - we'll see the use of the offline proxy (using MSMQ in this case).
6. Connect the client to the network, call a server method, the online proxy will be chosen (regular TCP channel).
7. The server will receive all calls (thanks to MSMQ...).

The result:

On the left we can see the client in a local machine, we can see the switch between the offline & the online proxy, on the right we can see the remote server machine showing that all the messages arrived - offline & online...



This step's mission is accomplished.

Till next time...

Diego

PS: Source Download

Saturday, January 30, 2010

The "Fancy Proxy" - having fun with WCF - 4-MSMQ Duplex

This article is part of The "Fancy Proxy" tutorial - implementing a few advance ideas in WCF in one solution.

This is the 4th step - MSMQ Duplex.

Ok...so let's see what we explored till now:
In the first two steps we saw simple TCP & simple MSMQ samples on the 3rd we experienced a sample a bit more complex - duplex.

Duplex allowed us to use two "one-way" interfaces to build a dialog between the client & the server in duplex the client actually leaves his endpoint and "becomes" the server waiting for the real one to call him back...
This is nice, but it's not quite the disconnected solution we are looking for.
MSMQ is, but then the "online" code would be weird & not natural using only one-way communication.

So what we're really looking for is a way to work with MSMQ but not only one-way but both-ways - meaning some kind of combination between MSMQ & Duplex.
Looking for this type of solution I was amazed to discover Microsoft did not implemented a "two-way" solution for MSMQ...All the samples I found included use of old MSMQ libraries code...opening queues etc..that's not WCF...WCF is suppose to separate between the code & the transport decisions....hmmm...

Then I found a great work by Nicolas Dorier called Duplex MSMQ I won't get deep here on how he implemented this if you want to read about it better go to the source on Code Project.
So let's take this excellent solution for a spin..

First we open a queue for the server & for the client since they will both talk to each other using queues (in develop environment it's on the same machine, in production it will of course be separated).




The contract is similar to duplex solution, it includes two "one-way" interfaces when the second acts as the "callback" interface of the first one.


[ServiceContract(CallbackContract=typeof(ISampleContractCallback))]
public interface ISampleContract
{
[OperationContract(IsOneWay=true)]
void GetData(Guid identifier);

[OperationContract(IsOneWay = true)]
void Execute(Guid identifier);
}

public interface ISampleContractCallback
{
[OperationContract(IsOneWay = true)]
void SendData(Guid identifier, string answer);
}


Same on the server's code - looks like regular duplex solution, notice the 'GetCallbackChannel' that retrieves the channel back to the client.


public void GetData(Guid identifier)
{
Console.WriteLine("recieved GetData request (id {0})", identifier);

ISampleContractCallback client = OperationContext.Current.GetCallbackChannel();

//get data by identifier
string answer = "hi! from server";

client.SendData(identifier, answer);
}

public void Execute(Guid identifier)
{
Console.WriteLine("recieved Execute request (id {0})", identifier);
}


The host is the same as previous steps...

On the client's code there are some changes, the proxy gets the channel from the 'DuplexMsmqChannelFactory' (part of the duplex-msmq solution) and it implements both interfaces, I showed here one way to implement this using events though it's not part of our final solution.


public class testFancyProxyProxy:ISampleContract, ISampleContractCallback
{
private ISampleContract proxy;

public delegate void AnswerArrivedHandler(object sender, AnswerArrivedArgs args);

public event AnswerArrivedHandler AnswerArrived;

public testFancyProxyProxy()
{
proxy = DuplexMsmqChannelFactory.GetChannel(ConfigurationSettings.AppSettings["ClientURI"],
this,
ConfigurationSettings.AppSettings["ServerURI"]);
}

#region ISampleContract Members

public void GetData(Guid identifier)
{
proxy.GetData(Guid.NewGuid());
}

public void Execute(Guid identifier)
{
proxy.Execute(Guid.NewGuid());
}

#endregion

#region ISampleContractCallback Members

public void SendData(Guid identifier, string answer)
{
OnAnswerArrived(this, new AnswerArrivedArgs(identifier, answer));
}

#endregion

protected void OnAnswerArrived(object sender, AnswerArrivedArgs args)
{
if (AnswerArrived != null)
{
AnswerArrived(sender, args);
}
}
}

public class AnswerArrivedArgs:EventArgs
{
private Guid _identifier;
private string _answer;

public AnswerArrivedArgs(Guid identifier, string answer)
{
_identifier = identifier;
_answer = answer;
}

public Guid Identifier { get { return _identifier; } }
public string Answer { get { return _answer; } }
}


And the consumer, simple test:


public void Run()
{
Console.WriteLine("press any key to run..");
Console.Read();

proxy = new testFancyProxyProxy();

proxy.AnswerArrived += new testFancyProxyProxy.AnswerArrivedHandler(proxy_AnswerArrived);

proxy.GetData(Guid.NewGuid());

proxy.Execute(Guid.NewGuid());

Console.WriteLine("press any key to close client..");
Console.Read();
}

private void proxy_AnswerArrived(object sender, AnswerArrivedArgs args)
{
Console.WriteLine("answer from server for id {0}: {1}", args.Identifier, args.Answer);
}




That's it for this step.

2 more steps to go...in the next one we will see a nice way to wrap & encapsulate the changing of the proxy (online/offline) using dynamic proxy & than we will combine all we learned here together in the final step.

Till than...

Feel free to ask/comment...

Diego

PS: Source download

Saturday, January 16, 2010

The "Fancy Proxy" - having fun with WCF - 3-Simple Duplex

This article is part of The "Fancy Proxy" tutorial - implementing a few advance ideas in WCF in one solution.

This is the 3rd step - Simple Duplex

Ok..so why duplex?! in the final step I want to have a proxy that dynamically changes between online & offline state - in previous step we looked at MSMQ - that would be our "offline" solution...I need an "online" solution that will work implementing the same interface, which is "one-way", but I also want to benefit from the "online" state and actually receive "answers" from the server...

So...let's implement a simple Duplex on WCF - to do just that.

We'll start with the contract, since Duplex is designed for async processing, it is built from two "one-way" interfaces, the second acts as the callback interface.

We'll use the same contract as previous samples, we'll see the second -
ISampleContractCallback is registered as the "CallbackContract" of the first interface:

[ServiceContract(CallbackContract=typeof(ISampleContractCallback))]
public interface ISampleContract
{
[OperationContract(IsOneWay=true)]
void GetData(Guid identifier);

[OperationContract(IsOneWay = true)]
void Execute(Guid identifier);
}

public interface ISampleContractCallback
{
[OperationContract(IsOneWay = true)]
void SendData(Guid identifier, string answer);
}


Next we'll implement this interface on server side - our "business logic", here we'll call back the client with the "answer":

public class testFancyProxyService:ISampleContract
{
public void GetData(Guid identifier)
{
Console.WriteLine("recieved GetData request (id {0})", identifier);

ISampleContractCallback client = OperationContext.Current.GetCallbackChannel();

//get data by identifier
string answer = "hi! from the server";

client.SendData(identifier, answer);
}

public void Execute(Guid identifier)
{
Console.WriteLine("recieved Execute request (id {0})", identifier);
}
}


As previous samples, the host does not change:

class Program
{
private static ServiceHost serviceHost = null;

static void Main(string[] args)
{
try
{
startListening();

Console.WriteLine("Server is up, press any key to stop it...");
Console.Read();
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Error: {0}\n\n Stack:{1}", ex.Message, ex.StackTrace));
Console.Read();
}
finally
{
stopListening();
}
}

private static void startListening()
{
// Create a ServiceHost for the CalculatorService type and
// provide the base address.
serviceHost = new ServiceHost(typeof(testFancyProxyServer.testFancyProxyService));

// Open the ServiceHostBase to create listeners and start
// listening for messages.
serviceHost.Open();
}

private static void stopListening()
{
if (serviceHost != null)
{
if (serviceHost.State == CommunicationState.Opened)
{
serviceHost.Close();
}
}
}
}


The server's endpoint stays as the "regular" TCP sample

<endpoint address="net.tcp://localhost:8080/testFancyProxy" binding="netTcpBinding"
bindingConfiguration=""
contract="testFancyProxyContracts.ISampleContract" />


Same thing on client side - we'll code a small proxy - here we'll create a 'DuplexChannelFactory' instead of a "regular" ChannelFactory:

public class testFancyProxyProxy:ISampleContract
{
InstanceContext m_context;
private NetTcpBinding tcpBinding;
private EndpointAddress endPointAddress;
ISampleContract proxy;

public testFancyProxyProxy(InstanceContext context)
{
m_context = context;
tcpBinding = new NetTcpBinding(SecurityMode.Transport);
endPointAddress = new EndpointAddress(ConfigurationSettings.AppSettings["ServerURI"]);

proxy = new DuplexChannelFactory(m_context, tcpBinding).CreateChannel(endPointAddress);
}

public void GetData(Guid identifier)
{
proxy.GetData(identifier);
}

public void Execute(Guid identifier)
{
proxy.Execute(identifier);
}
}


Testing...to receive an answer from server, we'll add implementation for ISampleContractCallback.

public class testFancyProxyConsumer : ISampleContractCallback
{
private static InstanceContext m_context = null;
private testFancyProxyClient.testFancyProxyProxy proxy;

public void Run()
{
m_context = new InstanceContext(this);

proxy = new testFancyProxyProxy(m_context);
proxy.GetData(Guid.NewGuid());

proxy.Execute(Guid.NewGuid());
}

//ISampleContractCallback:
public void SendData(Guid identifier, string answer)
{
Console.WriteLine("answer from server for id {0}: {1}", identifier, answer);
}
}





That's it!! 3rd step - that's it for the basics, till now we saw simple TCP, simple MSMQ and simple Duplex...next step we'll start with the more advanced steps towards our final goal - a duplex-dynamic proxy.

Till next step...
Diego

PS: source download

Friday, January 8, 2010

The "Fancy Proxy" - having fun with WCF - 2-Simple MSMQ

This article is part of The "Fancy Proxy" tutorial - implementing a few advance ideas in WCF in one solution.

This is the 2nd step - Simple MSMQ

2st step, lets implement a simple MSMQ on WCF - so we understand the basics.

We'll start with the contract, since one of MSMQs benefits is support of disconnected enviroment, the interface it implements can be only "one-way" (we'll explore this later on...).

So we'll start with the same contract (except the "two-way" method):

[ServiceContract]
public interface ISampleContract
{
//[OperationContract]
//string GetData(Guid identifier);

[OperationContract(IsOneWay=true)]
void Execute(Guid identifier);
}


Next we'll implement this interface on server side - our "bussiness logic":

public class testFancyProxyService:ISampleContract
{
public void Execute(Guid identifier)
{
Console.WriteLine"recieved Execute request (id {0})", identifier);
}
}


Next, lets host the service, this host did not change from previous step which is super-cool, specially for those who experiment MSMQ before WCF existed:

class Program
{
private static ServiceHost serviceHost = null;

static void Main(string[] args)
{
try
{
startListening();

Console.WriteLine("Server is up, press any key to stop it...");
Console.Read();
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Error: {0}\n\n Stack:{1}", ex.Message, ex.StackTrace));
Console.Read();
}
finally
{
stopListening();
}
}

private static void startListening()
{
// Create a ServiceHost for the CalculatorService type and
// provide the base address.
serviceHost = new ServiceHost(typeof(testFancyProxyServer.testFancyProxyService));

// Open the ServiceHostBase to create listeners and start
// listening for messages.
serviceHost.Open();
}

private static void stopListening()
{
if (serviceHost != null)
{
if (serviceHost.State == CommunicationState.Opened)
{
serviceHost.Close();
}
}
}
}


Configure the server's endpoint to listen to the private "testFancyProxy" queue.

<services>
<service name="testFancyProxyServer.testFancyProxyService">
<endpoint address="net.msmq://localhost/private/testFancyProxy"
binding="netMsmqBinding" bindingConfiguration="NoMSMQSecurity"
contract="testFancyProxyContracts.ISampleContract" />
</service>
</services>
<bindings>
<netMsmqBinding>
<binding name="NoMSMQSecurity" maxReceivedMessageSize="1073741824">
<readerQuotas maxArrayLength="1073741824" />
<security>
<transport msmqAuthenticationMode="None" msmqProtectionLevel="None" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netMsmqBinding>
</bindings>


Create the queue (Computer management->Services and Applications->Message Queuing->Private Queues):





Same thing on client side - we'll code a small proxy (yes, you can instead use "add service reference" on visual studio :-)) - again, this class is exactly as in previous sample since msmq stuff are in config file only:


public class testFancyProxyProxy:ISampleContract
{
ChannelFactory channelFactory;
ISampleContract proxy;

public testFancyProxyProxy()
{
channelFactory = new ChannelFactory("msmqEndPoint");
proxy = channelFactory.CreateChannel();
}

public void Execute(Guid identifier)
{
proxy.Execute(identifier);
}
}


Configure the client and test it:

<system.serviceModel>
<client>
<endpoint address="net.msmq://localhost/private/testFancyProxy"
binding="netMsmqBinding" bindingConfiguration="NoMSMQSecurity"
contract="testFancyProxyContracts.ISampleContract"
name="msmqEndPoint"/>
</client>
<bindings>
<netMsmqBinding>
<binding name="NoMSMQSecurity" maxReceivedMessageSize="1073741824">
<readerQuotas maxArrayLength="1073741824" />
<security>
<transport msmqAuthenticationMode="None" msmqProtectionLevel="None" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netMsmqBinding>
</bindings>
</system.serviceModel>


Testing...(same as previous sample...):

public class testFancyProxyConsumer
{
private testFancyProxyClient.testFancyProxyProxy proxy;

public void Run()
{
proxy = new testFancyProxyProxy();
Guid identifier = Guid.NewGuid();
proxy.Execute(identifier);

Console.WriteLine("Message {0} sent", identifier);
}
}





That's it!! 2nd step - nice & simple..

So you may ask..."if everything is the same except the config...what do I need MSMQ for??"

Well...there are a few..async processing, managing priority etc, we'll explore the relevant benefit - disconnected enviroment.

Lets add time stamp to the messages both on client & server.

Now lets start only the client.




After a few minutes, lets start the server.




As you can see the server recieved the message altough it was down when the message was sent - isn't that cool?


Till next step...
Diego

PS: source download

Thursday, December 31, 2009

The "Fancy Proxy" - having fun with WCF - 1-Simple TCP

This article is part of The "Fancy Proxy" tutorial - implementing a few advance ideas in WCF in one solution.

This is the 1st step - Simple TCP

Ok...so let's start than...

1st step, lets implement the easiest WCF "hello world" - just to warm up.

We'll start with the contract:

[ServiceContract]
public interface ISampleContract
{
[OperationContract]
string GetData(Guid identifier);

[OperationContract]
void Execute(Guid identifier);
}


Next we'll implement this interface on server side - our "bussiness logic":

public class testFancyProxyService:ISampleContract
{
public string GetData(Guid identifier)
{
Console.WriteLine("recieved GetData request (id {0})", identifier);

//in real life we'll probably get data using the identifier
return "hello world..";
}

public void Execute(Guid identifier)
{
Console.WriteLine("recieved Execute request (id {0})", identifier);
}
}


Next, lets host the service:

class Program
{
private static ServiceHost serviceHost = null;

static void Main(string[] args)
{
try
{
startListening();

Console.WriteLine("Server is up, press any key to stop it...");
Console.Read();
}
catch (Exception ex)
{
Console.WriteLine(string.Format("Error: {0}\n\n Stack:{1}", ex.Message, ex.StackTrace));
Console.Read();
}
finally
{
stopListening();
}
}

private static void startListening()
{
serviceHost = new ServiceHost(typeof(testFancyProxyServer.testFancyProxyService));

// listening for messages.
serviceHost.Open();
}

private static void stopListening()
{
if (serviceHost != null)
{
if (serviceHost.State == CommunicationState.Opened)
{
serviceHost.Close();
}
}
}
}


Configure the server's endpoint to listen on any available TCP port and that's it for the server.

<endpoint address="net.tcp://localhost:8080/testFancyProxy" binding="netTcpBinding"
contract="testFancyProxyContracts.ISampleContract" /;>


Same thing on client side - we'll code a small proxy (yes, you can instead use "add service reference" on visual studio :-)):


public class testFancyProxyProxy:ISampleContract
{
private ChannelFactory channelFactory;
private ISampleContract proxy;

public testFancyProxyProxy()
{
channelFactory = new ChannelFactory("tcpEndPoint");
proxy = channelFactory.CreateChannel();
}

#region ISampleContract Members

public string GetData(Guid identifier)
{
return proxy.GetData(identifier);
}

public void Execute(Guid identifier)
{
proxy.Execute(identifier);
}

#endregion
}


Configure the client and test it:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="net.tcp://localhost:8080/testFancyProxy/"
binding="netTcpBinding"
contract="testFancyProxyContracts.ISampleContract"
name="tcpEndPoint"/>
</client>
</system.serviceModel>
</configuration>


Testing...:

public class testFancyProxyConsumer
{
private testFancyProxyClient.testFancyProxyProxy proxy;

public void Run()
{
proxy = new testFancyProxyProxy();

Console.WriteLine(proxy.GetData(Guid.NewGuid()));

Console.WriteLine("calling Execute..");
proxy.Execute(Guid.NewGuid());

}
}







That's it!! 1st step - nice & simple..this project will be the base of the next steps.

Till next step...
Diego

PS: source download

The "Fancy Proxy" - having fun with WCF

A little project I was doing at home lately lead me to search for a solution to disconnected application.

In my imaginination I imagined an application that knows to work both "online" and "offline"...not just that but also knows how to switch between them when needed and ofcourse - controlled from WCF configuration or other infrastructure that will be as "transparent" as possible for the programmer who writes the application.

Sounds a little like science fiction? not quite...

Gathering information from all sort of good articles & blogs I've reach to a nice project which I've decieded to share with you in a kind of tutorial structure to help ,who ever finds this interesting, step by step.
I know the code could & should pass a bit of polish, but hey! remember it's just an idea not production material :-)

Each step in this "tutorial" represents a step in the way for the full solution, this is only to help understand each concept seperatly, feel free to jump over a few steps or go directly to the final step...

1- Simple TCP
2- Simple MSMQ
3- Simple Duplex
4- MSMQ Duplex
5- Simple Dynamic proxy
6- Dynamic & Duplex proxy

Feel free to ask or comment...

Diego

Saturday, October 3, 2009

MSMQ & WCF

Very interesting sample I ran into showing how to use MSMQ with WCF.

Going through the 'right' way to implement this, I encountered many samples where the queing & message stuff were embeded in the bussiness logic - I couldn't understand how this meets WCF goal to seperate transport from bussiness logic.

Finally I encounter this article.

The interesting part of the sample was the elegant way the writer shows how to narrow the MSMQ code to the binding code (configuration) & leaving the code nice and clean allowing to change transport without touching the bussiness logic - this maybe sounds easy when moving from TCP to HTTP or similar, but since MSMQ is message oriented it is more of a challenge.

For the full story, including a short & sweet video - see:
SOA'izing MSMQ with WCF (and Why It's Worth It)

Diego.