0

I have a application that needs to serialize a custom object and send it to a windows service, the custom object contains 2 lists of custom objects and a dictionary of int, string. When i try to serialize the object I am getting the error message:

There was an error generating the XML document.

I've googled around and found that this is generally due to one of the datatypes not being setup for serialization correctly. So I've gone through and verified the serialization on all the custom classes and as far as I can tell it is setup correctly.

My question now is, are lists and dictionaries serializable by default or does something need to be done in order to serialize them? Or, is there a better way to serialize collections of custom objects to be passed between executables?

Edits:

Main Custom Class:

[Serializable]
class MoveInInfoRequest : ServerRequestData
{ }
[Serializable]
[XmlInclude(typeof(GetUnitTypesResponseData)), XmlInclude(typeof(VendorObj.RequiredFields)),
     XmlInclude(typeof(VendorObj.InsuranceChoice)), XmlInclude(typeof(VendorObj.ProrateSettings))]
public class MoveInInfoResponse : ServerResponseData
{
    public GetUnitTypesResponseData UnitTypesInfo
    { get; set; }
    public List<VendorObj.RequiredFields> RequiredFields 
    { get; set; }
    public Dictionary<int, String> RentalPeriods
    { get; set; }
    public List<VendorObj.InsuranceChoice> InsCoverageAmounts
    { get; set; }
    public VendorObj.ProrateSettings ProrateOptions
    { get; set; }
}

Sampple Sub class: the other two classes are set up similar to this just much longer but they only use default datatypes.

<Serializable(), DataContract([Namespace]:="*companyNamespace*")> _
Public Class InsuranceChoice
    Public Sub New()
    End Sub
    <DataMember()> _
    Public InsuranceChoiceID As Integer
    <DataMember()> _
    Public CoverageDescription As String
    <DataMember()> _
    Public Premium As Decimal
    <DataMember()> _
    Public ActualCoverageAmount As Decimal

End Class
Mike_OBrien
  • 1,395
  • 15
  • 34
  • 3
    Posting code would help getting an answer :) – Mihai Nov 07 '12 at 19:53
  • They are serializable, yes. As @Mihai said, code will help. – Yatrix Nov 07 '12 at 19:56
  • List and Dictionary are serializable without anything for you to do. Obviously, you are putting something in them that is not, or serializing something else which isn't. – LightStriker Nov 07 '12 at 20:00
  • the question wasn't code specific it was more for general reference because i couldn't find a direct answer through google. But I added the main class and one of the sub classes in case something glaring is wrong... – Mike_OBrien Nov 07 '12 at 20:00
  • `My question now is, are lists and dictionaries serializable by default or does something need to be done in order to serialize them` What and which fields/properties of it can be serialized depends on the serializer you use. No general rule. For ex, `Serializable` attribute is not needed for XmlSerializer and it is used only(?) by BinaryFormatter – L.B Nov 07 '12 at 20:13

2 Answers2

1

It depends on what you are trying to serialize them with. In particular, Dictionary objects are not serializable if you are using XmlSerializer, though they are if you are using DataContractSerializer. You should be fine to serialize a List.

If you would like an alternative to Xml serialization, you could serialize to JSON using Json.Net.

References:

Serialize Class containing Dictionary member

Serializing .NET dictionary

Why doesn't XmlSerializer support Dictionary?

http://theburningmonk.com/2010/05/net-tips-xml-serialize-or-deserialize-dictionary-in-csharp/

Community
  • 1
  • 1
nick_w
  • 14,758
  • 3
  • 51
  • 71
  • that makes sense since I was trying to short cut the rentalperiods object instead of writing a new class. Thanks for the links they made it much more clear as to why i was having trouble. – Mike_OBrien Nov 07 '12 at 21:11
1

This is quite a common problem when it comes to serialization.

A collection implementing IDictionary cannot be serialized

You could use a DataContractSerializer ,but a better solution (in my opinion) would be to create your own Dictionary class which doesn't inherit from IDictionary

An example of such a class can be found here

Once you've implemented the class in your solution, simply do this:

using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var response = new MoveInInfoResponse
            {
                RentalPeriods = new SerializableDictionary<int, string> 
                { { 1, "Period 1" }, { 2, "Period 2" } }
            };

            string xml = Serialize(response);
        }

        static string Serialize(Object obj)
        {
            var serializer = new XmlSerializer(obj.GetType());
            var settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true };

            using (var stream = new StringWriter())
            {
                using (var writer = XmlWriter.Create(stream, settings))
                    serializer.Serialize(writer, obj);
                return stream.ToString();
            }
        }
    }

    [Serializable]
    public class MoveInInfoResponse
    {
        public SerializableDictionary<int, String> RentalPeriods
        { get; set; }
    }
}

Generates the following XML file:

<MoveInInfoResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <RentalPeriods>
    <Item>
      <Key>
        <int>1</int>
      </Key>
      <Value>
        <string>Period 1</string>
      </Value>
    </Item>
    <Item>
      <Key>
        <int>2</int>
      </Key>
      <Value>
        <string>Period 2</string>
      </Value>
    </Item>
  </RentalPeriods>
</MoveInInfoResponse>
Community
  • 1
  • 1
Denys Wessels
  • 16,829
  • 14
  • 80
  • 120
  • Thanks for the work around. This may come in handy in the future. For this implementation it just makes more sense for the datamember in question to be its own class though. – Mike_OBrien Nov 07 '12 at 21:13