I have a win forms client that accesses a wcf service for a long running operation. The service exposes subscribe and unsubscribe methods. When a client calls the subscribe method, service generates new guid for it and gets the current callback context, saves this guid and callback context in a client Dictionary and returns the Guid. On user request, client call service with this guid to start the long operation. Once the service finishes the operation it gives a callback to the client. the client then retrieves the processed data from the service.
The error I get sometimes when doing a callback is
The operation 'OnServiceCallback' could not be completed because the sessionful channel timed out waiting to receive a message. To increase the timeout, either set the receiveTimeout property on the binding in your configuration file, or set the ReceiveTimeout property on the Binding directly.
The part that I am not able to understand is that this happens very inconsistently. Most of the times it happens after the client and the service have been running for some time.
I am a beginner in wcf service and welcome any suggestions to solve this error.
Binding has property called receiveTimeout. This property is by default set to 10 minutes. It defines how long does the service instance wait for next request before it is terminated. So if there is no activity between client and service within 10 minutes your service instance is closed and client can't use it any more. In duplex service it can be even more complicated because there are services on both sides. You will probably need to configure receiveTimeout on both ends.
I was able to figure the answer to the error by doing some good old trial and error. The callback was failing because the OperationContext.Current object that I was trying to use was null. This was because I was trying to access the OperationContext.Current object on a thread which was different from the service thread. So to solve that I am now accessing the OperationContext.Current object in the service thread and then passing the callbackContext as a parameter to the external processing logic which actually needs to use it.
Related
My WPF application is calling the WCF service using a single client object. This is working fine when request is sent and response is coming immediately before next request.
When I am sending the first request and it is taking 3 minutes to complete the calculation task and return the result. In the meanwhile second request is sent from my WPF application (ping request is sent every 3 second). At this time, I am getting the following error and WPF application getting disconnected:
The server did not provide a meaningful reply: this might be caused by a contract mismatch, a prematured session shutdown or an internal server error
The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
My service behavior is written as follows:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, IncludeExceptionDetailInFaults=true)]
I tried different combination and it is not working.
If you do multiple concurrent calls from singel client you should set ConcurrencyMode to Multiple in addition to InstanceContextMode ..
Note that if you set InstanceContextMode to Single, your service act as singleton, Then you should be aware of manipulating variables because it has reflection on other calls ..
Your Ping request should not use the same Channel. It should open it's own channel. Ideally, every independent request should open it's own channel (alternatively, you could build a queuing system). But accessing the same channel from two different threads is not going to work.
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.
I created a WCF service and the user requirement is to have only one client connected on the service at a time.
So I set the value of the parameter maxConcurrentSessions to 1.
It's working great and if another client try to connect after a specific time it receives a timeout exception error.
But I don't like to send the timeout exception error to the client I want to have a more specific error like :
A timeout occurs because the number of maximum client on the service was reached.
Something like that.
It's there a way to do that?
Thanks
You can override default exceptions by implementing IErrorHandler
From MSDN
To explicitly control the behavior of the application when an
exception is thrown, implement the IErrorHandler interface and add it
to the ErrorHandlers property. IErrorHandler enables you to explicitly
control the SOAP fault generated, decide whether to send it back to
the client, and perform associated tasks, such as logging. Error
handlers are called in the order in which they were added to the
ErrorHandlers property.
Implement the ProvideFault method to control the fault message that is
returned to the client
Also check this one .Net WFC/Web service exception handling design pattern
I have a WCF service operation and I want a call to the operation to start a long running method, however I want the operation to return its result BEFORE the long running method finishes.
I have tried using an IParameterInspector implementation, but the result of the operation is not returned to the client until the long running method has completed.
How should I go about achieving this as anything I start from the operation seems to have to finish before the result is returned to the client?
Thanks.
If you want to do it at the server, take a look at http://blogs.msdn.com/b/carlosfigueira/archive/2011/05/17/wcf-extensibility-ioperationinvoker.aspx, it shows how to bypass the operation (it's a caching scenario, but it can be adapted to your problem).
If you want to do it at the client, you can simply call the operation asynchronously, it will return right away. And when the long-running operation completes, you'll get a notification (callback or event) that its results are ready.
You can't do this with a standard request/response type binding in WCF because as you found out, you won't get a response until the service has completed processing (or times out).
To do what you want, you'll need a service where you can trigger the long running operation and then poll for completion status & response results.
The netMsmqBinding supports this scenario in WCF. All the operations for this binding must be a one-way call since you are only putting a message in a queue for processing. You'll need to have another endpoint or service configured with a request/response binding for the polling method. A good overview of the netMsmqBinding is here.
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