Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I use WCF DataContract and ISerializable on the same class?

I have a class that I need to be able to serialize to a SQLServer session variable and be available over a WCF Service. I have declared it as follows

namespace MyNM
{
[Serializable] 
[DataContract(Name = "Foo", Namespace = "http://www.mydomain.co.uk")]

public class Foo : IEntity, ISafeCopy<Foo>
{
    [DataMember(Order = 0)] 
    public virtual Guid Id { get; set; }

    [DataMember(Order = 1)] 
    public virtual string a { get; set; }

    DataMember(Order = 2)]
    public virtual Bar c { get; set; }

    /* ISafeCopy implementation */
}


[Serializable]
[DataContract(Name = "Bar ", Namespace = "http://www.mydomain.co.uk")]
public class Bar : IEntity, ISafeCopy<Bar>
{
    #region Implementation of IEntity

    DataMember(Order = 0)]
    public virtual Guid Id { get; set; }
    [DataMember(Order = 1)]
    public virtual Baz y { get; set; }

    #endregion

    /* ISafeCopy implementation*/
}


[Serializable]
[DataContract]
public enum Baz
{
    [EnumMember(Value = "one")]
    one,
    [EnumMember(Value = "two")]
    two,
    [EnumMember(Value = "three")]
    three
}

But when I try and call this service, I get the following error in the trace log.

"System.Runtime.Serialization.InvalidDataContractException: Type 'BarProxybcb100e8617f40ceaa832fe4bb94533c' cannot be ISerializable and have DataContractAttribute attribute."

If I take out the Serializable attribute, the WCF service works, but when the object can't be serialized to session. If I remove the DataContract attribute from class Bar, the WCF service fails saying

Type 'BarProxy3bb05a31167f4ba492909ec941a54533' with data contract name 'BarProxy3bb05a31167f4ba492909ec941a54533:http://schemas.datacontract.org/2004/07/' 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

I've tried adding a KnownType attribute to the foo class

[KnownType(typeof(Bar))]

But I still get the same error.

Can anyone help me out with this?

Many thanks

Dave

like image 603
Dave Avatar asked Mar 17 '10 10:03

Dave


People also ask

Is Datacontract mandatory in WCF?

No, the DataContractAttribute is not required - WCF will infer serialization rules.

Why Datacontract is used in WCF?

It defines the structure and types of data exchanged in service messages. It maps a CLR type to an XML Schema. It defines how data types are serialized and deserialized. Through serialization, you convert an object into a sequence of bytes that can be transmitted over a network.

What is DataContract and datamember in c#?

A datacontract is a formal agreement between a client and service that abstractly describes the data to be exchanged. In WCF, the most common way of serialization is to make the type with the datacontract attribute and each member as datamember.

What is KnownType in WCF?

The [KnownType] attribute informs the WCF service that "it is ok" to receive this Admin type because it is a subclass of the awaited UserAccount type. It is especially important when the Admin subclass has more properties, like a public string AdminEmail { get;set; } . This property will be sent by the client too.


2 Answers

This question on MSDN might help: DataContract versus Serializable.

The accepted answer from that thread:

  1. [DataContract] and [Serializable] can be used together.

  2. DataContractSerializer understands both of them. If the type is marked with both of them, it will take the projection of [DataContract]

  3. Here are the docs on data transfer and serialization in WCF which provide a lot of detail on the serializers and known type: Data Transfer and Serialization

like image 84
Anders Abel Avatar answered Sep 21 '22 08:09

Anders Abel


I know this is very late, but in case anyone reads this, we had a similar issue. Our solution to leave the DataContract as is so WCF serialized fine, and then when we serialized to the SQL Server session, we serialized the object to JSON and wrote that to the session.

like image 21
jeff.eynon Avatar answered Sep 23 '22 08:09

jeff.eynon