59

I have the following WCF DataContract:

[DataContract]
public class Occupant
{
    private string _Name;
    private string _Email;
    private string _Organization;
    private string _Badge;

    public Occupant(string name, string badge, string organization)
    {
        Name = name;
        Badge = badge;
        Organization = organization;
    }

    public Occupant(string name, string badge)
    {
        Value = name;
        Key = badge;
    }

    [DataMember]
    public string Key
    {
        get { return _Name; }
        set { _Name = value; }
    }

    [DataMember]
    public string Value
    {
        get { return _Badge; }
        set { _Badge = value; }
    }

    [DataMember]
    public string Name
    {
        get { return _Name; }
        set { _Name = value; }
    }

    [DataMember]
    public string Email
    {
        get { return _Email; }
        set { _Email = value; }
    }

    [DataMember]
    public string Organization
    {
        get { return _Organization; }
        set { _Organization = value; }
    }

    [DataMember]
    public string Badge
    {
        get { return _Badge; }
        set { _Badge = value; }
    }
}

When I try to access this service via web browser (it is hosted on IIS), I am getting this error:

System.Runtime.Serialization.InvalidDataContractException: Type 'MyNamespace.Occupant' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute.

One of my methods is returning a List of type Occupant. Would this be causing it?

StuartLC
  • 104,537
  • 17
  • 209
  • 285
Justin
  • 6,373
  • 9
  • 46
  • 72

6 Answers6

116

Because you have provided one or more initializing constructors, you will also need to add a parameterless (default) constructor.

i.e. You need to add:

[DataContract]
public class Occupant
{
    // *** Needed only for Serialization
    public Occupant() {}
    ...

This is because the default constructor disappears when you add an explicit constructor.

[The issue isn't with the method returning List<Occupant>, since methods aren't serialized).]

Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • 1
    Despite the error, its moot whether DCS actually needs any constructor at all - see http://msdn.microsoft.com/en-us/magazine/cc163569.aspx and http://stackoverflow.com/questions/178645/how-does-wcf-deserialization-instantiate-objects-without-calling-a-constructor – StuartLC Apr 09 '12 at 17:50
  • 2
    Do we need a public parameterless constructor? Or private parameterless constructor will also work fine? – VCD Aug 04 '17 at 01:38
  • 7
    @VCD Private parameter-less constructor works. Just tried on .Net Framework 4.5 – Lionet Chen Aug 07 '17 at 05:23
  • 1
    I believe this is wrong if the serialization is done by DataContractSerializer ,as explained here https://stackoverflow.com/questions/1076730/datacontractserializer-doesnt-call-my-constructor and here https://learn.microsoft.com/en-us/archive/msdn-magazine/2006/august/service-station-serialization-in-windows-communication-foundation – Lombas Sep 30 '20 at 22:48
9

Try adding an empty constructor. Often times that will set off the serializer.

Rob Rodi
  • 3,476
  • 20
  • 19
5

You need a default parameterless constructor. I don't ever plan to actually use mine, so I added a summary for IntelliSense and throw a run-time exception to keep it from being used.

/// <summary>
/// parameterless default constructor only for serialization
/// </summary>
public MyClass() { throw new NotImplementedException("parameterless default constructor only for serialization"); }
Zack Peterson
  • 56,055
  • 78
  • 209
  • 280
2

You should add an empty parameter constructor to your datacontract class

rada
  • 21
  • 1
2

When you have NO setter by default, do these steps:

  1. Add parametreless constructor;
  2. And add private set at least.

This helps me.

Anton Semenov
  • 411
  • 5
  • 11
0

My guess would be because _Email is not initialized. You could set EmitDefaultValue to false and see if that helps:

[DataMember(EmitDefaultValue = false)]
public string Email
{
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184