views:

125

answers:

5

I'm reading up on serialization, and have so far been messing with BinaryFormatter and SoapFormatter. So far, so good - and everything have both Serialized and Deserialized perfectly.

However, when I try the code below, I would expect my datafile to NOT contains the info for Name - and it does. Why would it contain that, when I specify SoapIgnore on the field?

I also tried with SoapAttribute("SomeAttribute") on the Age-field, and that didn't make any difference either. The framework version is set to 2.0, but the same thing happens in 3.5 and 4.0.

using System;
using System.Runtime.Serialization.Formatters.Soap;
using System.IO;
using System.Xml.Serialization;

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        p.Age = 42;
        p.Name = "Mr Smith";

        SoapFormatter formatter = new SoapFormatter();
        FileStream fs = new FileStream(@"c:\test\data.txt", FileMode.Create);

        formatter.Serialize(fs, p);
    }
}

[Serializable]
class Person
{
    public int Age;
    [SoapIgnore]
    public string Name;
}
+1  A: 

Because serialization and SOAP aren't the same. You have Name marked as public, so the serializer will serialize/deserialize it. If you want it not to appear in a serialization you should change its protection level to protected.

Joel Etherton
This isn't only way to ignore some fields during serialization.
Bart
There is a SoapFormatter which is designed to serialized data. I'm not talking about a webservice soap envelope.The MSDN it self states the following about SoapFormatters:"Serializes and deserializes an object, or an entire graph of connected objects, in SOAP format."
Peter Olsen
@Bart, @Peter Olsen - I read a little more into your question and some of the responses, and my "answer" isn't complete or accurate. I was tempted to delete it, but that would deprive potential downvoters of a clear and present opportunity.
Joel Etherton
+9  A: 

Use [NonSerialized] instead of [SoapIgnore]

Furthermore, this is an older (and aging) API. Not directly wrong but be sure to read up on XmlSerialization and ProtoBuf as well.

And be careful not to mix the API's up. Serialization is part of SOAP communication but not the same. SoapAttribute is not involved in bare Serialization.

Henk Holterman
Nope. Not correct.[NonSerialized] is for the BinaryFormatter.[SoapIgnore] is for the SoapFormatter.[XmlIgnore] is for the XmlSerializer.
Peter Olsen
@Peter: Are you sure? From MSDN: When using the BinaryFormatter or SoapFormatter classes to serialize an object, use the NonSerializedAttribute attribute ...., http://msdn.microsoft.com/en-us/library/system.nonserializedattribute.aspx
Henk Holterman
@Peter: According to the docshttp://msdn.microsoft.com/en-us/library/system.xml.serialization.soapattributes.soapignore.aspx [SoapIgnore] is for the XMLSerializer, not the SoapFormatter
w69rdy
Actually, I'd stay away from the XML Serializer as well, unless you require control over the exact format of the XML. It's in the process of being dropped, along with ASMX web services.
John Saunders
So how would I go about serializing an object either through BinaryFormatter, SoapFormatter or XmlSerializer, where I have control over which fields is serialized? The only way seems to be implemented ISerializable - and that might be a TAD overkill.
Peter Olsen
OK @John, thanks for the tip. Do you have a link for the ASMX state of affairs?
Henk Holterman
@Peter: That might be a good (new) question actually.
Henk Holterman
I found a solution - I answered it below. It seems that the SoapFormatter uses NonSerialized just like the BinaryFormatter does.
Peter Olsen
And it seems that the MS Press book I'm reading is wrong, in listing SoapIgnore and SoapAttribute alongside SoapFormatters.
Peter Olsen
@Henk: no single link, unfortunately. The strongest hint is in Ed Pinto's reply to https://connect.microsoft.com/VisualStudio/feedback/details/362727/xsd-exe-incorrect-class-generated-for-abstract-type-with-derived-types. That and the fact that ASMX web services are replaced by WCF, and XML Serialization has only limited applicability to WCF.
John Saunders
A: 

Have a look at this question: http://stackoverflow.com/questions/2283482/applying-soapignore-attribute-doesnt-take-any-effect-to-serialization-result/2285142#2285142

Chris Conway
The answer to that question states, that the SoapIgnore attribute is only for webservices. My question origins from reading the MS Press book for 70-536, where it clearly states that SoapIgnore and SoapAttribute works in union with SoapFormatter for serializing objects.
Peter Olsen
Right, but those books are notorious for having mistakes in them. Have you checked the book corrections page to see if it's listed? http://www.microsoft.com/learning/en/us/training/format-books-support.aspx#tab2
Chris Conway
+1  A: 

From the docs it states that the [SoapIgnore] attribute tells the XMLSerializer not to serialize this property, and it doesn't mention the SoapFormatter so I assume it doesn't apply to it, even though the name suggests it does

w69rdy
If I use an XmlSerializer, and use the [SoapIgnore] attribute, it serializes the field. If I change the attribute to [XmlIgnore] it correctly ignores the field.It just makes no sense, that there is no way to tell the serializer, that a given public field shouldn't be serialized. Lets say that I have string firstname, lastname, fullname, and fullname is in the ctor set to firstname +" "+ lastname. Why would I then want to serialize fullname? But I need fullname to be public.
Peter Olsen
Ok does [NonSerialized] work as @Henk suggested?
w69rdy
@w69rdy: [NonSerialized] seems to make the SoapFormatter ignore the field.
Peter Olsen
+1  A: 

The following code works. It seems that the SoapFormatter uses the same attributes as the BinaryFormatter does - the [NonSerialized] attribute. This however goes against what the MS Press book I'm reading states. It lists SoapIgnore, SoapAttribute and others as attributes that works with the SoapFormatter when serializing data.

This code creates two files, none of them having the Name-field.

using System;
using System.Runtime.Serialization.Formatters.Soap;
using System.IO;
using System.Xml.Serialization;

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person();
        p.Age = 42;
        p.Name = "Mr Smith";

        FormatSoap(p);
        FormatXml(p);
    }

    private static void FormatXml(Person p)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(Person));
        FileStream fs = new FileStream(@"c:\test\xmldata.txt", FileMode.Create);

        serializer.Serialize(fs, p);
    }

    private static void FormatSoap(Person p)
    {
        SoapFormatter formatter = new SoapFormatter();
        FileStream fs = new FileStream(@"c:\test\soapdata.txt", FileMode.Create);

        formatter.Serialize(fs, p);
    }
}

[Serializable]
public class Person
{
    public int Age;
    [XmlIgnore]
    [NonSerialized]
    public string Name;
}
Peter Olsen
Of course this doesn't mean I can alter how I want the resulting soapenvelope to be created - setting some values to soap-attributes and renaming other fields.
Peter Olsen
@Peter: which book, and when was it published?
John Saunders
@John: It's the Self Paced Training Kit for the 70-536 exam (.Net Application Development Foundation). It's even the second edition from 2009.
Peter Olsen
@Peter: which version of .NET is the exam for?
John Saunders
@Peter: BTW, just read the code and have to downvote you for not using `using` blocks around the FileStream's.
John Saunders
@John hehe, the code isn't productioncode or anything - it was just to make a simple example. The exam is for 2.0.
Peter Olsen
Compensation vote for improper use of the apostrophe.
Hans Passant
The way the code works directly goes against what the MS Press book says? Shocking...
Chris Conway
+1 for _not_ cluttering it up with using blocks.
Henk Holterman
@Peter: non-production, example code is copied by those who don't know what production code looks like, and is actually used. Fix it and I'll remove the -1.
John Saunders
@John: should all SO answers be copy-pate ready or focus on the problem as clear as possible?
Henk Holterman
@Henk: I compromise on that by downvoting lack of `using` blocks, missing any locking, and use of `new XmlTextReader()/XmlTextWriter()`These are cases that I've seen used in real code; when asked, the devs have said, "but I got it from an example".
John Saunders
@Henk: also, anyone who says, "use WSE".
John Saunders
@John, uhhh WSE in this context = ??
Henk Holterman
@Henk: i was enumerating my reasons for auto downvotes. WSE is a very obsolete web service technology replaced by WCF
John Saunders
OK, _that_ WSE.
Henk Holterman