Isolated Storage Helper For C# and XAML based Metro Application

This post and helper class is based on work of Jamie Thomson . I thank him lot for that.

Why to use Metro Application Isolated Storage Helper?

This helper class helps you to perform Read,Write and Delete of structured data in Isolated storage folders.

How to use this?

Download Metro Application Isolated Storage Helper from here

You have a class Student



public class Student
    {
        public string Name { get; set; }
        public int RollNumber { get; set; }
    }


You want to save object of Student then you can save it in Local Folder of isolated storage as below


Student objStudent = new Student { Name = "DJ ", RollNumber = 1 };
            var objectStorageHelper = new StorageHelper<Student>(StorageType.Local);            
            objectStorageHelper.SaveASync(objStudent,"abc");



And you can read back Student from isolated storage as below



public async void ReadData()
        {            
            var objectStorageHelper = new StorageHelper<Student>(StorageType.Local);           
            Student objStudent = await objectStorageHelper.LoadASync("abc");
            
        }


Abc is name of the file. If you want to store List<Student> then you can do that as following,



List<Student> lstStudent = new List<Student>()
                                        {new Student { Name = "DJ ", RollNumber = 1 },
                                         new Student { Name = "debugmode", RollNumber = 2 }
                                        };

            var objectStorageHelper = new StorageHelper<List<Student>>(StorageType.Local);
            objectStorageHelper.SaveASync(lstStudent, "abc");



You can read List<Student> from local folder of isolated storage as following



public async void ReadData()
        {            
            var objectStorageHelper = new StorageHelper<List<Student>>(StorageType.Local);           
            List<Student> lstStudent = await objectStorageHelper.LoadASync("abc");
            foreach (var r in lstStudent)
            {
                string n = r.Name;
            }
        }




Background

I was working with storing and retrieving structured data in Isolated Storage. While Binging I came across nicely written Generic Object Storage Helper for WinRT . This is written by Jamie Thomson . When I tried using this utility I came across an exception. I tried to store object of Student as following.


private void btnSaveData_Click_1(object sender, RoutedEventArgs e)
        {
            Student objStudent = new Student { Name = "Hary ", RollNumber = 1 };
            var objectStorageHelper = new ObjectStorageHelper<Student>(StorageType.Local);            
            objectStorageHelper.SaveASync(objStudent);
        }

But while running the program I came across exception as below,

image

After inspecting I found that library is written in Developer Preview and few API has been changed in Consumer Preview. Thankfully Jamie Thomson has put the source code on the CodePlex also. A big thank to him for the same. Rather than adding DLL and working with API, I copied and pasted code in my program and started to debug that.

First changes in API from DP to CP was that there were no TryMoveToRecycleBin in StorageDeleteOption enum

image

Now StorageDeleteOption enum contains only two values as below,

image

So I replaced above line of code as below,

image

The Second changes from DP to CP I found was removal of OpenWrite and OpenRead method from IRandomAcccessStream interface

image

Where readStream is defined as below,

image

And OpenWrite has been replaced with AsStreamForWrite

image

I have modified code to explicitly take filename as well. After these changes have been done Code was ready to be used in Consumer Preview. Updated helper class code is as following,

 



     public enum StorageType
    {
        Roaming, Local, Temporary
    }

    public class ObjectStorageHelper<T>
    {
        private ApplicationData appData = Windows.Storage.ApplicationData.Current;
        private XmlSerializer serializer;
        private StorageType storageType;

        
        public ObjectStorageHelper(StorageType StorageType)
        {
            serializer = new XmlSerializer(typeof(T));
            storageType = StorageType;
        }

        public async void DeleteASync(string FileName)
        {
            FileName = FileName + ".xml";
            try
            {
                StorageFolder folder = GetFolder(storageType);

                var file = await GetFileIfExistsAsync(folder, FileName);
                if (file != null)
                {
                    await file.DeleteAsync(StorageDeleteOption.PermanentDelete);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        public async void SaveASync(T Obj,string FileName)
        {

            FileName = FileName + ".xml";
            try
            {
                if (Obj != null)
                {
                    StorageFile file = null;
                    StorageFolder folder = GetFolder(storageType);
                    file = await folder.CreateFileAsync(FileName, CreationCollisionOption.ReplaceExisting);

                    IRandomAccessStream writeStream = await file.OpenAsync(FileAccessMode.ReadWrite);
                    Stream outStream = Task.Run(() => writeStream.AsStreamForWrite()).Result;
                    serializer.Serialize(outStream, Obj);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
        public async Task<T> LoadASync(string FileName)
        {
            FileName = FileName + ".xml";
            try
            {
                StorageFile file = null;
                StorageFolder folder = GetFolder(storageType);
                file = await folder.GetFileAsync(FileName);
                IRandomAccessStream readStream = await file.OpenAsync(FileAccessMode.Read);
                Stream inStream = Task.Run(() => readStream.AsStreamForRead()).Result;
                return (T)serializer.Deserialize(inStream);
            }
            catch (FileNotFoundException)
            {
                //file not existing is perfectly valid so simply return the default 
                return default(T);
                //throw;
            }
            catch (Exception)
                 {
                //Unable to load contents of file
                throw;
            }
        }

        private StorageFolder GetFolder(StorageType storageType)
        {
            StorageFolder folder;
            switch (storageType)
            {
                case StorageType.Roaming:
                    folder = appData.RoamingFolder;
                    break;
                case StorageType.Local:
                    folder = appData.LocalFolder;
                    break;
                case StorageType.Temporary:
                    folder = appData.TemporaryFolder;
                    break;
                default:
                    throw new Exception(String.Format("Unknown StorageType: {0}", storageType));
            }
            return folder;
        }

        private async Task<StorageFile> GetFileIfExistsAsync(StorageFolder folder, string fileName)
        {
            try
            {
                return await folder.GetFileAsync(fileName);

            }
            catch
            {
                return null;
            }
 }
    }



In this way you can work with structured data in XAML based Metro Application for Windows 8. I hope this post is useful. Thanks for reading.

10 thoughts on “Isolated Storage Helper For C# and XAML based Metro Application

  1. Pingback: Monthly Report April 2012: Total Posts 4 « debug mode……

  2. In Release Preview we need fix a little thing to solve this problem.
    Just change the line of LoadASync Method

    IRandomAccessStream readStream = await file.OpenAsync(FileAccessMode.Read);

    to use OpenReadAsync method, like this:

    IRandomAccessStream readStream = await file.OpenReadAsync();

    Everything will works fine
    =)

  3. This isn’t working for me… It is breaking here:

    var objectStorageHelper = new StorageHelper(StorageType.Local);

    An exception of type ‘System.InvalidOperationException’ occurred in System.Xml.dll but was not handled in user code.

    I’m using the Release Candidate.

  4. ‘System.InvalidOperationException’ occurred in System.Xml.dll System.Runtime.InteropServices.WindowsRuntime.RuntimeClass is inaccessible due to its protection level. Only public types can be processed.
    Error At serializer = new XmlSerializer(typeof(T));

  5. I so needed this thank you very much. I am only running into one problem where i get this error when trying to load data Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) – I did the change IRandomAccessStream readStream = await file.OpenReadAsync();

    Any suggestions? Thank you very much for your hard work.

  6. Hi – Related to the access “denied error”, put please
    writeStream.Dispose();
    after the line 045.
    This solves the issue.

    Cheers, S.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s