Developing for Modern Windows

Tips, tricks, and guides for developing on modern Windows platforms

Serialize / Deserialize an Object to an XML File (Windows Universal apps 8.1)

WinRT’s built-in XML serialization makes it easy to save and load data in .xml files. This article will show you how to store an arbitrary object in an .xml file, and then how to load that data back. Typical uses for this would be saving game progress or storing a purchase order.

This technique will work for WinRT 8.1 apps, and is therefore compatible with Universal Windows/Windows Phone apps that target version 8.1.

Overview

We will create a class with two methods – one takes an object and stores the data from that object in an .xml file; the other loads object data from an .xml file.

As an example we’ll create a simple class to demonstrate saving and loading an object.

How to use this Code

You can add the XmlIO class to any WinRT project. The code inside is completely universal, so you can put it in the shared project of a Universal App.

Note: Because this code targets WinRT8.1 you’ll need Visual Studio 2013.

Once you have the XmlIO class in your project, just follow the example code for how to use it. You literally just call the relevant method to save or load .xml data.

Create the XmlIO Class

You can add this code to any project, so we won’t go through creating a new project for this. You can follow my Windows 8.1 Universal App Hello World article to create a new app.

Create a new class called XmlIO.cs. We’ll use this to hold the methods to save and load .xml files. For simplicity/laziness we’ll make our methods static and public. The save and load methods will also be asynchronous (so the UI doesn’t get held up while accessing the disk) and generic (they will work for any kind of object, not just the example given in this article).

For Universal apps, put this class in the Shared project.

The Code

Here is the code for the serialization class. It includes two methods – one to save an object to an .XML file and one to load an object out of an .XML file. Paste the following code into XmlIO.cs (replace all the default code):


using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Windows.Storage;

namespace XmlReadWriteUniversal
{

class XmlIO
{
public static async Task<T> ReadObjectFromXmlFileAsync<T>(string filename)
{
// this reads XML content from a file ("filename") and returns an object from the XML
T objectFromXml = default(T);
var serializer = new XmlSerializer(typeof(T));
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.GetFileAsync(filename);
Stream stream = await file.OpenStreamForReadAsync();
objectFromXml = (T)serializer.Deserialize(stream);
stream.Dispose();
return objectFromXml;
}

public static async Task SaveObjectToXml<T>(T objectToSave, string filename)
{
// stores an object in XML format in file called 'filename'
var serializer = new XmlSerializer(typeof(T));
StorageFolder folder = ApplicationData.Current.LocalFolder;
StorageFile file = await folder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
Stream stream = await file.OpenStreamForWriteAsync();

using (stream)
{
serializer.Serialize(stream, objectToSave);
}
}

}

}

The ReadObjectFromXmlFileAsync method takes a filename string as an argument. It opens the file and streams out the contents into the serializer, which converts the XML data into an object of the correct type. The SaveObjectToXml method does the opposite – streams an object data as XML into a file with the filename provided.

A few points

To keep the code simple I’ve left out some bits not specific to the task at hand:

  • These methods don’t contain any error handling, but you should in your final code.
  • You should check if a file exists before trying to open it.
  • I’ve hardcoded the folder to be ApplicationData.Current.LocalFolder. You may want to change this or implement subfolders. Be mindful of where you can and can’t access files in WinRT.
  • Some objects can’t be serialized, but as long as you don’t try anything too complex or weird everything will be OK.

Using it

You can add that class into any WinRT application.

To demonstrate how it works, create a simple class called Robot, which has a few properties of a typical robot.

Since the methods are generic you can, of course, use any objects already in your app.


public class Robot
{
public string Name { get; set; }
public string Model { get; set; }
public int Power { get; set; }
public List<String> Components { get; set; }
}

The following code can be put anywhere in your project (though because the code is asynchronous it needs to go in an async method). It will do the following:

  1. Create a new instance of Robot called ‘robot’ with some properties.
  2. Save the new Robot object to disk in a file called “robbie.xml”.
  3. Create a new instance of Robot called ‘robot2’, and populate it with the saved XML from “robbie.xml” so it has the same properties as ‘robot’.

 NOTE: You can look in your [user folder]\AppData\Local\Packages\[app package folder]\LocalState folder (on Windows – you’ll need a tool like Windows Phone Power Tools to view the file on a phone) to see the actual XML file.


Robot robot = new Robot()
{
    Name = "Robbie",
Components = new List() { "head", "torso", "antennae" },
Model = "RRR123",
Power = 345
};

await XmlReadWriteUniversal.XmlIO.SaveObjectToXml(robot, "robbie.xml");
Robot robot2 = await XmlReadWriteUniversal.XmlIO.ReadObjectFromXmlFileAsync("robbie.xml");

Note that you need to tell the save and read methods the type of object you are loading/saving in the <brackets>. This is because the methods are generic and can be used with different object types, but they need to know what kind of object they are working with when you call them.

What Next?

Before using this in an actual app you should add some error handling into the XmlIO methods, including checking if files exist before trying to access them. I left out error handling in this example to stay on the task at hand.

You can use the same techniques to read in data downloaded from a server or to retrieve data stored in your app package as well. For example in a game you could store each level as an .xml file.

Tags: , , , ,

5 Responses to “Serialize / Deserialize an Object to an XML File (Windows Universal apps 8.1)”

  1. Larry Maturo says:

    Thank you! It did the job for me. I was going crazy trying to get something to work. I was attempting to use strings instead of streams, and it just did not work. I spent days looking for a clue, and you gave me the entire solution in a really easy to use format.

  2. […] recently came upon a problem when serializing a class to XML using my standard serializing technique. It wouldn’t serialize a list of Vehicle […]

  3. Ventsislav Georgiev says:

    Robot robot2 = await XmlReadWriteUniversal.XmlIO.ReadObjectFromXmlFileAsync(“robbie.xml”);

    this call should be specifying the arguments explicitly so this is how it should be done:

    Robot robot2 = await XmlReadWriteUniversal.XmlIO.ReadObjectFromXmlFileAsync(“robbie.xml”);

  4. Anthony D says:

    Hi ,

    Thanks for sharing the code. Just one query related to data storage for the method shared.

    I am planing to make Windows App that will store substantial amount of data. What do you think the approach for data storage I should implement. Please suggest.

  5. Jan. says:

    Easy and works great. Thanks!

Leave a Reply

Your email address will not be published.