Based on documentation and articles it is recommended to call Abort() on a client proxy if an unexpected exception/fault is encountered. See the following (simplified):
MyServiceClient proxy = null;
try {
proxy = new MyServiceClient();
proxy.DoSomething();
proxy.Close();
} catch (Exception ex) {
if (proxy != null)
proxy.Abort();
}
Is there any possibility of the call to Abort() throwing an exception itself? Should the call to Abort() be within its own try/catch?
No, Abort will not fail (but .Close() or .Dispose() might). Calling .Abort() is the "sledgehammer" approach to terminating a channel - it's just torn down, regardless of an ongoing message handling.
Use it only carefully - e.g. in a exception catch case when calling .Close() failed. That's it's real purpose and proper use.
Marc
Related
public UserMailDto getUserByEmail(String email) throws UserExceptionMessage {
try {
return userRepository.searchByMail(email);
} catch (DataAccessException | JDBCConnectionException accessException) {
com.example.user_service.config.log.Logger.errorLog("UserService", accessException.getMessage());
throw new DataAccessExceptionMessage(Messages.ERROR_TRY_AGAIN + accessException.getMessage());
}
}
In my view you should handle it, but not with a try..catch block in what seems to be your service. Why are you catching the Exception and then rethrowing you own custom Exception with a message? You will need to handle that Exception at some point in your code to. So you are not really handling it here.
It looks like you are building a web app, so I would recommend that you handle your Exceptions in one central place in a #ControllerAdvice class. You can read about it here. This way you can really handle the Exception, by returning a corresponding status code to the user. 503 in your case.
I have a WCF service with wsHttpBinding. Everything works just fine, but I have got problem with catching faults on my client, sent from my custom Authenticator.
I use custom Authenticator code from msdn:
https://msdn.microsoft.com/en-us/library/aa702565(v=vs.110).aspx
// This throws an informative fault to the client.
throw new FaultException("Unknown Username or Incorrect Password");
this comment says that we are throwing an informative fault to the client, but i can't catch it on the client side:
bool isReachable = false;
try {
isReachable = client.agentIsReachable();
}
catch(FaultException faultException){
MessageBox.Show(faultException.Message);
}
While debugging I can see, that a fault is thrown, but my clients catch code does not work. My communication channel faults, but without fault exception. Then i catch a .NET ex, saying that I am trying to use faulted proxy.
Everything works great when i throw faults from any of my service methods. I can catch them on my client.
Is it really possible to catch faults, sent from Authenticator. And what is the best way to pass an informative message to the client when authentication fails?
Client-side, the exception you have to catch is not a FaultException but a MessageSecurityException (using System.ServiceModel.Security).
Then you can retrieve your FaultException with the InnerException attribute of the MessagSecurityException you caught. In your case, you'll end up with something similar to this:
catch (MessageSecurityException e)
{
FaultException fault = (FaultException) e.InnerException;
MessageBox.Show(faultException.Message);
}
I hope it will help.
I have a WCF service that's hosted in IIS, and uses a WS HTTP binding (the external service). This service ends up calling a second WCF service that's hosted in a Windows service, over Net TCP (the internal service). When the internal service throws a FaultException, the external service crashes rather than throwing it to the client. All the client sees is the connection being forcibly closed.
The internal service uses the Enterprise Library Validation Application Block to validate the incoming messages. When validation errors occur, the service throws a FaultException<ValidationFault>.
Both the internal and external service have a [FaultContract(typeof(ValidationFault)] attribute in the service contract. If I change the external service to just immediately throw a new FaultException<ValidaitonFault>, this gets back to the client fine. I can catch the exception from the internal service in the external service, but if I try to re-throw it, or even wrap it in a new exception and throw that, the whole Application Pool in IIS crashses. I can't see anything useful in the event log, so I'm not sure exactly what the problem is.
The client object the external service uses to communicate with the internal service is definitely being closed and disposed of correctly. How can I get the internal service's faults to propagate out to the client?
updated:
Below is a simplified version of the external service code. I can catch the validation fault from the internal service call. If I throw a brand new FaultException<ValidationFault>, everything is fine. If I use the caught exception, the connection to the external client is broken. The only difference I can see is when debugging the service - trying to use the caught exception results in a message box appearing when exiting the method, which says
An unhandled exception of type
'System.ServiceModel.FaultException`1'
occurred in mscorlib.dll
This doesn't appear if I throw a brand new exception. Maybe the answer is to manually copy the details of the validation fault into a new object, but this seems crazy.
public class ExternalService : IExternalService
{
public ExternalResponse DoSomething(ExternalRequest)
{
try
{
var response = new ExternalResponse();
using (var internalClient = new InternalClient())
{
response.Data = internalClient.DoSomething().Data;
}
return response;
}
catch (FaultException<ValidationFault> fEx)
{
// throw fEx; <- crashes
// throw new FaultException<ValidationFault>(
// fEx.Detail as ValidationFault); <- crashses
throw new FaultException<ValidationFault>(
new ValidationFault(new List<ValidationDetail> {
new ValidationDetail("message", "key", "tag") }),
"fault message", new FaultCode("faultCode"))); // works fine!
}
}
}
I have almost the exact design as you and hit a similar issue (not sure about a crash, though!).
If I remember correctly, even though the ValidationFault is a common class when the Fault travels over the wire the type is specific to the WCF interface. I think this is because of the namespace qualifiers on the web services (but this was a while back so I could be mistaken).
It's not terribly elegant, but what I did was to manually re-throw the exceptions:
try
{
DoStuff();
}
catch (FaultException<ValidationFault> fe)
{
HandleFault(fe);
throw;
}
...
private void HandleFault(FaultException<ValidationFault> fe)
{
throw new FaultException<ValidationFault>(fe.Detail as ValidationFault);
}
Well, it works if I do this, but there must be a better way...
This only seems to be a problem for FaultException<ValidationFault>. I can re-throw FaultException and FaultException<SomethingElse> objects with no problems.
try
{
DoStuff();
}
catch (FaultException<ValidationFault> fe)
{
throw this.HandleFault(fe);
}
...
private FaultException<ValidationFault> HandleFault(
FaultException<ValidationFault> fex)
{
var validationDetails = new List<ValidationDetail>();
foreach (ValidationDetail detail in fex.Detail.Details)
{
validationDetails.Add(detail);
}
return new FaultException<ValidationFault>(
new ValidationFault(validationDetails));
}
We are using WCF service
on the client side we are planning to explicitly close the connection
It seems there are more then one way of closing
Sample1:
In the finally block of the WCF service consumption use
if (client.State == CommunicationState.Faulted)
{
client.Abort();
}
client.Close();
Since if the service is in fault state we will not be able to call close()
Sample2:
using(ClientProxy proxy = new ClientProxy())
{
//call your service methods
}
in sample2 i am not sure what will happen if the service is in fault state, will it throw error closing the connection?
You have all the necessary information at hand - the resulting Best Practice to use and properly close/abort all your WCF client proxies would be:
YourClientProxy clientProxy = new YourClientProxy();
try
{
.. use your service
clientProxy.Close();
}
catch(FaultException)
{
clientProxy.Abort();
}
catch(CommunicationException)
{
clientProxy.Abort();
}
catch (TimeoutException)
{
clientProxy.Abort();
}
Catching the FaultException handles all cases when the service responsded with an error condition (and thus your channel is in a faulted state), and CommunicationException will handle all other communication-related exceptions that can occur, like network connectivity dropping etc.
The approach with the using() block won't work, since if an exception happens at the end of the block, when the Dispose() method calls the Close() method on the client proxy, you have no way to catching and handling that.
The 2nd sample using the "using" block is incorrect. The using block ensures that the Dispose method is called on the proxy object. The Dispose method in turn calls the Close method which will (try to) connect to the service which will throw an exception when the communication state is faulted. So your feelings/hunch are absolutely right. It would be nice if the proxy Dispose method used the code from your first sample but it doesn't so don't use the using block :)
In Juval Lowy's Excellent Programming WCF book he recommends:
try
{
ClientProxy clientProxy = new ClientProxy();
clientProxy.SomeMethod();
clientProxy.Close();
}
catch
{
proxy.Abort();
}
Use sample 1
Here is a good article on why you should not use using:
http://msdn.microsoft.com/en-us/library/aa355056.aspx
What I found out was if you throw a FaultException from a new worker thread, it doesnt percolate up to the client but just crashes WCF.
Any solutions???
example:
var thread = new Thread(new ThreadStart(
delegate
{
new Killbot().KillAllHumans(); // Throws a FaultException
}));
The simplest way would be to wrap the call in a try-catch block and log the exception:
var thread = new Thread(new ThreadStart(
delegate
{
try
{
new Killbot().KillAllHumans(); // Throws a FaultException
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.ToString());
}
}));
If you want to handle the exception in your main thread you would have to use BeginInvoke and EndInvoke in combination with an AsyncCallback.
Personally I would not bother with background threads in a WCF service. A service is effectively a "background worker" anyway. All you need to do is ensure that any blocking calls you make inside the service don't affect other clients. You can do this by changing the concurrency mode:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
class MyServiceClass : IMyServiceContract {
public void KillAll() {
new Killbot().KillAllHumans(); // Throws a FaultException
}
}
When that is set, WCF will call your service methods on multiple threads with no attempt to synchronise them. As long as you write your code with this in mind, you can do all the blocking calls you want.