Upgrading from the IsolatedStorageSettings to ApplicationData.LocalSettings

When Windows Phone 7 came out, the SDK provided a really easy class to maintain the app settings: the IsolatedStorageSettings.

Basically, the class is an IDictionary<string, object> with a Save() method that will take the instance and serialize it to a file called “__ApplicationSettings” in the root of the app’s isolated storage.

Now if you upgraded your app from Windows Phone Silverlight 8.0 to the Windows Runtime model, you’ll probably want to migrate the settings from the old format to the new one, right?

Problem is that though the class exists in Windows Phone Silverlight apps, it does not in the new Windows Runtime apps, being replaced with ApplicationData.LocalSettings and ApplicationData.RoamingSettings instead.

So the only solution will be doing it ourselves, by reading and deserializing the “old” settings file!

Here’s a sample of the content of an “__ApplicationSettings” file from one of my tests:

PhoneApp1.Address, PhoneApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
<ArrayOfKeyValueOfstringanyType xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays"><KeyValueOfstringanyType><Key>Name</Key><Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:string">John Doe</Value></KeyValueOfstringanyType><KeyValueOfstringanyType><Key>Age</Key><Value xmlns:d3p1="http://www.w3.org/2001/XMLSchema" i:type="d3p1:int">20</Value></KeyValueOfstringanyType><KeyValueOfstringanyType><Key>Country</Key><Value xmlns:d3p1="http://schemas.datacontract.org/2004/07/PhoneApp1" i:type="d3p1:Address"><d3p1:Code>UK</d3p1:Code><d3p1:Name>United Kingdom</d3p1:Name></Value></KeyValueOfstringanyType></ArrayOfKeyValueOfstringanyType>

By looking at the contents of some samples of settings file like the one above, here’s what we can learn:

  • the file has always two lines (second line in the above sample is auto-wrapped to fit the post!)
  • the first line has the known types full names that should be loaded and passed on to the DataContractSerializer constructor, each properly separated by a null char
  • if only basic types are used, the first line will be empty
  • the second line is the serialized xml data

So I wrote the following code snippet to read and deserialize the values from “__ApplicationSetting” to an IEnumerable<KeyValuePair<string, object>>:

public async Task<IEnumerable<KeyValuePair<string, object>>> GetValuesAsync()
{
    try
    {
        using (var fileStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync("__ApplicationSettings"))
        {
            using (var streamReader = new StreamReader(fileStream))
            {
                var line = streamReader.ReadLine() ?? string.Empty;

                var knownTypes = line.Split('')
                    .Where(x => !string.IsNullOrEmpty(x))
                    .Select(Type.GetType)
                    .ToArray();

                fileStream.Position = line.Length + Environment.NewLine.Length;

                var serializer = new DataContractSerializer(typeof(Dictionary<string, object>), knownTypes);

                return (Dictionary<string, object>)serializer.ReadObject(fileStream);
            }
        }
    }
    catch
    {
        return new Dictionary<string, object>();
    }
}

So all you now have to do is call the GetValuesAsync() method above and load those values to one of the new Settings repositories!

The Cimbalino Toolkit way

Starting in Cimbalino Toolkit 1.2.0, you’ll be able to use the new IApplicationSettingsService to access Local, Roaming, and Legacy app settings.

In case that wasn’t clear from the names, the Legacy settings will allow you to get the values on the “__ApplicationSettings” file (do note that only the Values property is implemented, so it’s read-only).

Here are the platform rules for the ISettingsService:

  • Local
    • Supported in all platforms
  • Roaming
    • Supported in all platforms except Windows Phone Silverlight 8.0
  • Legacy
    • Only supported in Windows Phone

One last suggestion: after migrating the legacy settings remember to delete the “__ApplicationSettings” file as it won’t be needed again! 😉

  • Philip Colmer

    Hi – thanks for sharing this information.
    In the testing I’ve done, installing the APPX version of my app always results in it being installed as well as the XAP version of the app, even though I’ve copied over the ProductID from WMAppManifest.xml into PhoneProductId in Package.appxmanifest.
    I posted to the forums about this and MS replied that this was by design. I find that very difficult to believe and I’m more inclined to believe that I’ve missed something out in the configuration of the app that tells the phone that it is the new version of an existing app … but I don’t know what.
    Any suggestions, please?
    Thanks.

    • Unfortunately at this time I don’t have much more insight over this… no promises, but I’ll try to get some information internally and see if there is any other way of solving this!

      • Philip Colmer

        I think I’m making some progress on this. If you’ve installed an app from the Store, you can’t upgrade it from VS – you can only upgrade it from the Store. I’m still testing that out, but that is what it looks like.

  • Philip Colmer

    I think that the first line only lists the object types that aren’t “standard”, e.g. boolean, int, string, etc. In my __ApplicationSettings file, though, there is only one non-standard type and it doesn’t appear to be null-terminated.

    • Correct, though the null char is only used as a type separator, not as terminator! Lines are separated by crlf.

      • Philip Colmer

        OK, so if it is a separator, unfortunately it doesn’t appear if there is only one type, so knownTypes is empty when your code tries to parse my file. I can email it to you as a sample if that would help?

        • Please do, send it to pedrolamas at gmail dot com! 🙂

  • Pingback: Migrating a WP Silverlight app to WP XAML – supporting settings | Musings of a PC()