In a client server WCF duplex scenario, what is the recommended way to let the server know that an error occurred on the client side? Let's say that the server notifies one of the clients that it needs to perform a certain operation and an exception is being thrown on the client side.
On the callback interface, I have something like this
[OperationContract(IsOneWay = true)]
void Work(...);
What's the best approach:
Implement a NotifyServer(int clientId, string message) message that the client can call to let the user know that the requested operation failed,
If I set IsOneWay = false on the operation contract, would I have to call every client on a BackgroundWorker thread in order to keep the UI responsive?
Implementing async operations on the server? How will this work? I can generate async operation on the client, will I have to use the same pattern (BeginWork, EndWork) for the client callback method?
Can't think of anything else, because throwing a FaultException on the client side when IsOneWay = true will not work.
Any advice?
Thank you in advance!
Ad 1. That is one way of doing it... recommended if the Work() may take unpredictable amount of time and you do not want your server thread hanging on that call.
Ad 2. You should always perform WCF operations in the background worker and never inside the UI thread.. If you set IsOneWay=False then obviously Work() method will block on the server until it has finished executing on the remote client and returns results. However even if you set isOneWay=true the method will still block on the low-level WCF communication. If WCF connection is dropped, this can be a long time, before you get notified.
Ad 3.
The pattern is up to you.
Example: MSDN: OperationContractAttribute.AsyncPattern Property
No best solution exists. It all depends on your setup (classes, threads, etc). The WCF layer you code should be easy and convenient to use - that is the main guide line.
Related
I stuck on this one for about two weeks now - So could someone tell me, is there a limitation from WCF that only one callback at a time can be handled by a callback object? I have tried just about anything I can find in trying to resolve this issue still can't get any place.
I created a very simple app: a client invokes a service then the service makes two callbacks to the client at the same time: callback A, which takes a long time to return; then callback B, calls back repeatedly in a loop even when A is in processing. The problem is, B will never get through when A is in processing. But as soon as A returns, B will get through right away.
Here are the things I have tried:
1. Set ConcurrencyMode to Multiple or Reentrant on both client and service;
2. Set UseSynchronizationContext to False on both client and service;
3. Start service invocation from a worker thread on the client;
4. Creates proxy (service channel) on a worker thread on the client;
5. Start both callbacks on their own worker thread on the service;
6. Making both callbacks as Oneway.
None of these solved issue. The only thing I can think now is that this may be a limitation from WCF. So if someone can shed some light on this it will be greatly appreciated.
Could you try to make an async proxy? When you left click on you're project then clic add Service Reference, then check Generate asynchronous operations.
You will have a client that use event to callback returns. And if I'm not wrong, each callback are done in different threads.
In my client/server applications, I want a single duplex WCF channel to be available for communication with its server - sort of a background connection that isn't strictly necessary for the client application to run, but is desirable for reporting status to the server. I have a Ping() call and Echo() callback in the IServerContract and IClientContract respectively.
I implement class ServerProxy : System.ServiceModel.DuplexClientBase<IServerContract> with the pass-thru methods to base.InnerChannel.
If I create var proxy = new ServerProxy(...) in my client, I can just begin calling proxy.Ping() and WCF will automatically open the connection for the first call and perform the operation call immediately after. However, the first call always takes ~10 seconds because of channel initialization and authentication. (I'm using windows authentication, Message-based security, EncryptAndSign.) Subsequent calls are quicker.
I believe this 10 seconds is unavoidable, but there is usually time prior to the first call by the client to the server during which this initialization could happen. So rather than wait for the auto-open feature of DuplexClientBase, I open the channel early with a call to proxy.InnerDuplexChannel.Open(). (proxy.Open() throws an exception and this indirection seems to avoid it.)
Unfortunately, authenticating the client-to-server channel does not also authenticate the server-to-client callback channel. Instead, the first call by the server to the client ALSO requires ~10 seconds. Since I'm using netTcp binding I'm surprised by this, but I'll assume it is to be expected for now.
How can I open the callback channel preemptively as well?
I could require the client to call some Login() method instead, but I don't believe that WCF should strictly require an operation before user-code can be aware of a connected client!
Hint(?): I imagine that this code would have to go in a place in the WCF pipeline/lifecycle where the server has the opportunity to perform custom actions upon a client-connected event (and BEFORE any operation message is transmitted). This integration point has so far eluded me.
In my client program, there is a WCF connection that is opened at startup and supposedly stays connected til shutdown. However, there is a chance that the server closes due to unforeseeable circumstances (imagine someone pulling the cable).
Since the client uses a lot of contract methods in a lot of places, I don't want to add a try/catch on every method call.
I've got 2 ideas for handling this issue:
Create a method that takes a delegate and executes the delegate inside a try/catch and returns an Exception in case of a known exception, or null else. The caller has to deal with nun-null results.
Listen to the Faulted event of the underlying CommunicationObject. But I don't see how I could handle the event except for displaying some error message and shutting down.
Are there some best practices for faulted WCF connection that exist for app lifetime?
If you do have both ends of the wire under your control - both the server and the client are .NET apps - you could think about this approach instead:
put all your service and data contracts into a shared assembly, that both the server and the client will use
create the ChannelFactory<IYourService> at startup time and cache it; since it needs to have access to the service contract, this only works if you can share the actual service contract between server and client. This operation is the expensive part of building the WCF client
ChannelFactory<IYourService> factory = new ChannelFactory<IYourService>();
create the actual communications channel between client and server each time you make a call, based on the ChannelFactory. This is pretty cheap and doesn't cost much time - and you can totally skip any thoughts about having to detect or deal with faulted channels.....
IYourService client = factory.CreateChannel();
client.CallYourServiceMethod();
Otherwise, what you basically need to do is wrap all service calls into a method, which will first check for a channel's faulted state, and if the client proxy is faulted, aborts the current one and re-creates a new one.
I wrote a blog post on exceptions in WCF that deals with how to handle this: http://jamescbender.com/bendersblog/Default.aspx
Just trying to get my head around what can happen when things go wrong with WCF. I have an implementation of my service contract declared with an InstanceContextMode of PerSession...
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Multiple)]
The calls happen as follows:
My client calls the server and calls GetServerUTC() to return the current UTC time of the server. This is a one way call and the server will call the client back when its ready (trivial in this instance to simply return the current time!)
The server calls back to the client and for test purposes in the callback implementation on the client I throw an exception.
This goes unhandled in the client (for test purposes) and the client crashes and closes down.
On the server I handle the faulted event handler on the ICommunicationObject...
obj.Faulted += new EventHandler(EventService_Faulted);
Questions...
Will this kill off the session for the current connection on the server.
I presume I am free to do what I want in this method e.g. logging or something, but should I do anything specific here to terminate the session or will WCF handle this?
From a best practise view point what should I do when the callback is faulted? Does it mean "something has happened in your client" and thats the end of that or is there something I a missing here?
Additionally, are there any other faulted handlers I should be handling.
Ive done a lot of reading on WCF and it seems sort of vague on what to do when something goes wrong. At present I am implementing a State Machine on my client which will manage the connection and determine if a user action can happen dependant on if a connection exists to the server - or is this overkill.
Any tips would be really appreciated ;)
I found out that the session will time out as per the settings for your sessions. Strangely I noticed that once faulted the client is still able to call other methods on the same session.
Few methods in my WCF service are quite time taking - Generating Reports and Sending E-mails.
According to current requirement, it is required so that Client application just submits the request and then do not wait for the whole process to complete. It will allow user to continue doing other operations in client applications instead of waiting for the whole process to finish.
I am in a doubt over which way to go:
AsyncPattern = true OR
IsOneWay=true
Please guide.
It can be both.
Generally I see no reason for WCF operation to not be asynchronous, other than developer being lazy.
You should not compare them, because they are not comparable.
In short, AsyncPattern=True performs asynchronous invocation, regardless of whether you're returning a value or not.
OneWay works only with void methods, and puts a lock on your thread waiting for the receiver to ack it received the message.
I know this is an old post, but IMO in your scenario you should be using IsOneWay on the basis that you don't care what the server result is. Depending on whether you need to eventually notify the client (e.g. of completion or failure of the server job) then you might also need to look at changing the interface to use SessionMode=required and then using a Duplex binding.
Even if you did want to use asynchronous 2-way communication because your client DID care about the result, there are different concepts:
AsyncPattern=true on the Server - you would do this in order to free up server resources, e.g. if the underlying resource (?SSRS for reporting, Mail API etc) supported asynchronous operations. But this would benefit the server, not the client.
On the client, you can always generate your service reference proxy with "Generate Asynchronous Operations" ticked - in which case your client won't block and the callback will be used when the operation is complete.