Serializing unsupported data types to ApplicationData.Current.RoamingSettings

USCloud

Today, while working on a new Windows 8 Store Application, I decided that I wanted to store some data in the RoamingSettings store for my application.  This is a handy way to store small bits of information that an application needs each time it starts up, and is also handy because Microsoft will “roam” that data across all of your machines that you log into that have the same application installed.  In this way, the user’s application configuration just magically shows up everywhere the user is.  It’s very cool, and is covered here (XAML/C# version) and here (HTML5/JS version) in awesome posts written by a couple of my buddies.

I did, however, run into a problem while using it.  I wanted to store a “List<MyAwesomeType>” which contained a nice little list of user data into the settings, as described in those posts.  However, when I did so, I ran into the following error:

WinRT information: Error trying to serialize the value to be written to the application data store.  Additional information: Data of this type is not supported.

So what’s up with that?  Well, it turns out that the functionality works for basic data types (strings, numbers, etc.), but the default serializer in play can’t handle more “complex” types like my generic list.  So, what to do?

Turns out, the answer is pretty simple.  Just build up a simple serializer / deserializer that can mangle my data into and out of a string (which is supported), and insert it into the Load/Save functionality stream.  So, I wrote two simple functions:

public static string SerializeToString(object obj)
{
   XmlSerializer serializer = new XmlSerializer(obj.GetType());
   using (StringWriter writer = new StringWriter())
   {
      serializer.Serialize(writer, obj);
      return writer.ToString();
   }
} 
public static T DeserializeFromString<T>(string xml)
{
   XmlSerializer deserializer = new XmlSerializer(typeof(T));
   using (StringReader reader = new StringReader(xml))
   {
      return (T)deserializer.Deserialize(reader);
   }
}

Now, in the SaveSettings flow, I can do something like this:

// verify that we have our roaming data container attached...
if (settingsRoaming == null)
   settingsRoaming = ApplicationData.Current.RoamingSettings;
settingsRoaming.Values["myData"] = SerializeToString(myData);

And in the LoadSettings flow, it looks like this:

// verify that we have our roaming data container attached...
if (settingsRoaming == null)
   settingsRoaming = ApplicationData.Current.RoamingSettings;
if (settingsRoaming.Values["myData"] != null)
   myData = (List<DataTypes.MyDataType>) DeserializeFromString<List<DataTypes.MyDataType>>(settingsRoaming.Values["myData"].ToString());
else
   myData = new List<DataTypes.MyDataType>(); // init to empty list if no roaming data...

Easy!  We serialize our data to an XML string which we save to the RoamingSettings and we deserialize it back from an XML string.  Works like a charm.

blogroll

social