I have a WPF client that makes calls to 2 WCF services.
One service is for querying only and one service is for commands (CQS pattern).
How should I make the calls to the commands service ?
I read somewhere that all the operations in the command service must be 'One-Way',
because they should not return any values. And that if something went wrong - the operation should throw a 'FaultException' to the client.
But if the commands are all One-Way - what do I do in the client ?
Say I have an 'AddProduct' window in the WPF client, and I enter information and press 'Save'.
I now call 'AddProduct(Product)' in the service, but :
Should it close the window ?
Should it wait for 10 seconds to see if there wasn't any FaultException ?
Should the operation not be 'One-Way' ? If so - should all operations in the command service return some type of generic 'Result' object with 'succeeded' or 'failed' ?
If section 3 is 'Yes' - should I call the service in a seperate thread and 'disable' all the controls on the window until I get a response back from the service ?
Thanks.
I would say option 3 is the way to go, but you probably do not need the generic Result object to communicate errors to the client. As you might know, exceptions are not serialized in the SOAP message so you won't get any of the usual .NET exceptions on the client side. On the other hand, you can still take advantage of SOAP Faults by catching FaultException on the client. Accordingly, if no exceptions were caught on the client, then everything went well.
For more information about fault exceptions and how you can use them to your benefit, take a look at:
Specifying and Handling Faults in Contracts and Services
I think using On-Way is fine but you have to be aware of some one-way call characteristic. If you care and can handle service exceptions then #4 is fine option.
One Way message - Once the client issues the call, WCF generates the request message but no correlated message will be ever returned to the client. Any exceptions thrown on the service side will not make it to the client.
One thing that you should have on is the reliability on your service so side so that you can insure that request has been delivered to the service.
When there is no transport session (basic or wsHttp binding) if exception occurs during the call of one-way operation client will be unaffected and it can continue sending calls on the same proxy instance.
If there is a presence of transport session - service side exception will fault the channel hence client will not be able to re-use proxy for sending more calls. This can give you an option to discover if something went wrong on the server side (but not what went wrong). Although, if service is using a FaultContracts you can still get into situation where client is unaware that something went wrong.
When service throws an exception listed in service side fault contract this will not fault the communication channel hence the client using one-way contract cannot detect communication failure.
Related
For some reason, all the examples I find on WCF MSMQ show void as the return type of the method. Is this just coincidence? If not, why? What are the valid return types?
There are no valid Return types for sending to to a WCF service on an MSMQ end point.
Because you are writing to a queue and not directly communicating with the service the communication channel is not available for the service to send a response. Additionally one of the major benefits of writing to the queue is that the service may not even be running at the point the message is sent, the message will get picked up once the service becomes active again.
If no exception is thrown whilst sending to the service then you know that the message has at the very least been added to the message queue.
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 service that uses callback operations to call back its client. Is there a away to notify the client when Service goes down? An exception is raised when client goes down during callback, but with service goes down the subscription is lost but client is not notified.
Does WCF support some heartbeat operation to check the state of the service?
Thanks
No, there's no such thing as a "check if this service call will succeed" method.
You need to call the service and be prepared to handle any exceptions that occur during the service call.
There's really no reliable or useful way to check for service availability. All that a heartbeat could check for is that you can call your service method right now - but a fraction of a second later, that connection might be gone (cable has been unplugged or severed, server has crashed - the possibilities of things going wrong are endless......), too. It cannot check if all the necessary background services and databases etc. are available.
So in reality, such a heartbeat check is quite pointless. Just call the service, hope for the best, and be prepared for the worst! Wrap your service calls in good exception handling, and get on with it.
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
I have the standard error handing in place in my service:
I have an IErrorHandler hooked to the service to handle unexpected errors during service execution.
I have try/catch blocks in all my service methods to handle expected cases.
However, there are cases where exceptions are thrown on the server and neither is called.
Here is a case where the server exception is not sent to the IErrorHandler:
Set the receiveTimout on the server binding to 5 seconds.
On the client do this:
.
Service1Client sc = new Service1Client();
ICommunicationObject o = sc as ICommunicationObject;
o.Open(); // open channel
sc.GetData(10); // do a first call
Thread.Sleep(10000); // wait longer than the server receiveTimeout
sc.GetData(10); // Attempt another call: server throws a FaulException
In that case, the error is thrown on the server but I cannot find a way to handle it (and log it). I know an error is raised because if I attach a debugger on the server process and break on all exceptions, the debugger breaks.
I have found other similar cases where low level errors are not passed to my program.
Where can I hook my code to ensure that I can handle ALL exceptions that occur on the server before they are returned to the client app? Should I implement my own IChannel or some other low level interface?
Thanks
UPDATE Sep 21 2009: See this thread on the Microsoft WCF Forum. I'll probably have to implement my own Channel if I want to handle this type of exception. I'll update this post again when I have more info.
After much research and experimentation, the answer is:
At this time (.Net 3.5) there is no mechanism that allows one to handle all possible exceptions that may occur in the context of a WCF call.
Exceptions that happen during the service method execution can easily be handled with:
Try/catch blocks in all service methods to handle expected cases.
IErrorHandler hooked to the services to handle unexpected errors during service execution.
However, for low level WCF infrastructure errors, there is no perfect solution. The best solution that exists seems to be to implement a custom channel to catch more exceptions.
In this Microsoft Connect Bug Report, Microsoft confirms that there is no way to handle all types WCF infrastructure errors.
In this thread on the Microsoft WCF forums, there is a sample on how to implement a custom channel. That solution only works for HTTP, not for HTTPS. Also some WCF infrastructure errors are not caught by the custom channel either (see more details in that specific thread).
Use FaultContracts. Then the fault can be handled at the client end.
http://msdn.microsoft.com/en-us/library/ms732013.aspx
http://www.c-sharpcorner.com/UploadFile/ankithakur/ExceptionHandlingWCF12282007072617AM/ExceptionHandlingWCF.aspx
This is also much better for debugging, since often you will be developing a client and don't want to bring down the server for debugging purposes.
On the client end, use try/catch blocks to catch all exceptions/faults. There are definitely errors that can't be detected on the server end, such as a communication problem, so you need to handle errors on the client end anyways.
If you want centralized error handling, you can create a service that takes messages about all errors, send the error to that server, and have it log that. This can be useful if you want to create a centralized message tracing/performance analysis/logging tool and have a large number of application processors, servers, clients etc.
The point is - if the server is not reachable or can't handle the message, there won't be an error on the server - the error will pop up on the client ("TimeoutException" or others).
So in those cases, having the IErrorHandler on the server really isn't gonna help - since the error really happens on the client (no connection can be made, due to network down, or typo in server's address or sstuff like that).
So on the client side, you definitely also have to use try....catch around all your server calls.
Marc
Set up diagnostic tracing and check the logs with Service Trace Viewer Tool. Link contains information about configuring tracing as well.