Ask a questionAsk a question
 

AnswerException handling in WCF

  • Thursday, May 08, 2008 7:01 AMNgoc Luu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I have a problem with exception handling in WCF.

     

    Service contract:

    [ServiceContract()]

    public interface IMyService

    {

    [OperationContract]

    [FaultContract(typeof(DllNotFoundException))]

    [FaultContract(typeof(DivideByZeroException))]

    [FaultContract(typeof(Exception))]

    string Hello();

    }

     

    Service implementation:

    public class MyService : IMyService

    {

    public string Hello()

    {

    throw new FaultException<Exception>(new Exception("aaa"));

    return "Hi";

    }

    }

     

    Aspx page:

    try

    {

    ChannelFactory<IMyService> proxy = new ChannelFactory<IMyService>("MyService");

    IMyService client = proxy.CreateChannel();

    string h = client.Hello();

    Response.Write(h);

    }

    catch (FaultException<DllNotFoundException> ex1)

    {

    Response.Write(ex1.Detail.Message);

    }

    catch (FaultException<DivideByZeroException> ex2)

    {

    Response.Write(ex2.Detail.Message);

    }

    catch (FaultException<Exception> ex3)

    {

    Response.Write(ex3.Detail.Message);

    }

    catch (Exception ex4)

    {

    }

    In aspx page, I alway receive FaultException<DivideByZeroException> exception although I only throw FaultException<Exception> on service. But, when I remove [FaultContract(typeof(DivideByZeroException))] on service contract, I receive FaultException<Exception>.

    What's wrong? I attached a sample app at: http://cid-b044e83441146203.skydrive.live.com/self.aspx/Public/TestWCF.zip

    Anyone could help me!

Answers

  • Monday, May 12, 2008 4:38 PMJames Osborne - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    As a side note, you might consider adding a suggestion through connect.microsoft.com about enhancing the FaultContract design in WCF to handle CLR exceptions.  The reason this wasn't implemented is mainly because of interoperability.  We can't guarantee the same exception type will exist on different platforms, so deserialization must be done by the user.  Maybe there's a real need for this, even though it is not interoperable.  There are non-interoperable bindings, after all, so a non-interoperable Exception returning class might be justified.

     

    -James

     

  • Friday, May 09, 2008 8:11 PMJames Osborne - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    I talked to a PM who is familiar with this behavior.  Apparently, FaultContract<T> is intended to be used for custom types, not CLR types such as DivideByZeroException.  So, using FaultContract<T> when T is a clr type will generate unexpected results.  But if you stick to only custom types, it should work fine.

     

    -James

     

All Replies

  • Thursday, May 08, 2008 8:14 PMJames Osborne - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    At this point, it looks like a bug to me.  The code you posted above repros the issue just fine.  If this issue is blocking your deployment, please file a connect bug.  I'm notifying the product team of the bug so that it could be potentially fixed in the next release.

     

    https://connect.microsoft.com/default.aspx (search for WCF)

     

    -James

     

  • Friday, May 09, 2008 1:19 AMNgoc Luu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    If I mark operation contract is:

    [OperationContract]

    [FaultContract(typeof(DllNotFoundException))]

    [FaultContract(typeof(DivideByZeroException))]

    [FaultContract(typeof(Exception))]

    string Hello();

     

    FaultException<DivideByZeroException> is the exception that I alway received.

     

    But if I remove [FaultContract(typeof(DivideByZeroException))] from attributes of operation contract:

    [OperationContract]

    [FaultContract(typeof(DllNotFoundException))]

    [FaultContract(typeof(Exception))]

    string Hello();

     

    I received the correct exception - FaultException<Exception>, I wonder why the exception I alway received is FaultException<DivideByZeroException> but not FaultException<DllNotFoundException>.

    It's not only FaultException<DivideByZeroException>, but also my custom exception (such as: FaultException<MyBusinessException>).

     

    using System;

    using System.Runtime.Serialization;

    namespace ExceptionHandling

    {

    [Serializable]

    public class MyBusinessException : Exception

    {

    public MyBusinessException()

    {

    }

    public MyBusinessException(string message)

    : base(message)

    {

    }

    public MyBusinessException(string message, Exception innerException)

    : base(message, innerException)

    {

    }

    public MyBusinessException(SerializationInfo info, StreamingContext context)

    : base(info, context)

    {

    }

    }

    }

     

    If this is a bug, maybe I must find a workaround or another solution Sad

     

  • Friday, May 09, 2008 4:31 PMJames Osborne - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Yes, this is a product bug.  It looks like there's a class of exceptions that seem to "take over."  Custom Exceptions and DivideByZero are all I know of so far.  Is this blocking your deployment, or can you work around the issue?

     

    -James

     

  • Friday, May 09, 2008 4:32 PMJames Osborne - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Yes, this is a product bug.  Is this blocking your deployment, or can you work around this?

     

    -James

     

  • Friday, May 09, 2008 8:11 PMJames Osborne - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    I talked to a PM who is familiar with this behavior.  Apparently, FaultContract<T> is intended to be used for custom types, not CLR types such as DivideByZeroException.  So, using FaultContract<T> when T is a clr type will generate unexpected results.  But if you stick to only custom types, it should work fine.

     

    -James

     

  • Saturday, May 10, 2008 6:42 AMNgoc Luu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I tried with a custom exception class, I got the same result. Sad

     

    http://cid-b044e83441146203.skydrive.live.com/self.aspx/Public/TestWCF2.zip

     

  • Monday, May 12, 2008 4:33 PMJames Osborne - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    But you are still throwing a Exception, not your custom exception.  At this point, it is not advisable to have fault contracts handle non-custom exceptions.

     

    -James
  • Monday, May 12, 2008 4:38 PMJames Osborne - MSFT Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer

    As a side note, you might consider adding a suggestion through connect.microsoft.com about enhancing the FaultContract design in WCF to handle CLR exceptions.  The reason this wasn't implemented is mainly because of interoperability.  We can't guarantee the same exception type will exist on different platforms, so deserialization must be done by the user.  Maybe there's a real need for this, even though it is not interoperable.  There are non-interoperable bindings, after all, so a non-interoperable Exception returning class might be justified.

     

    -James

     

  • Thursday, May 15, 2008 4:07 AMNgoc Luu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    I resolved my problem by throwing a custom exception (called UnhandledException) instead of throwing Exception.

    Thank you so much Big Smile.

     

  • Friday, October 10, 2008 1:07 PMAnton Bogushevsky Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Proposed AnswerHas Code
    I see that this topic is very old but i hope that somebody will help me with my problem.
    I'm trying to handle custom exception on client side but client code is always catching FaultException instead of FaultException<T>. Here are the code samples:
    My custom exception:

    [Serializable] 
    public class MyException : Exception 
        public MyException (string message) : 
            base(message) 
        { 
        } 


    I've declared FaultContract for service operation:

    [OperationContract] 
    [FaultContract(typeof(MyException))] 
    void UpdateOrder(Order order); 

    Service operation code:

    public void UpdateOrder(Order order) 
        try 
        { 
            this.Facade.UpdateOrder(order); 
        } 
        catch (MyException ex) 
        { 
            throw new FaultException<MyException>(ex); 
        } 


    And, finally, a client code:

    using (WorkSchedulerServiceClient client = new WorkSchedulerServiceClient()) 
        try 
        { 
            client.UpdateOrder(orderForUpdate); 
        } 
        catch (System.ServiceModel.FaultException<MyException> ex) 
        { 
             MessageBox.Show(ex.Message); 
             return
        } 
        catch (System.ServiceModel.FaultException ex1) 
        { 
             throw ex1; 
        } 


    Using fault contracts with standard CLR types such as Exception or ApplicationException doesn't cause this problem - client catches correct FaultException<Exception>  or FaultException<ApplicationException>.
    Maybe i forget something? Please advise.
  • Thursday, November 06, 2008 4:38 AMAn Phu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Hi etwre64363,

    This is because MyException is missing a constructor that takes in the SerializationInfo and Streaming context.  
        [Serializable]  
        public class MyException : Exception  
        {  
            public MyException(string message): base(message) { }  
     
            public MyException(SerializationInfo info, StreamingContext context)  
                : base(info, context) { }  
        } 

    You should follow the design guidelines for custom exceptions.  One of these guidelines recommends you implement a common set of constructors.

    http://msdn.microsoft.com/en-us/library/ms229064(VS.80).aspx


    If you are using VS2008, there is a snippet that will jumpstart the custom exception code for you.

    Type "except" and the code snippet helper will popup and from there just hit the Tab key.

    I advocate throwing a soap fault type instead of a .Net exception for interoperability and security sake.

    My message fault.
     
        [DataContract]  
        public class ServiceFault  
        {  
            public ServiceFault(string message)  
            {  
                Message = message;  
            }  
     
            [DataMember]  
            public string Message {get;set;}  
        } 

    Service interface
        [ServiceContract()]  
        public interface IMyService  
        {  
            [FaultContract(typeof(ServiceFault))]   
            string Hello();  
        }  
     

    Service impl
            throw new FaultException<ServiceFault>(new ServiceFault("aaa"));  
     

    client
            catch (FaultException<ServiceFault> ex)  
            {  
                Response.Write(ex6.Detail.Message);  
     
                // cast the detail into a message fault.  
                //ServiceFault sf = ex6.Detail;  
                //Response.Write(sf.Message);  
            }  
     

    HTH,
    An



  • Thursday, November 06, 2008 4:45 AMAn Phu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
     Hi James,

    Just wanted to add in my observation.

    >there's a class of exceptions that seem to "take over."  Custom Exceptions and DivideByZero

    The errant behavior does not seem to be about one exception taking over another.  I have observed that regardless of whether it is a  custom exception or built-in exception, if you throw an Fault<Exception> in the service, the exception handler before the one that handles Fault<Exception> gets called.


    An