XmlSerialize a class and send it from client to server - c#

I have 2 clases:
public class products
{
public string category;
public string name;
public double price;
public string desc;
public string version;
public string logoURL;
public string imgURL;
public string prod;
public string Category
{
set { categorie = value; }
get { return category; }
}
and:
[Serializable()]
public class groupProducts
{
public products[] produse;
}
I want to XmlSerialize the groupProducts class and send the data from a server via TCP conection to a client!
I've tried something like:
groupProducts gp = new groupProducts();
XmlSerializer xmlSel = new XmlSerializer(typeof(groupProducts));
TextWriter txtStream = new StreamWriter("xmlStreamFile.xml");
xmlSel.Serialize(txtStream, gp);
txtStream.Close();
try
{
Stream inputStream = File.OpenRead("xmlStreamFile.xml");
// declaring the size of the byte array to the length of the xmlfile
msg = new byte[inputStream.Length];
//storing the xml file in the byte array
inputStream.Read(msg, 0, (int)inputStream.Length);
//reading the byte array
communicator[i].Send(msg);
}
but it when I Deserialize it on the client side - the XML file has some weird data in it!
Do you have any idea what could it be? What am I doing wrong?

1- To be safe I would use an encoding while opening StreamWriter
2- In inputStream.Read(msg, 0, (int)inputStream.Length); Read does't guarantee that you will get inputStream.Length bytes from stream. You have to check the returned value.
3- You don't need a temp file. Use MemoryStream
XmlSerializer xmlSel = new XmlSerializer(typeof(groupProducts));
MemoryStream m = new MemoryStream();
xmlSel.Serialize(m);
communicator[i].Send(m.ToArray());

Related

C# Deserialization automatically deserialize a String as a byte array to attribute via custom code?

I have a class with a byte array as an attribute as binary
[System.Xml.Serialization.XmlAttributeAttribute(DataType="hexBinary")]
public byte[] aValue {
get {
return this.aValueField;
}
set {
this.aValueField= value;
}
}
The data itself...for aValue...has a String inside in the XML file I am attempting to deserialize in certain files
.
To deserialize I do this:
XmlSerializer xml = new XmlSerializer(typeof(Data));
using (Stream reader = new FileStream(file, FileMode.Open))
{
config = (Data)xml.Deserialize(reader);
}
The problem is, the data in the XML file, it has a String there not a byte[] (but other files do have a valid byte[] too). I cannot change the input file data nor can I change the attribute to a String, it has to be a byte[] for other files processed. Is there a way to do a custom conversion during this deserialization process somehow during via code for just this field, if the input is a String, to do a Custom Conversion to byte[] using logic? That way it doesn't exception and not get the class.
If you can differentiate between the string and the byte[] in code, you can add another property to handle the serialization, and make aValue XmlIgnore so it won't be deserialized but it will still get set inside bValue set.
private string bValueField;
[System.Xml.Serialization.XmlIgnore]
public byte[] aValue { get; set; }
[System.Xml.Serialization.XmlAttribute("aValue")]
public string bValue
{
get
{
return bValueField;
}
set
{
if (value.Contains("string identifier here")) // i.e. it's not a byte[]
{
aValue = new byte[] { };
bValueField = value;
}
else // it's a byte[]
{
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream(Encoding.Unicode.GetBytes(value ?? "")))
{
aValue = (byte[])formatter.Deserialize(stream);
bValueField = "not a string";
}
}
}
}

How to save a C# Custom Class List<> to file stream?

I want to save a custom class List (C#) in file stream (in Unity3d). I've already done saving a [Serializable] class saving into memory using this code:
[Serializable]
public class GameData
{
public int Score_SR;
public float ChaseCredits_SR;
}
Following method for saving the data:
public void Save()
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/chaserace.cr");
// Save data here from local to orignal data path storage i.e /chaserace.cr
GameData data = new GameData();
data.Score_SR = Score;
data.ChaseCredits_SR = ChaseCredits;
// this take the "data" class data and write it to our "chaserace.cr" file
bf.Serialize(file , data);
file.Close();
}
And then use a method Load to load the data.
But, now I would like to save a List<> of a custom class "RawData". I've tried doing the same with a List, but could not do that. Maybe there will be an edit within the code that will work for a List<>.
Here is the class whose List I want to save to memory:
[Serializable]
public class RawData{
public string key;
public int level;
public string value;
public RawData(string key_,string value_,int level_){
key = key_;
level = level_;
value = value_;
}
}
When I try loading data, there is an Error:
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/chaserace.cr", FileMode.Open);
RawData rawData = (RawData)bf.Deserialize(file);
List<RawData> rawDataList=rawData; //Here is conversion error
file.Close();
you have to Parser to a List :
List<RawData> rawDataList = new List<RawData>() { rawData };
because rawData is a single object , But you want to conversion a List
for example :
int a = 1;
List<int> b = a; //Here will conversion error

UDP Packet to Class

I'm making a simple program that receive UDP Packets from another program and I want to cast this packet to a class.
I have a class :
public class Packet
{
public string MyFirstProperty {get; set;}
public string MySecondProperty {get; set;}
public string MyThirdProperty {get; set;}
public OtherObject[] ObjectArray {get; set}
}
The packet that I receive are bytes array. How can I transform the packet to a class. I've heard of marshalling but I'm not experienced enough to fully understand it.
What should I do.
Thank you.
To send an object from client to server (utilizing Json.Net) ; assuming you have already done your own research and have a working UDP client/server
Client site:
c1) Packet p = new Packet();
c2) //fill the properties
c3) string json = JsonConvert.SerializeObject(p);
c4) byte[] buf = Encoding.UTF8.GetBytes(json);
c5) Send *buf* to server
Server site:
s1) Receive data from client( call it *buf*)
s2) string json = Encoding.UTF8.GetString(buf); (must be equal to json at client site)
s3) Packet p = JsonConvert.DeserializeObject<Packet>(json);
s4) Tada........
Now you can use the same algorithm to send object from server to client
PS: As long as you can send and then receive the same byte array using UDP(c5 => s1), you can get the original object back.
You need to use Serialization and De-Serialization to convert back class objects from and to Byte Array.
Here is a sample example.
public class MyClass {
public int Id { get; set; }
public string Name { get; set; }
public byte[] Serialize() {
using (MemoryStream m = new MemoryStream()) {
using (BinaryWriter writer = new BinaryWriter(m)) {
writer.Write(Id);
writer.Write(Name);
}
return m.ToArray();
}
}
public static MyClass Desserialize(byte[] data) {
MyClass result = new MyClass();
using (MemoryStream m = new MemoryStream(data)) {
using (BinaryReader reader = new BinaryReader(m)) {
result.Id = reader.ReadInt32();
result.Name = reader.ReadString();
}
}
return result;
}
}
Link to MSDN for more on serialization

Object de-serializing from base64 in C#

I have a class as so
[Serializable]
public class ExternalAccount
{
public string Name { get;set;}
}
I have converted this to JSON like so
{\"Name\":\"XYZ\"}
I have then base64 encoded the JSON string
I then send across the wire to a web api service
I receive the base64 encoded string and now need to de-serialize it back to the original object as above (ExternalAccount) so i firstly do a
byte[] byteArray = Convert.FromBase64String(base64EncodedExternalAccount);
What is the next step?
I have tried the below but this returns null...
using (MemoryStream memoryStream = new MemoryStream(byteArrayToConvert))
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
// set memory stream position to starting point
memoryStream.Position = 0;
// Deserializes a stream into an object graph and return as a object.
return binaryFormatter.Deserialize(memoryStream) as ExternalAccount;
}
Any pointers/tips greatly appreciated.
You can try converting the byte array back to string (it will be the same JSON you sent), then deserialize to the ExternalAccount object. Using the Newtonsoft JSON library the following sample correctly displays "Someone" on the console:
class Program
{
static void Main(string[] args)
{
var account = new ExternalAccount() { Name = "Someone" };
string json = JsonConvert.SerializeObject(account);
string base64EncodedExternalAccount = Convert.ToBase64String(Encoding.UTF8.GetBytes(json));
byte[] byteArray = Convert.FromBase64String(base64EncodedExternalAccount);
string jsonBack = Encoding.UTF8.GetString(byteArray);
var accountBack = JsonConvert.DeserializeObject<ExternalAccount>(jsonBack);
Console.WriteLine(accountBack.Name);
Console.ReadLine();
}
}
[Serializable]
public class ExternalAccount
{
public string Name { get; set; }
}
you need to extract string from the bytes you recieve.
byte[] byteArray = Convert.FromBase64String(base64EncodedExternalAccount);
string AccountInfo = System.Text.Encoding.UTF8.GetString(byteArray );
As expected, you will get {\"Name\":\"XYZ\"} in your AccountInfo string. Now you need to Deserialize. you can use the same model, ExternalAccount. you may do something like:
ExnternalAccount model = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<ExnternalAccount>(AccountInfo );

Multiple root element (DataContractSerializer)

I'm trying to deserialize file by using DataContractSerializer. I have such class:
[DataContract]
public class kontenerUstawienia
{
[DataMember]
public int[] stanGry;
[DataMember]
public int maxSize;
[DataMember]
public int[] stanOpcji;
[DataMember]
public int numerFlagi1;
[DataMember]
public int numerFlagi2;
public kontenerUstawienia()
{
}
(...)
}
Inside, after saving serialized class instance to the file, I read the file and try to deserialize:
try
{
zapiszObiektUstawien((kontenerUstawienia)deserializer.ReadObject(strumien));
}
catch (SerializationException e)
{
System.Diagnostics.Debug.WriteLine("\n\n\n\n++++++\n" +
e.Message
+ "\n+++++++++++++++++++++++++++++++++++++++++++++++");
}
catch prints me:
++++++
There was an error deserializing the object of type
WindowsPhoneGame1.kontenerUstawienia. There are multiple root elements. Line 1,
position 599.
+++++++++++++++++++++++++++++++++++++++++++++++
What am I doing wrong?
EDIT:
Here is code that I serialize and save:
public void zapiszDoPliku(string sciezkaDoPliku, IsolatedStorageFile katalog)
{
IsolatedStorageFileStream strumien = katalog.CreateFile(sciezkaDoPliku); // tworzenie pliku
MemoryStream ms = new MemoryStream();
StreamReader r = new StreamReader(ms);
DataContractSerializer serializer = new DataContractSerializer(typeof(kontenerUstawienia));
serializer.WriteObject(ms, this);
ms.Position = 0;
string daneDoZapisania = r.ReadToEnd();
byte[] bytes = Encoding.Unicode.GetBytes(daneDoZapisania);
strumien.Write(bytes, 0, bytes.Length);
ms.Close();
strumien.Close();
}
EDIT2:
File saved:
File is here
Are you sure that the file was empty before writing?

Categories