System.InvalidOperationException when reading from xml in WP8 - c#

This is a follow-up question from How to create an empty xml in Windows Phone 8.
I did this to create the xml:
public void create()
{
List<DataModel> __dataList = new List<DataModel>();
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = true;
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Data.xml", FileMode.Create))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<DataModel>));
using (XmlWriter xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
{
serializer.Serialize(stream, __dataList);
}
}
}
}
When I try to read it with this code, I get another System.InvalidOperationException
public void read()
{
List<DataModel> __dataList = new List<DataModel>();
try
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Data.xml", FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<DataModel>));
__dataList = (List<DataModel>)serializer.Deserialize(stream);
}
}
}
catch (Exception e)
{
string s = e.Message;
e.ToString();
}
}
The exception message is "There is an error in XML document (2, 118)." What is wrong with my code?
Edit: Inner exception is "Data at the root level is invalid. Line 2, position 118."
Edit 2: I read the contents of the xml using StreamReader.ReadToEnd() before deserializing and this is the return string:
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfDataModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
This is my first time working with xml, so the issue may be a simple one but I may not realise it. Any help?

Does the code below also give an error? And what is the construction of DataModel?
public void create()
{
List<DataModel> __dataList = new List<DataModel>();
//XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
//xmlWriterSettings.Indent = true;
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Data.xml", FileMode.Create))
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(List<DataModel>));
//using (XmlWriter xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
//{
serializer.Serialize(stream, __dataList);
//}
}
catch { }
}
}
}
public void read()
{
List<DataModel> __dataList = new List<DataModel>();
try
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("Data.xml", FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<DataModel>));
__dataList = (List<DataModel>)serializer.Deserialize(stream);
}
}
}
catch (Exception e)
{
string s = e.Message;
e.ToString();
}
}
And somewhere:
public class DataModel
{ }
That code above works for me.

Related

Reading from XML file in memory using XmlSerializer

I use code below to open zip archive in memory.
using (var leagueFile = File.OpenRead(openFileDialog.FileName))
using (var package = new ZipArchive(leagueFile, ZipArchiveMode.Read))
{
foreach (var team in package.Entries)
{
if (team.Name.EndsWith(".xml"))
{
_xmlHandler.Import<Player>(team.FullName, Encoding.UTF8);
//...
}
}
}
When I try to deserialize with my Import<T>() method, app crashes due to file wasn't found.
public T Import<T>(string fileName, Encoding encoding) where T : class, new()
{
var serializer = new XmlSerializer(typeof(T));
serializer.UnknownNode += serializer_UnknownNode;
serializer.UnknownAttribute += serializer_UnknownAttribute;
var reader = XmlReader.Create(new StreamReader(fileName, encoding));
var po = (T)serializer.Deserialize(reader);
return po;
}
The problem is that app is searching for fileName in the bin directory of application. Not in stream (?) of zip archive. Is there a way to do this with XmlSerializer class?
Modify your code as below:
using (var leagueFile = File.OpenRead(openFileDialog.FileName))
using (var package = new ZipArchive(leagueFile, ZipArchiveMode.Read))
{
foreach (var team in package.Entries)
{
if (team.Name.EndsWith(".xml"))
{
using(var xmlStream = team.Open())
{
_xmlHandler.Import<Player>(xmlStream, Encoding.UTF8);
//...
}
}
}
}
public T Import<T>(Stream input, Encoding encoding) where T : class, new()
{
var serializer = new XmlSerializer(typeof(T));
serializer.UnknownNode += serializer_UnknownNode;
serializer.UnknownAttribute += serializer_UnknownAttribute;
var reader = XmlReader.Create(input);
var po = (T)serializer.Deserialize(reader);
return po;
}

Saving XDocument to file in PCL C#

I'm working within my PCL library and need to serialise a class and output to a file. I'm very short on space, so don't have the space for PCLStorage.
Currently I'm using this for the serialisation. IFilePath returns a file path from the non-PCL part.
IFilePath FilePath;
public void SerializeObject<T>(T serializableObject, string fileName)
{
if (serializableObject == null) { return; }
try
{
using (var ms = new MemoryStream())
{
var xmlDocument = new XDocument();
using (var writer = xmlDocument.CreateWriter())
{
var serialize = new DataContractSerializer(typeof(T));
serialize.WriteObject(writer, serializableObject);
xmlDocument.Save(ms, SaveOptions.None);
}
}
}
catch (Exception ex)
{
//Log exception here
}
}
When I try to save, nothing is showing. I have a feeling it's because I'm not outputting the stream to a file, but I'm at a loss as how to do this.
You are trying to save to a file, an action which is specific for each platform.
PCLStorage is implementing this functionality for each platform and this is what you will have to do also if you can"t use it.
In you case what you have to do is to create the stream (in each platform) in your non pcl code and then pass it to your function which will look like this:
public void SerializeObject<T>(T serializableObject, Stream fileStream)
{
if (serializableObject == null) { return; }
try
{
var xmlDocument = new XDocument();
using (var writer = xmlDocument.CreateWriter())
{
var serialize = new DataContractSerializer(typeof(T));
serialize.WriteObject(writer, serializableObject);
xmlDocument.Save(fileStream, SaveOptions.None);
}
}
catch (Exception ex)
{
//Log exception here
}
}
more on pcl here.
Problem is that your variable ms in using (var ms = new MemoryStream()) is empty and does not point to any file location of which MemoryStream does not receive a filepath as argument. I propose you use a StreamWriter instead and pass the your FileStream to it. Example
Use your fileName to create a FileStream which inherits from the Stream class then replace the Memory stream with the newly created filestream like this.
using(FileStream stream = File.OpenWrite(fileName))
{
var xmlDocument = new XDocument();
using (var writer = xmlDocument.CreateWriter())
{
var serialize = new DataContractSerializer(typeof(T));
serialize.WriteObject(writer, serializableObject);
xmlDocument.Save(stream, SaveOptions.None);
}
}
Hope this helps.

How to Deserialize using binary Deserialization from file [duplicate]

This question already has an answer here:
How to Deserialize using binary Deserialization from file text file
(1 answer)
Closed 8 years ago.
public static void SaveRestaurantList(List<Restaurant> restaurantList)
{
FileStream fs = new FileStream("Restaurant.txt", FileMode.Create, FileAccess.Write);
BinaryFormatter bf = new BinaryFormatter();
for (int i = 0; i < restaurantList.Count; i++)
{
Restaurant r = new Restaurant();
r = (Restaurant)restaurantList[i];
bf.Serialize(fs, r);
fs.Flush();
}
fs.Close();
Console.WriteLine("\n\n\t\t File Get Serialized.., \n\t\t Close the Promt and Check in Application Debug Folder..!!");
}
I have Serailze the generic list which I have, into "Restaurant.txt" file.
now I want to Deserialize the same and return it into a Generic List, I have tried
but its not working and it is giving error "Invalid Cast Expression".
Can anyone please help in solving out this.
You should serialize the complete list itself.
using (Stream stream = File.Open("data.bin", FileMode.Create))
{
BinaryFormatter bin = new BinaryFormatter();
bin.Serialize(stream, restaurantList);
}
You can later deserialize the complete list like this
using (Stream stream = File.Open("data.bin", FileMode.Open))
{
BinaryFormatter bin = new BinaryFormatter();
var restaurantList=(List<Restaurant>)bin.Deserialize(stream);
}
Kapadni,
I am storing my list/BindingList of object in .xml file and may be below functions/code will help you to serialize and de-serialize object and store/retrieve from .xml file
BindingList<IntradayData> objIntradayDataList;
SerializeObject(objIntradayDataList, filepath);
objIntradayDataList = DeSerializeObject<BindingList<IntradayData>>(filepath);
public void SerializeObject<T>(T serializableObject, string fileName)
{
if (serializableObject == null) { return; }
try
{
XmlDocument xmlDocument = new XmlDocument();
XmlSerializer serializer = new XmlSerializer(serializableObject.GetType());
using (MemoryStream stream = new MemoryStream())
{
serializer.Serialize(stream, serializableObject);
stream.Position = 0;
xmlDocument.Load(stream);
xmlDocument.Save(fileName);
stream.Close();
}
}
catch (Exception ex)
{
//Log exception here
log.Error("SerializeObject ", ex);
}
}
public T DeSerializeObject<T>(string fileName)
{
if (string.IsNullOrEmpty(fileName)) { return default(T); }
T objectOut = default(T);
try
{
string attributeXml = string.Empty;
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(fileName);
string xmlString = xmlDocument.OuterXml;
using (StringReader read = new StringReader(xmlString))
{
Type outType = typeof(T);
XmlSerializer serializer = new XmlSerializer(outType);
using (XmlReader reader = new XmlTextReader(read))
{
objectOut = (T)serializer.Deserialize(reader);
reader.Close();
}
read.Close();
}
}
catch (Exception ex)
{
//Log exception here
log.Error("DeSerializeObject ", ex);
}
return objectOut;
}

IsolateStorage Issue in WP7

I am facing the problem regarding the following issue in wp7
"Type 'System.Windows.Media.Transform' cannot be serialized in C#"
When i call the below method to save my List data to isolated storage
SerializeHelper.SaveSetting("myfile.Xml",swaplist);
then then i am getting the exception.
public static class SerializeHelper
{
public static void SaveSetting<T>(string fileName, T dataToSave)
{
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
try
{
using (var stream = store.CreateFile(fileName))
{
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(stream, dataToSave);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message);
return;
}
}
}
}
I am attaching the screenshot of structure of list data
How to resolve this?
Thank you for adding the screenshot... and pasting some code. Can't really see anything wrong.
does you VM only expose public primitive / serialisable types ? I have in past used something like this to serialise to iso store.
public static void SaveObjectToStorage<T>(T ObjectToSave)
{
TextWriter writer;
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream fs = isf.OpenFile(GetFileName<T>(), System.IO.FileMode.Create))
{
writer = new StreamWriter(fs);
XmlSerializer ser = new XmlSerializer(typeof(T));
ser.Serialize(writer, ObjectToSave);
writer.Close();
}
}
}

Simultaneously writing and validating XML

I have a Write method that serializes objects which use XmlAttributes. It's pretty standard like so:
private bool WriteXml(DirectoryInfo dir)
{
var xml = new XmlSerializer(typeof (Composite));
_filename = Path.Combine(dir.FullName, _composite.Symbol + ".xml");
using (var xmlFile = File.Create(_filename))
{
xml.Serialize(xmlFile, _composite);
}
return true;
}
Apart from trying to read the file I have just written out (with a Schema validator), can I perform XSD validation WHILE the XML is being written?
I can mess around with memory streams before writing it to disk, but it seems in .Net there is usually an elegant way of solving most problems.
The way I've done it is like this for anyone interested:
public Composite Read(Stream stream)
{
_errors = null;
var settings = new XmlReaderSettings();
using (var fileStream = File.OpenRead(XmlComponentsXsd))
{
using (var schemaReader = new XmlTextReader(fileStream))
{
settings.Schemas.Add(null, schemaReader);
settings.ValidationType = ValidationType.Schema;
settings.ValidationEventHandler += OnValidationEventHandler;
using (var xmlReader = XmlReader.Create(stream, settings))
{
var serialiser = new XmlSerializer(typeof (Composite));
return (Composite) serialiser.Deserialize(xmlReader);
}
}
}
}
private ValidationEventArgs _errors = null;
private void OnValidationEventHandler(object sender, ValidationEventArgs validationEventArgs)
{
_errors = validationEventArgs;
}
Then instead of writing the XML to file, using a memory stream do something like:
private bool WriteXml(DirectoryInfo dir)
{
var xml = new XmlSerializer(typeof (Composite));
var filename = Path.Combine(dir.FullName, _composite.Symbol + ".xml");
// first write it to memory
var memStream = new MemoryStream();
xml.Serialize(memStream, _composite);
memStream.Position = 0;
Read(memStream);
if (_errors != null)
{
throw new Exception(string.Format("Error writing to {0}. XSD validation failed : {1}", filename, _errors.Message));
}
memStream.Position = 0;
using (var outFile = File.OpenWrite(filename))
{
memStream.CopyTo(outFile);
}
memStream.Dispose();
return true;
}
That way you're always validating against the schema before anything is written to disk.

Categories