The third file access mechanism is Isolated Storage mechanism, which provides storage associated with the logged in user. The API presents data through the Stream class from .NET System.IO namespace. Therefore, as with the other mechanisms we have looked at so far, you can use the other types in System.IO to work with the streams, enabling you to store either textual or binary data.
Some important features are −
This storage mechanism is called Isolated Storage because the store is partitioned, and a Silverlight application has access only to certain parts.
You cannot access any old stored data. First of all, the store is partitioned per user. A Silverlight application cannot get access to the store for a different user than the one logged in, and running the application.
This has nothing to do with any identification mechanisms your web application may use. That is an important point to remember because some people who share computers do not bother with separate Windows accounts, and are accustomed just to logging in and out of the websites that they use.
Isolated Storage is not unique to Silverlight. The API was originally introduced for Windows Forms to enable applications launched from the web to store data locally in partial trust scenarios. The implementation is different, and there is no way to access the full .NET Framework's Isolated Storage from Silverlight's, or vice versa.
However, if you have used it, the steps here will look very familiar.
You begin by asking for the user specific store. In this case, we are asking for the one for the application. If we wanted the per-site store shared by all XAPs on the site, we would call GetUserStoreForSite instead.
Either method returns an IsolatedStorageFile object, which is a pretty unhelpful name as this represents a directory, not a file.
To access a file, you need to ask the IsolatedStorageFile for a Stream.
We use the IsolatedStorageFileStream class, and its constructor requires you to pass the IsolatedStorageFile object as an argument.
So we are creating a new file in the store. The exact location of the file on disk is unknown.
The containing directory has randomized elements in order to make it impossible to guess the name of the file.
Without this, it might be possible for malicious websites to place a file on the user's computer, and then construct a file URL to open it, in the hope of fooling the user into clicking a link that executes a program locally.
There are various other safeguards built into Windows that try to prevent this from happening, but this is another layer of defense in case the others have somehow been disabled, or bypassed.
The file will be stored somewhere inside the user's profile, but that is as much as you can know about it. Your IsolatedStorageFileStream will not report its true location.
Let us have a look at a simple example that tracks how many times the application has been run. Given below is the XAML code.
<UserControl x:Class = "StoreRunCount.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <TextBlock x:Name = "runCountText" FontSize = "20" /> </Grid> </UserControl>
Here is the C# code in which Isolated storage are used.
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.IO.IsolatedStorage; using System.IO; namespace StoreRunCount { public partial class MainPage : UserControl { const string RunCountFileName = "RunCount.bin"; public MainPage() { InitializeComponent(); int runCount = 0; using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { if (store.FileExists(RunCountFileName)) { using (var stm = store.OpenFile(RunCountFileName, FileMode.Open, FileAccess.Read)) using (var r = new BinaryReader(stm)) { runCount = r.ReadInt32(); } } runCount += 1; using (var stm = store.OpenFile(RunCountFileName, FileMode.Create, FileAccess.Write)) using (var w = new BinaryWriter(stm)) { w.Write(runCount); } } runCountText.Text = "You have run this application " + runCount.ToString() + " time(s)"; } } }
When the above code is compiled and executed, you will see the following webpage which will show you that how many times you run this application.
Applications may ask for more space if the initial amount is insufficient for some reason. There is no guarantee that the request will succeed. Silverlight will ask the user if they are happy to grant the application more space.
By the way, you are only allowed to ask for more storage in response to user input, such as a click. If you try to ask it some other time, such as when the plug-in loads, or in a timer handler, Silverlight will automatically fail the request without even prompting the user. Extra quota is only available to the applications with which the user is interacting.
The IsolatedStorageFile object provides three members for managing quota −
The AvailableFreeSpace property tells you how much of your quota remains free.
Note that even an empty subdirectory consumes some of your quota because the operating system needs to allocate space on disk to represent the directory. So, the available space may be less than the total quota, minus the sum size of all your files.
If you do not have sufficient space to proceed, you ask for more by calling the IncreaseQuotaTo method.
Here we are using the third property, Quota, to discover the current quota size, and then we are adding the amount extra we require to get our new requested quota.
The method returns either True or False to indicate whether we are allocated what we asked for. Note that Silverlight may decide to allocate more space than you asked for.
Here is a simple example to increase the quota, when the button is clicked. Given below is the XAML code.
<UserControl x:Class = "ChangeQuota.MainPage" xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "400"> <Grid x:Name = "LayoutRoot" Background = "White"> <TextBlock x:Name = "infoText" FontSize = "20" TextWrapping = "Wrap" /> <Button x:Name = "increaseQuota" Content = "Increase" HorizontalAlignment = "Center" FontSize = "20" VerticalAlignment = "Center" Click = "increaseQuota_Click" /> </Grid> </UserControl>
Here is the implementation of click event in which quota is increased.
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.IO.IsolatedStorage; namespace ChangeQuota { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); } private void increaseQuota_Click(object sender, RoutedEventArgs e) { using (IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication()) { long newQuota = isoStore.Quota + 10240; if (isoStore.IncreaseQuotaTo(newQuota)) { infoText.Text = "Quota is " + isoStore.Quota + ", free space: " + isoStore.AvailableFreeSpace; } else { infoText.Text = "Meanie!"; } } } } }
When the above code is compiled and executed, you will see the following output.
When you click Increase, the prompt appears. It asks to increase the Quota to be 10KB larger than whatever it already is.
When you click Yes, it then prints out the amount of Quota available.
We recommend you to execute the above examples for better understanding.