One topic that comes up frequently in dev circles is persisting data in Silverlight applications. There are a number of ways to do this, and the right solution depends on the data that is being stored. In ASP.NET applications, user settings are typically stored in a database and often abstracted through a mechanism like the ASP.NET Profile provider in conjunction with the ASP.NET Membership provider. The make the end user experience a bit better, log in state (or simply the username) is persisted in a cookie.
In Silverlight, this is still a viable approach (although the data is typically exposed via webservices, depending on the application).
Another approach, however, is to use isolated storage. Isolated storage can be an effective tool for caching data (with a number of caveats). In the example below, I’ve created a very simple class that contains the application settings I’d like to persist. The key methods are Load() and Save(). Out of the box, this will work and you can simply add/remove properties as you’d like.
1: public class ApplicationSettings
2: {
3: [DefaultValue(6)]
4: public int MinZoom { get; set; }
5:
6: [DefaultValue(13)]
7: public int MaxZoom { get; set; }
8:
9: [DefaultValue(8)]
10: public int PlotDelay { get; set; }
11:
12: [DefaultValue(false)]
13: public bool RememberSettings { get; set; }
14:
15: public ApplicationSettings() { }
16:
17: public static WorldmapsSettings Load()
18: {
19: ApplicationSettings settings = new ApplicationSettings();
20:
21: using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
22: {
23: if (!store.FileExists(@"ApplicationSettings.xml"))
24: {
25: return settings;
26: }
27:
28: using (var isoStream = store.OpenFile(@"ApplicationSettings.xml",
29: FileMode.Open))
30: {
31: XmlSerializer s = new XmlSerializer(typeof(ApplicationSettings));
32: TextReader r = new StreamReader(isoStream);
33: settings = (ApplicationSettings)s.Deserialize(r);
34: r.Close();
35:
36: if (settings != null && settings.RememberSettings)
37: {
38: return settings;
39: }
40: else
41: {
42: return new ApplicationSettings();
43: }
44: }
45: }
46: }
47:
48: public void Save()
49: {
50: using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
51: {
52: using (IsolatedStorageFileStream isoStream = store.OpenFile(@"ApplicationSettings.xml",
53: FileMode.Create))
54: {
55: XmlSerializer s = new XmlSerializer(typeof(ApplicationSettings));
56: TextWriter writer = new StreamWriter(isoStream);
57: s.Serialize(writer, this);
58: writer.Close();
59: }
60: }
61: }
62: }
[EDIT]
Silverlight guru Tim Heuer pointed out I’m doing a lot of extra work I don’t need to. The ApplicationSettings of the IsolatedStorageSettings allows us to stuff objects in it pretty cleanly – so the above could be implemented like so:
1: public static WorldmapsSettings Load()
2: {
3:
4: WorldmapsSettings settings = null;
5:
6: if (IsolatedStorageSettings.ApplicationSettings.Contains("foo"))
7: {
8: settings = IsolatedStorageSettings.ApplicationSettings["foo"] as WorldmapsSettings;
9: }
10:
11: if (settings == null)
12: {
13: settings = new WorldmapsSettings();
14: }
15:
16: return settings;
17: }
18:
19: public void Save()
20: {
21: IsolatedStorageSettings.ApplicationSettings["foo"] = this;
22: }
I can’t think of a good reason not to do it this way, unless some more complex serialization is called for, but even then I can’t come up with a good scenario for that.
[/EDIT]
Now for the caveat. Isolated storage isn’t secure unless you take some measures to secure it manually. While you could encrypt the contents, I’d probably recommend not storing data on the client if you’re saving sensitive data. In the above example, I’m serializing the data using the XML serializer, so the data is obviously in plain text and stored locally:
… and it contains the expected object:
1: <ApplicationSettings xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2: xmlns:xsd="http://www.w3.org/2001/XMLSchema">
3: <MinZoom>2</MinZoom>
4: <MaxZoom>16</MaxZoom>
5: <PlotDelaySeconds>14</PlotDelaySeconds>
6: <RememberSettings>false</RememberSettings>
7: </ApplicationSettings>
Isolated storage offers a lot of potential, but it’s also important to remember the security implications in both exposing the data as well as potential injection points.