I have WCF Service-client, On Service side, If unhandled exception is thrown, the channel will get faulted, After channel is faulted i have to recreate the client side.
When i create the client i use ChannelFactory, so i need to .Abort the current channel and then create it again.
What is the benefit of doing Try Catch with Fault Exception on service side ? it wont fault the channel ?
My managed application contains several ServiceHost opened, How can i register their faulted state and restart a certain service from the Event Handler?
Code:
...
serviceHost.Faulted+=serviceHost_Faulted;
...
private static void serviceHost_Faulted(object sender, EventArgs e)
{
//How to detect the channel information ? can i cast sender to and know its implemented IService interface ?
}
Related
I have a WCF Duplex net.tcp binding. I create a client DuplexClient to comuunicate with server. If, for some reason the service stop responding (app pool recycles for exemple) between the client creation and the method call, I get a weird behavior.
try
{
var result = await client.SomeMethod();
}
catch (Exception ex)
{
Console.WriteLine($"client.State = {client.State}");
Console.WriteLine($"Error : {ex.Message}");
}
I have this message in the console :
client.State = Opened
Error : The communication object,
System.ServiceModel.Channels.ClientFramingDuplexSessionChannel, cannot
be used for communication because it is in the Faulted state.
How can the channel be in the state Opened while the error says that it is in a Faulted state ? I strongly suspect the ClientFramingDuplexSessionChannel type because it probably keeps an open channel from server to client while the client to server channel is dead. Is it possible ? How can I check if client is realy opened and running both ways ?
We are implementing a saga that calls out to other services with NServiceBus. I'm not quite clear about how NServiceBus deals with exceptions inside a saga.
Inside the saga we have a handler, and that handler calls an external service that should only be called once the original message handler completes succesfully. Is it okay to do:
public void Handle(IFooMessage message)
{
var message = Bus.CreateInstance<ExternalService.IBarMessage>();
Bus.Send(message);
// something bad happens here, exception is thrown
}
or will the message be sent to ExternalService multiple times? Someone here has suggested changing it to:
// handler in the saga
public void Handle(IFooMessage message)
{
// Do something
var message = Bus.CreateInstance<ISendBarMessage>();
Bus.SendLocal(message);
// something bad happens, exception is thrown
}
// a service-level handler
public void Handle(ISendBarMessage message)
{
var message = Bus.CreateInstance<ExternalService.IBarMessage>();
Bus.Send(message);
}
I've done an experiment and from what I can tell the first method seems fine, but I can't find any documentation other than http://docs.particular.net/nservicebus/errors/ which says:
When an exception bubbles through to the NServiceBus infrastructure, it rolls back the transaction on a transactional endpoint, causing the message to be returned to the queue, and any messages that user code tried to send or publish to be undone as well.
Any help to clarify this point would be much appreciated.
As long as you're doing messaging from your saga and not doing any web service calls, then you're safe - no need to do SendLocal.
I'm looking at NServiceBus v3.3.0.0, in our MessageHandler it calls an external WCF service.
If the WCF service is called synchronously and that service throws an exception, NServiceBus handles it perfectly and retries the process as per configuration.
But, if the WCF service is called asynchronously and an exception is thrown then the subscriber process crashes.
So, for example, this handles the exception fine if service.Update throws
public class LeagueMessageHandler : IHandleMessages<LeagueMessage>
{
public void Handle(LeagueMessage message)
{
var service = new LeagueService.LeagueContractClient();
var league = service.Update(leagueDto);
}
}
but if the call to service.UpdateAsync throws an exception then the process crashes
public class LeagueMessageHandler : IHandleMessages<LeagueMessage>
{
public async void Handle(LeagueMessage message)
{
var service = new LeagueService.LeagueContractClient();
var league = await service.UpdateAsync(leagueDto);
}
}
The WCF service is just added as a Service Reference to the class library, it generates the Async method wrappers.
Edit after Adam and Udi comments.
It looks like the issue is unrelated to NServiceBus it's more to do with how console applications handle async methods throwing exceptions. Please see thread
Catch unhandled exceptions from async
Stephen Cleary has written this
http://nuget.org/packages/Nito.AsyncEx
which helps you roll your own SynchronisationContext which handles catching the exception. So the WCF call above is wrapped such...
var league = AsyncContext.Run(() => service.UpdateAsync(leagueDto));
when the exception gets thrown it is caught within that context and the console app no longer closes.
When you call it async, the exception happens on a different thread than the one that is processing the message. For that reason, there's no way for NServiceBus to know which message was the one to cause that exception, so it can't roll anything back.
When using NServiceBus, your overall architecture is already asynchronous - there really isn't any need to perform these WCF calls asynchronously.
My client is using one WCF service which is throwing an exception
(EXCEPTION: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state).
All subsequent calls throwing an same exception.
I read on internet that client need to close()/Abort() channel, this will solve the problem. is it completely right?
Also I am using customer serviceChannel factory provided by service developers. When I create channel it does not show the close and abort methods. So how do I get these close and abort methods when I create custom service channel instance on client side?
Assuming that you have a proxy instance that implements the IClientChannel interface, here is a way (hopefully the right way) to use it.
IClientChannel clientChannel = (IClientChannel)proxy;
bool success = false;
try
{
// do something with the proxy
clientChannel.Close();
success = true;
}
finally
{
if (!success)
{
clientChannel.Abort();
}
}
You may also want to check this. You can wrap your operations using a shared class or function.
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));
}