.NET

Silverlight and Local Storage

By Dino Esposito, May 26, 2008

All applications benefit from local storage

Silverlight applications are something in between traditional Web applications and smart clients. A Silverlight application is more powerful than a Web application because of its support for managed code and its embedded .NET common language runtime. Compared to a smart client application, instead, a Silverlight-based solution is still a partial trust application with, among other things, limited access to URLs and the local filesystem.

Nearly all applications, on nearly any platforms, would greatly benefit from local data storage. Notice that I'm not talking about storing data to a DBMS on some server. With local storage, I mean the application's ability to save some data on the client machine. This has never been an issue for desktop applications which have full access to the local disk. For Web applications, instead, it has always been a mission-impossible task. For security reasons, any code hosted by Web pages  typically, JavaScript code  can't just access the filesystem of the local machine. For years, Web page developers resorted to cookies, or server-side storage, to save some user-specific information.

As far as local storage is concerned, Silverlight confirms to be a platform sitting in between the Web and desktop. A Silverlight application can't freely perform I/O operations on the user's hard disk because those are considered critical from a security perspective. However, a Silverlight application takes advantage of a special and constrained programming interface that permits disk access only under certain conditions. This .NET Framework API is known as "isolated storage" and Silverlight fully supports it.

Why Is Local Storage Important?

What kind of content should an application store in the user's local disk? While it mostly depends on the particular application, a couple of categories of data can be easily identified. First off, applications may need to save application settings and everything that can be filed under that tag. Application settings include user preferences, configuration, extra features installed, and also user-specific data that are helpful and useful to the application. For example, you could save in the local storage the draft of a form so that users could come back later and fill out the rest of the form without losing any information.

Second, applications may need to temporarily save any data that the user is still working on and that has not been committed yet. The user will eventually submit this work to the server, but until then data has to be maintained on the client and updated as needed.

These two broad categories of data going into the local storage of a Silverlight application have significant differences as far their size is concerned. Application settings are usually short pieces of data limited to just a few KBs. Working data, instead, is usually a much larger chunk of data, even in the order of MBs, that contain text or binary data representing a piece of work.

Nearly all types of application may benefit from persistent settings; mostly occasionally connected applications, though, may benefit of client-side persistence of working data.

However, for both types of applications Silverlight is a very good and promising presentation layer. That's why you find support for local storage in Silverlight 2.0.

Isolated Storage in Silverlight 2.0

In the .NET Framework, isolated storage is a storage mechanism that enables partially trusted applications to save data on the local machine without violating any security policies set on the computer. Isolated storage is around since the first version of the .NET Framework and is especially useful for downloaded, partially trusted components that are not usually given access to the standard I/O mechanisms. These same applications, though, are usually granted the right to use isolated storage. In this way, applications coming from potentially untrusted sources can still do some disk I/O, albeit in a controlled way.

Silverlight has its own implementation of the isolated storage feature and doesn't directly rely on the bits provided with the .NET Framework. This is not surprising as Silverlight is not a desktop platform and doesn't rely on a full edition of the .NET Framework installed on the client machine. A compatible subset of the .NET isolated storage subsystem is supported in Silverlight, but don't be too concerned  reading, writing and deleting files and directories in a virtual and application specific filesystem are all supported features. Can you ask for more?

The entry point in the Silverlight isolated storage subsystem is the IsolatedStorageFile class and in particular its static method GetUserStoreForApplication. The method gets you a token that can be used to perform any supported operation on the virtual filesystem.

The token you get through the GetUserStoreForApplication method is ultimately an aptly created instance of the IsolatedStorageFile class properly initialized to track which part of the physical filesystem it has to work on.

The root of the isolated storage filesystem is located in a hidden folder within the subtree reserved to the current user. If you're using Windows Vista, the hidden isolated storage folder lives under the Users directory. If you're using Windows 2003 Server, it will then be located under the Documents and Settings folder for the current user. Each Silverlight application has its own virtual filesystem that is completely separated from the filesystem visible to other applications. A Silverlight application can't just navigate out of its personal filesystem. File names are always intended to be relative to the filesystem meaning that you can't use absolute paths that include drive information. At the same time, any relative path that includes ellipsis \..\..\ is not allowed.

When the GetUserStoreForApplication method is invoked it first checks whether the proper subtree exists and, if not, it will create it. As an application developer, you only have to worry about your own files and directories. The system guarantees that the isolated storage infrastructure is always up and running for you.

Working with Files and Directories

The IsolatedStorageFile class features a number of methods to perform CRUD and lookup operations on files and directories. Table 1 lists the most important methods.

Silverlight and the Local Storage

Method name

Description

CreateFile

Creates a file with the specified name.

CreateDirectory

Creates a directory with the specified name. To create subdirectories you specify a combined name that includes the parent directories.

DeleteFile

Deletes the specified file. If the file doesnt exist you will receive an exception of type IsolatedStorageException.

DeleteDirectory

Deletes the specified directory, provided that the directory exists and is empty. In any other case, you will receive an exception of type IsolatedStorageException.

DirectoryExists

Indicates whether a directory with the specified name exists.

FileExists

Indicates whether a file with the specified name exists.

GetDirectoryNames

Enumerates all the directories in the current store that match the specified search criteria.

GetFileNames

Enumerates all the files in the current store that match the specified search criteria.

OpenFile

Opens the specified file and returns a stream for it. If the file doesnt exist, you will receive an exception of type IsolatedStorageException.

What if you need to create a child subdirectory? All that you have to do is getting hold of a directory name that includes both the parent directory and the new directory. If you can't provide the full name of the directory as a hard-coded string, you can use the Path class to build the name programmatically. Here's how to do it:

It is worth recalling that in Silverlight you can only use relative names to refer to files and directories as if they were scoped to the root of the filesystem. Well, this is exactly what happens here; except that we're talking about a virtual filesystem.

To enumerate the content of a directory, whether you want to list files or child directories, you use ad hoc methods such as GetFileNames and GetDirectoryNames. Both methods return an array of strings with all the names that match the specified search criteria.

string[] filelist = iso.GetFileNames("*.txt");

Both GetFileNames and GetDirectoryNames have two overloads. If you use the parameterless overload, then the returned array includes all elements found. If you specify a search pattern, keep in mind that you can use both single character (?) and multiple character (*) wildcards.

In Silverlight, you can't make any use of the DirectoryInfo and FileInfo classes that in the full .NET Framework are so helpful when it comes to do any special work on files and directories. The following code, though, compiles successfully:

DirectoryInfo dir = new DirectoryInfo(@"c:\");

In other words, the DirectoryInfo class, as well as the companion FileInfo class, is an integral part of the .NET Framework that ships with Silverlight. The problem with the previous code is just security. No developer code can be executed in Silverlight that invokes a class method that is flagged with the SecurityCritical attribute. As you can see in Figure 1, all methods of the DirectoryInfo class, including the constructors, fall in this category.

Figure 1:Dissecting the source code of the DirectoryInfo class.

The DirectoryInfo class is defined in the Silverlight base class library but it is not available to developer code. It can only be invoked from system code that is, in turn, decorated with the SecuritySafeCritical attribute. No developer code can ever be decorated with the SecuritySafeCritical attribute. Any programmatic access to DirectoryInfo, or other classes or methods flagged with a security critical attribute, results in an exception of type MethodAccessException.

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!