How do I prevent a WCF service from enter a faulted state?
Asked Answered
S

6

37

I have a WCF Service that should not enter the faulted state. If there's an exception, it should be logged and the service should continue uninterrupted. The service has a one-way operation contract and is reading messages from an MSMQ.

My problems are twofold:

  1. The service appears to be swallowing an exception/fault so I am unable to debug it. How do I get the service to expose the exception so that I can log or handle it?
  2. The service is entering into a faulted state after this exception is swallowed. How do I prevent the service from entering into a faulted state?
Scramble answered 24/11, 2008 at 22:31 Comment(1)
here you can get all theory msdn.microsoft.com/en-us/library/ms789041(v=vs.110).aspxAlluvium
M
21

Most, if not all exceptions can be seen in the WCF Trace (Configuring Tracing) and the trace is best viewed with the Service Trace Viewer.

Obviously, this is not something you should have running all day in a production environment, but it helps in troubleshooting anyway.

Apart from that, note that oneways may not run as a true "fire and forget" depending on the SessionMode you use. If you have your service configured for SessionMode.Allowed or even SessionMode.Required, the oneway operation will run as if it was not oneway at all (this can be observed when using oneways over the netTcpBinding). To be frank, however, I don't know if that changes the type of exceptions you can get, or when you get them. However, in any case, you should get an exception if the request could not be send at all. AFAIK, the oneway "ends" when it is successfully enqued on the server side. So there is some place for (WCF framework related) exceptions until then (serialization/deserialization comes to mind).

Then, such framework related exceptions are best seen (even an IErrorHandler doesn't get them all due to the fact when it is called in the request/response-flow) using the above mentioned trace / traceviewer.

Manno answered 25/11, 2008 at 6:54 Comment(1)
I am facing the similar issue.I have the service running on Production with netTcpBinding having few methods as IsOneway=True and SessionMode set to Required.However when there is exception occurs ,The services goes to Faulted state.To make it work i have to restart itTortoni
P
29

The official documentation on how to handle Faults is here:

with the main page being at Channel Model Overview

There's a nice state diagram showing how things happen:

enter image description here

Prebendary answered 10/5, 2011 at 8:43 Comment(0)
M
21

Most, if not all exceptions can be seen in the WCF Trace (Configuring Tracing) and the trace is best viewed with the Service Trace Viewer.

Obviously, this is not something you should have running all day in a production environment, but it helps in troubleshooting anyway.

Apart from that, note that oneways may not run as a true "fire and forget" depending on the SessionMode you use. If you have your service configured for SessionMode.Allowed or even SessionMode.Required, the oneway operation will run as if it was not oneway at all (this can be observed when using oneways over the netTcpBinding). To be frank, however, I don't know if that changes the type of exceptions you can get, or when you get them. However, in any case, you should get an exception if the request could not be send at all. AFAIK, the oneway "ends" when it is successfully enqued on the server side. So there is some place for (WCF framework related) exceptions until then (serialization/deserialization comes to mind).

Then, such framework related exceptions are best seen (even an IErrorHandler doesn't get them all due to the fact when it is called in the request/response-flow) using the above mentioned trace / traceviewer.

Manno answered 25/11, 2008 at 6:54 Comment(1)
I am facing the similar issue.I have the service running on Production with netTcpBinding having few methods as IsOneway=True and SessionMode set to Required.However when there is exception occurs ,The services goes to Faulted state.To make it work i have to restart itTortoni
C
12

Exceptions will fault the proxy. You can't AFAIK do much about that: don't cause exceptions ;-p

I'm a little surprised that one-way is still causing a problem, but for swallowing in general, there are 3 aspects:

  1. are you throwing faults? or exceptions? it matters (and should be "faults")
  2. as a hack, you can enable debug exception messages - but turn it off please!!!
  3. are you "using" the service object? I've just blogged on this exact subject... basically, your "using" can swallow the exception. 3 options:

    • don't use "using"
    • subclass the proxy and override Dispose()
    • wrap it, as per the blog
Chastity answered 24/11, 2008 at 22:41 Comment(3)
Thanks for the comments Marc. I stopped using using to try and track down the exceptions but no luck. The business layer that the WCF service is calling in to is throwing exceptions but these are being swallowed somewhere... Mystery...Scramble
You could try switching to FaultException<T> where T is a published fault - that might help things. And note it is still very important to close down the proxy; simply that "using" doesn't necessarily do quite what we want on this occasion.Chastity
I think only exceptions that not been caught and wrapped by the service will fault the proxy, but not all exceptionsTestator
O
11

Usually the WCF service is hosted in a ServiceHost, if the WCF-Service fails then the only option is to kill the WCF service and start a new one.

The ServiceHost has an event trigger "Faulted" that is activated when the WCF Service fails:

ServiceHost host = new ServiceHost(new Service.MyService());
host.Faulted += new EventHandler(host_faulted);
host.Open();

It is possible to get the exception causing the fault, but it requires a bit more work:

public class ErrorHandler : IErrorHandler
{
    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {

    }

    public bool HandleError(Exception error)
    {
        Console.WriteLine("exception");
        return false;
    }
}

public class ErrorServiceBehavior : IServiceBehavior
{
    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {

    }

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {

    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        ErrorHandler handler = new ErrorHandler();
        foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
        {
            dispatcher.ErrorHandlers.Add(handler);
        }
    }
}

ServiceHost host = new ServiceHost(new Service.MyService());
host.Faulted += new EventHandler(host_faulted);
host.Description.Behaviors.Add(new ErrorServiceBehavior());
host.Open();

Credits http://www.haveyougotwoods.ca/2009/06/24/creating-a-global-error-handler-in-wcf

Ogawa answered 2/12, 2009 at 15:12 Comment(1)
Tried this but the HandleError method is never hit, even though I hit the Faulted event handler.Lip
A
8

I had an issue where the Channel remained in a faulted state after a ReceiveTimeout exception. This would cause the service to be rendered unusable by any subsequent connections.

The fix for recovering the service from the faulted state for me was to handle the Faulted event of the communication channel:

 channelFactory = new ChannelFactory<IService>(endpoint);
 channelFactory.Faulted += OnChannelFaulted;
 var channel = channelFactory.CreateChannel();

Then define OnChannelFaulted:

 void OnChannelFaulted(object sender, EventArgs e)
 {
     channelFactory.Abort();
 }

Note: I am running the WCF config via code versus using bindings in the Web.config's.

Addiel answered 25/9, 2009 at 22:58 Comment(0)
C
7

About 2)...

The trick is that you should use "using" and should always call Abort() on the proxy that threw an exception. The article WCF Gotcha explains it all.

We use service class inspired by that article that wraps service calls. This is sample code from my project:

ServiceHelper<CodeListServiceClient, CodeListService.CodeListService>.Use(
    proxy => seasonCodeBindingSource.DataSource = proxy.GetSeasonCodes(brandID);
);

And this is the code of ServiceHelper, slightly modified from the article. So far it has served us really well.

using System;
using System.ServiceModel;

namespace Sportina.EnterpriseSystem.Client.Framework.Helpers
{
    public delegate void UseServiceDelegate<TServiceProxy>(TServiceProxy proxy);

    public static class ServiceHelper<TServiceClient, TServiceInterface> where TServiceClient : ClientBase<TServiceInterface>, new() where TServiceInterface : class
    {
        public static void Use(UseServiceDelegate<TServiceClient> codeBlock)
        {
            TServiceClient proxy = null;
            bool success = false;
            try
            {
                proxy = new TServiceClient();               
                codeBlock(proxy);
                proxy.Close();
                success = true;
            }
            catch (Exception ex)
            {
                Common.Logger.Log.Fatal("Service error: " + ex);                                
                throw;
            }
            finally
            {
                if (!success && proxy != null)
                    proxy.Abort();
            }
        }
    }
}
Clam answered 25/11, 2008 at 7:12 Comment(1)
The link to 'WCF Gotcha' post is broken, but I don't have enough rep to edit it. Here is the good link: old.iserviceoriented.com/blog/post/… .Aboveground

© 2022 - 2024 — McMap. All rights reserved.