Hi I have a service contract and in its implementation I am trying to write the request parameters it receives in a text file. Here a composite object of 'TypeA a' is passed as a parameter.
namespace WebService
{
// NOTE: If you change the interface name "IRequestStatusChanged" here, you must also update the reference to "IRequestStatusChanged" in App.config.
[ServiceContract]
public interface IRequestStatusChanged
{
[OperationContract]
Input StatusChanged(Input In);
}
[Serializable] [DataContract]
public class Input
{
[DataMember]
RequestStatus RS = new RequestStatus();
}
[Serializable] [DataContract]
public class RequestStatus
{
[DataMember]
RequestToken RT = new RequestToken();
[DataMember]
public String State
}
[Serializable] [DataContract]
public class RequestToken
{
[DataMember]
public string Id;
}
}
Implementation of contract
namespace WebService
{
// NOTE: If you change the class name "RequestStatusChanged" here, you must also update the reference to "RequestStatusChanged" in App.config.
public class RequestStatusChanged : IRequestStatusChanged
{
public Input StatusChanged(Input In)
{
/* IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
Stream outfile = new FileStream(@"C:\test.txt", FileMode.Open,FileAccess.Write);
formatter.Serialize(outfile, In);
outfile.Close(); */
XmlSerializer serializer = new XmlSerializer(typeof(Input));
TextWriter TW = new StreamWriter(@"c:\test.xml");
serializer.Serialize(TW, In);
TW.Close();
return In;
}
}
}
earlier I tried IFORMATTER to serialize the object and write it to text file but it is not human readable, so I tried xml serialization.
When I check the XML file written it only has tags for 'TypeA' object and does not write 'TypeB' and 'TypeC' objects to the file. I have marked all the classes as [Serializable] in the service contract. I want to write all the parameters received in the text or xml format to a file so that they are readable (kind of a log file).
The types 'TypeB' and 'TypeC' aren't written to the files because they're not necessary - when the serializer is serializing or deserializing an instance of TypeA, it knows that the type of the member 'b' is TypeB
, so it doesn't write the type information. Do you need this information as well? Since you're serializing a TypeA
, and you know that the field b
is of type TypeB
, you don't need that extra information in the log file.
In all serializers used by WCF, the only one which you can "force" the type to be written all the time is the JSON serializer - but then you'll get the result as JSON, not as XML - see below.
public class StackOverflow_6666697
{
[DataContract]
public class TypeA { [DataMember] public TypeB b = new TypeB(); }
[DataContract]
public class TypeB { [DataMember] public TypeC c = new TypeC(); }
[DataContract]
public class TypeC { [DataMember] public string S1; }
public static void Test()
{
MemoryStream ms = new MemoryStream();
XmlWriterSettings ws = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
OmitXmlDeclaration = true,
Encoding = Encoding.UTF8
};
TypeA instance = new TypeA { b = new TypeB { c = new TypeC { S1 = "Hello world" } } };
XmlWriter w = XmlWriter.Create(ms, ws);
new XmlSerializer(typeof(TypeA)).Serialize(w, instance);
w.Flush();
Console.WriteLine("XmlSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = XmlWriter.Create(ms, ws);
new DataContractSerializer(typeof(TypeA)).WriteObject(w, instance);
w.Flush();
Console.WriteLine("DataContractSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = XmlWriter.Create(ms, ws);
new NetDataContractSerializer().WriteObject(w, instance);
w.Flush();
Console.WriteLine("NetDataContractSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8);
new DataContractJsonSerializer(typeof(TypeA), null, 65536, false, null, true).WriteObject(w, instance);
w.Flush();
Console.WriteLine("DataContractJsonSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
}
Another option (which I really don't advise, as you'd be changing the logic of your system for the sake of logging) would be to declare the fields as object
. This way, since the declared type is different than the actual one, the type information will be written out - see below.
public class StackOverflow_6666697
{
[DataContract]
public class TypeA { [DataMember] public object b = new TypeB(); }
[DataContract]
public class TypeB { [DataMember] public object c = new TypeC(); }
[DataContract]
public class TypeC { [DataMember] public string S1; }
public static void Test()
{
MemoryStream ms = new MemoryStream();
XmlWriterSettings ws = new XmlWriterSettings
{
Indent = true,
IndentChars = " ",
OmitXmlDeclaration = true,
Encoding = Encoding.UTF8
};
TypeA instance = new TypeA { b = new TypeB { c = new TypeC { S1 = "Hello world" } } };
XmlWriter w = XmlWriter.Create(ms, ws);
new XmlSerializer(typeof(TypeA), new Type[] { typeof(TypeB), typeof(TypeC) }).Serialize(w, instance);
w.Flush();
Console.WriteLine("XmlSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = XmlWriter.Create(ms, ws);
new DataContractSerializer(typeof(TypeA), new Type[] { typeof(TypeB), typeof(TypeC) }).WriteObject(w, instance);
w.Flush();
Console.WriteLine("DataContractSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = XmlWriter.Create(ms, ws);
new NetDataContractSerializer().WriteObject(w, instance);
w.Flush();
Console.WriteLine("NetDataContractSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
ms.SetLength(0);
w = JsonReaderWriterFactory.CreateJsonWriter(ms, Encoding.UTF8);
new DataContractJsonSerializer(typeof(TypeA), new Type[] { typeof(TypeB), typeof(TypeC) }, 65536, false, null, true).WriteObject(w, instance);
w.Flush();
Console.WriteLine("DataContractJsonSerializer:");
Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray()));
}
}