13

I am developing a WCF service which will be consumed by multiple different client applications. In order to make one functionality work, the server needs to read an XML file into a C# DataContract which is then passed on to the concerned client. As far as I understand from the MSDN website, this is possible but I couldn't find any complete examples. In particular, the website talks about a 'stream' parameter which I don't quite get yet.

My data contract has one property field which is a list of another data contract which has multiple simple property fields.

e.g.

    [DataContract]
    public class MyClass1 {
        [DataMember]
        public string name;
        [DataMember]
        public int age;
    }

    [DataContract]
    public class MyClass2 {
        [DataMember]
        public List<MyClass1> myClass1List;
    }

My classes look something like this.

temelm
  • 826
  • 4
  • 15
  • 34

3 Answers3

15

Here is an example

MyClass1 obj = new MyClass1();
DataContractSerializer dcs = new DataContractSerializer(typeof(MyClass1));

using (Stream stream = new FileStream(@"C:\tmp\file.xml", FileMode.Create, FileAccess.Write))
{
    using (XmlDictionaryWriter writer = 
        XmlDictionaryWriter.CreateTextWriter(stream, Encoding.UTF8))
    {
        writer.WriteStartDocument();
        dcs.WriteObject(writer, obj);
    }
}

Books b = new Books();

DataContractSerializer dcs = new DataContractSerializer(typeof(Books));

try
{
    Stream fs = new FileStream(@"C:\Users\temelm\Desktop\XmlFile.xml", FileMode.Create, FileAccess.Write);

    XmlDictionaryWriter xdw = XmlDictionaryWriter.CreateTextWriter(fs, Encoding.UTF8);
    xdw.WriteStartDocument();
    dcs.WriteObject(xdw, b);
    xdw.Close();
    fs.Flush();
    fs.Close();
}
catch (Exception e)
{
    s += e.Message + "\n";
}
Richard Ev
  • 52,939
  • 59
  • 191
  • 278
Ventsyslav Raikov
  • 6,882
  • 1
  • 25
  • 28
  • @KirkWoll what does do? and what if I only want to append 1 element to the XML file? – temelm Jun 21 '12 at 16:29
  • [from metadata] - When overridden in a derived class, writes the XML declaration with the version "1.0". And this code writes only 1 object to the file, if that's what you mean. – Ventsyslav Raikov Jun 21 '12 at 16:31
  • it writes one object but that object is a list of other objects so it's fine. how about reading an existing XML document into a datacontract. any ideas? – temelm Jun 21 '12 at 18:06
  • Never mind, I got it both working. Thanks a lot, I appreciate it. :) – temelm Jun 21 '12 at 18:19
  • When I try to declare the FileStream and XmlDictionaryWriter without the 'using's it does not write the xml file. any ideas? – temelm Jun 21 '12 at 21:43
  • yes - the dispose/close methods flush the file back to disk, don't remove the usings – Ventsyslav Raikov Jun 22 '12 at 05:32
  • i understand that the using concept but i manually flush the FileStream and close it. still does not work. I am actually really curious why it doesn't work :D apart from the disposal is there something else done? – temelm Jun 22 '12 at 12:45
  • nope, are you sure you flush/close/dispose the writer and the stream in the same order as in my example? note there are 2 nested usings – Ventsyslav Raikov Jun 22 '12 at 15:18
  • I added a block of code at the end of the question. I am not closing the writer.. – temelm Jun 22 '12 at 15:29
  • yes, I added your code to the answer - you were missing the line to close the writer - you have to do this, otherwise the data you've written to it stays in its buffer and doesn't get flushed to the stream – Ventsyslav Raikov Jun 23 '12 at 07:16
2

This can be useful for you. When you need XElement. For instance when you going append node to XDocument or replece XElement of this document.

private XElement objectToXElement(SomeContractType obj)
        {
            DataContractSerializer dcs = new DataContractSerializer(typeof(SomeContractType);

            var ms = new MemoryStream();
            var xw = XmlWriter.Create(ms);
            dcs.WriteObject(xw, obj);
            xw.Flush();
            xw.Close();
            ms.Position = 0;
            XElement xe = XElement.Load(ms);

            return xe;
        }
trueboroda
  • 2,650
  • 26
  • 24
0

There is the NetDataContractSerializer which solves a whole bunch of problems when using WCF.

See here MSDN NetDataContractSerializer

It is typically used for wrapping all kinds of objects and pass it over WCF.

You can use it for wrapping objects into a byte[] and transport it over WCF, on the serverside, you can easily Deserialize the objects and do whatever you want with them.

Here is a discussion on how to use this Serializer correctly: MSDN Social

Code snippets are provided there also!

Liam
  • 27,717
  • 28
  • 128
  • 190
Mare Infinitus
  • 8,024
  • 8
  • 64
  • 113
  • 4
    WTF, a link to the GERMAN Microsoft site??? you probablye meant: http://msdn.microsoft.com/library/system.runtime.serialization.netdatacontractserializer.aspx – Luuk Dec 04 '15 at 08:13