none
Passing an exception object to a WCF service

    Question

  • Hi,

    I'm pretty new to WCF , as an experiment I was trying to create a WCF service wrapper over an exception handler class which is using the enterprise library underneath.

    I created a simple class with one exception variable, which gets exposed as the data contract

    when I try to pass the exception to the WCF service I get the following serialzation error

    There was an error while trying to serialize parameter http://tempuri.org/:ex. The InnerException message was 'Type 'System.Collections.ListDictionaryInternal' with data contract name 'ArrayOfKeyValueOfanyTypeanyType:http://schemas.microsoft.com/2003/10/Serialization/Arrays' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.  Please see InnerException for more details.

    I configured the app.config for the calling application by adding Syste.Exception as known type in the DataContractSerializer

      <system.runtime.serialization>
        <dataContractSerializer>
          <declaredTypes>
            <add type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
              <knownType type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">           
              </knownType>
            </add>
          </declaredTypes>
        </dataContractSerializer>
      </system.runtime.serialization>


    this didnt seem to work either, still getting the same error. Can any one please shed some light on this ?
    Monday, January 21, 2008 6:21 AM

Answers

  •  

    Have you tried XML Serialization as opposed to DataContract serialization?  See http://msdn2.microsoft.com/en-us/library/ms732038.aspx.   Exception is XML serializable and should be serializable in that way.  

     

    I should ask why you are trying to pass Exception objects as parameters.   In the decoupled architecture of WCF, that would not be the best way to transmit error information.   If you are in a .NET world only and you wish to preserve type fidelity between client and serve, you could use the NetDataContractSerializer (http://msdn2.microsoft.com/en-us/library/system.runtime.serialization.netdatacontractserializer.aspx) but that would also kill the decoupledness of WCF.

     

     

    Wednesday, January 23, 2008 6:01 PM
  • I'm no authority on this, but I think your design here has a flaw.

    In reality, what you should be considering a logging library such as log4net or Enterprise Library logging.

    "centralized repository for handling...exceptions" doesn't really make sense to me as a concept; it would make much more sense as a library that performed standardized error (integration with Enterprise Library, perhaps?) handling in conjuntion with a logging library which would output the exception information and details to multiple targets (including database targets or network endpoints).

    Seems like it would be a bad design choice from a performance perspective to have error handling handled by a remote component.  It seems like it would also be a liability when it comes to robustness since you are counting on a remote service to handle an error condition.
    Thursday, February 28, 2008 8:26 PM

All replies

  • I am researching the exact same problem

    "There was an error while trying to serialize parameter http://tempuri.org/:ex. The InnerException message was 'Type 'System.DivideByZeroException' with data contract name 'DivideByZeroException:http://schemas.datacontract.org/2004/07/System' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'.  Please see InnerException for more details."
    Wednesday, January 23, 2008 3:48 PM
  •  

    Have you tried XML Serialization as opposed to DataContract serialization?  See http://msdn2.microsoft.com/en-us/library/ms732038.aspx.   Exception is XML serializable and should be serializable in that way.  

     

    I should ask why you are trying to pass Exception objects as parameters.   In the decoupled architecture of WCF, that would not be the best way to transmit error information.   If you are in a .NET world only and you wish to preserve type fidelity between client and serve, you could use the NetDataContractSerializer (http://msdn2.microsoft.com/en-us/library/system.runtime.serialization.netdatacontractserializer.aspx) but that would also kill the decoupledness of WCF.

     

     

    Wednesday, January 23, 2008 6:01 PM
  • Thanks, I think this should resolve it.

    We are designing an SOA based system, so we have a lot of business services. we needed a central repository for handling and logging exceptions along with policies etc.

    we were trying out by creating a central WCF service that logs exceptions (and emails the code break etc.) instead of everyone implementing their own exception handling policies in their own services. Communication should all be .NET
    Thursday, January 24, 2008 7:13 AM
  • A collection of blog posts on WCF serialization
    http://weblogs.asp.net/avnerk/search.aspx?q=wcf+serialization&o=Relevance

    it seems WCF does not allow NameValueCollections by default
    Thursday, January 24, 2008 11:57 AM
  • I'm no authority on this, but I think your design here has a flaw.

    In reality, what you should be considering a logging library such as log4net or Enterprise Library logging.

    "centralized repository for handling...exceptions" doesn't really make sense to me as a concept; it would make much more sense as a library that performed standardized error (integration with Enterprise Library, perhaps?) handling in conjuntion with a logging library which would output the exception information and details to multiple targets (including database targets or network endpoints).

    Seems like it would be a bad design choice from a performance perspective to have error handling handled by a remote component.  It seems like it would also be a liability when it comes to robustness since you are counting on a remote service to handle an error condition.
    Thursday, February 28, 2008 8:26 PM
  • Thanks for the insight Charlie,

    your right about having to call a remote service just to log exceptions, we realized it before implementaiton.
    We're using EL 3.1 for logging exceptions locally for each of the service as well as the webclient
    Thursday, March 06, 2008 2:20 PM
  • Hi !

    Why do you need System.Exception in WCF knownType ? Even if your custom exception class do not inherit from System.Exeption
    it still is a type of Exception.

    what you need to do is put FaultContract Attribute on your operation contract signature and throw the exception of your custom type
    with new FaultException<[CustomException]>, Client side Catch Block of Catch{FaultException<[CustomException]>} will get executed.

    This is what the WCF framework has wrapped exceptions within FaultException and Fault Contracts. thanks to WCF team.

    Exception Class
    [Serializable]
    [DataContract]
            public class MyException
           {
    public string Message{get;set;} 

    public MyException(string message)
    {
    Message = message;
    }
    }

    Contract
     
    [OperationContract]
            [FaultContract(typeof(MyException))]
            string ExportSchema(string entityName);
            

    Service

              public string ExportSchema(string entityName)
            {
                throw new FaultException<MyException>(new MyException("Error"),

                                                                   new FaultReason("Error"));
            }



    Client


    try
    string s = proxy.ExportSchema("AA"); 
    catch(FaultException<SmartSolveException> ex1)      // This block will get executed....
    {

     } 
    catch (FaultException ex1)

    }





    Monday, November 17, 2008 4:48 AM
  • Hi Danish,

    please find below a sample which I am using to pass any .NET Exception from a .NET client to WCF Server.

    WCF Server side:

     

    public interface IService

    {

        [OperationContract]

        void LogException(byte[] exc);

    }

     

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////

    using System.Runtime.Serialization;

    using System.IO;

    public class Service : IService

    {

     

        public void LogException(byte[] exc)

        {

     

            Exception exception = (Exception)ToObject(exc);

     

            //Now, do what you want with the exception

            string stackTrace = exception.StackTrace;

            string message = exception.Message;

            Exception innerException = exception.InnerException;

        }

     

        public static object ToObject(byte[] serializedObject)

        {

            if (serializedObject == null)

            {

                return null;

            }

     

            using (MemoryStream dataInMemory = new MemoryStream(serializedObject))

            {

                return new NetDataContractSerializer().Deserialize(dataInMemory);

            }

        }

    }

     

     

    .NET Client side:

     

    using System.IO;

    using System.Runtime.Serialization;

     

            public void PublishException(System.Exception ex)

            {

                ServiceClient cl = new ServiceClient();           

     

                LogExceptionRequest excreq = new LogExceptionRequest();

                excreq.exc = ToBytes(ex);

     

                cl.LogException(excreq);

            }

     

            public static byte[] ToBytes(object value)

            {

                if (value == null)

                {

                    return null;

                }

     

                byte[] inMemoryBytes;

                using (MemoryStream inMemoryData = new MemoryStream())

                {

                    new NetDataContractSerializer().Serialize(inMemoryData, value);

                    inMemoryBytes = inMemoryData.ToArray();

                }

     

                return inMemoryBytes;

            }

     

     

      private void button1_Click(object sender, EventArgs e)

            {

                try {

                    int x = 0;

                    int y = 5 / x;

                }

                catch (System.Exception ex)

                {

                    PublishException(ex);

                }

     

            }

     

    Tuesday, May 25, 2010 9:05 AM
  • can you say what is LogExceptionRequest here?
    Friday, December 03, 2010 5:15 AM