none
Why can a type not implement ISerializable and have a DataContract attribute?

    Question

  • Hello everybody

    I tried to define a custom exception within my webservice which I can also use to throw with FaultException<T>. In order to be able to throw it with FaultException<T>, I have to mark it with the DataContract attribute like this:

    [DataContract]
    public class MyCustomException :
    Exception
    {
      ...
    }

    But after accessing the webservice, I get the following error:

    An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
    System.InvalidOperationException: An exception was thrown in a call to a WSDL export extension: System.ServiceModel.Description.DataContractSerializerOperationBehavior
    contract:
    http://tempuri.org/MyWebservice:IMyWebservice ----> System.Runtime.Serialization.InvalidDataContractException: Type 'MyWebservice.MyCustomException' cannot be ISerializable and have DataContractAttribute attribute.

    Why isn't this possible?

    Thursday, January 11, 2007 4:27 PM

Answers

  • Sowmy explains why WCF disallows the mixing of interface serialization programming model (ISerializable or IXmlSerializable) with attribute-based ones on http://blogs.msdn.com/sowmy/archive/2006/05/14/597476.aspx.

    For your scenario, you don't need to put the [DataContract] attribute in your class - WCF supports ISerializable types as well (System.Exception implements ISerializable). What you need to do is to follow the ISerializable contract described in http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimeserializationiserializableclasstopic.asp and add a constructor for this interface:

    "The ISerializable interface implies a constructor with the signature Constructor(SerializationInfo info, StreamingContext context). At deserialization time, the current constructor is called only after the data in the SerializationInfo has been deserialized by the formatter. In general this constructor should be protected if the class is not sealed (NotInheritable in Visual Basic) ."

    For example:

    public class MyCustomException : Exception
    {
        private string myValue;
        public MyCustomException(string myValue)
        {
            this.myValue = myValue;
        }
        protected MyCustomException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
            myValue = info.GetString(
    "myValueKey");
        }
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue(
    "myValueKey", myValue);
        }
    }

     

    Thursday, January 11, 2007 5:45 PM

All replies

  • Sowmy explains why WCF disallows the mixing of interface serialization programming model (ISerializable or IXmlSerializable) with attribute-based ones on http://blogs.msdn.com/sowmy/archive/2006/05/14/597476.aspx.

    For your scenario, you don't need to put the [DataContract] attribute in your class - WCF supports ISerializable types as well (System.Exception implements ISerializable). What you need to do is to follow the ISerializable contract described in http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemruntimeserializationiserializableclasstopic.asp and add a constructor for this interface:

    "The ISerializable interface implies a constructor with the signature Constructor(SerializationInfo info, StreamingContext context). At deserialization time, the current constructor is called only after the data in the SerializationInfo has been deserialized by the formatter. In general this constructor should be protected if the class is not sealed (NotInheritable in Visual Basic) ."

    For example:

    public class MyCustomException : Exception
    {
        private string myValue;
        public MyCustomException(string myValue)
        {
            this.myValue = myValue;
        }
        protected MyCustomException(SerializationInfo info, StreamingContext context) : base(info, context)
        {
            myValue = info.GetString(
    "myValueKey");
        }
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue(
    "myValueKey", myValue);
        }
    }

     

    Thursday, January 11, 2007 5:45 PM
  • Hi,

    I’ve got similar problem with the same result. 

    I implemented ISerializable “interface” and got next exception:

     

    System.InvalidOperationException: An exception was thrown in a call to a WSDL export extension: System.ServiceModel.Description.DataContractSerializerOperationBehavior
     contract: http://tempuri.org/:IMyService ----> System.Runtime.Serialization.InvalidDataContractException: Type 'MyCompany.Common.Exceptions.MyCompanyValidationException' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute.

     

    I really want to avoid creating dummy container for each exception in my solution.

     

    Any ideas?

     

    Monday, August 27, 2007 6:00 AM
  • You should mark your exception class with the [Serializable] attribute, if you want to transfer it between client and server.

     

    Some additional detail: the ISerializable interface defines how a class should serialize/deserialize itself by adding/getting members to/from a dictionary. But (it's been like that for ages, WCF had to maintain the design or risk breaking backward compatibility) it doesn't make a class serializable. In order to do that, you need to apply the [Serializable] attribute to it.

     

    Monday, August 27, 2007 5:15 PM
  • I have the exact same problem!

    When I use the [DataContract] attribute, I get the fallowing  exception: Type  ... cannot be ISerializable and have DataContractAttribute attribute.

    I do not want to use  ISerializable  in my WCF service, instead I want to use [DataContract].

    If I add [Serializable] then it works fine?
    • Proposed as answer by metril Tuesday, October 12, 2010 12:15 AM
    Wednesday, October 24, 2007 10:21 AM