Access is denied when saving an object in local storage Windows 8 Metro application

I am trying to save a list (where Show is my class that implements IXmlSerializable) in local isolated storage. I use the code on this page: http://metrostoragehelper.codeplex.com/ I implemented the change suggested in the Problems section. I use the following code to add a Show object when it is clicked from a list of items.

private async void addShowButton_Click_1(object sender, RoutedEventArgs e) { var isoStorage = new StorageHelper<List<Show>>(StorageType.Local); List<Show> currentShows = await isoStorage.LoadASync("myShowsEx"); if(currentShows == null) { currentShows = new List<Show>(); } currentShows.Add(currentShow); isoStorage.SaveASync(currentShows, "myShowsEx"); //Read it back, for debugging to check if it has been added properly. List<Show> currentShowsRB = await isoStorage.LoadASync("myShowsEx"); //Exception here } 

The first show has been added perfectly, and it appears in the current ShowsRB list. When you click on the second element and the method called above, an exception occurs during the last call to LoadAsync: access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)) How can I get around this to access the local data store for multiple calls?

Below is also the corresponding code from StorageHelper:

 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); using (var writeStream = await file.OpenAsync(FileAccessMode.ReadWrite)) { Stream outStream = Task.Run(() => writeStream.AsStreamForWrite()).Result; serializer.Serialize(outStream, Obj); //writeStream.Dispose(); //Added and we get UnauthorizedAccessException // outStream.Dispose(); //Added ObjectDisposedException caught in catch statement below } } } 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); using (var readStream = await file.OpenAsync(FileAccessMode.Read)) { Stream inStream = Task.Run(() => readStream.AsStreamForRead()).Result; inStream.Position = 0; 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; } } 

The writeStream.Dispose () line that I added, but even when it is turned on, I get the same Access is Denied error message. If I also include the outStream.Dispose () line, then I get an ObjectDisposedException that hits the catch statement right away. Is there anything else I should do?

+4
source share
2 answers

You do not wait for SaveAsync to finish trying to load when Save is still running. Change it to:

 //isoStorage.SaveASync(currentShows, "myShowsEx"); await isoStorage.SaveASync(currentShows, "myShowsEx"); List<Show> currentShowsRB = await isoStorage.LoadASync("myShowsEx"); 

await ing to void is a standard issue.
Quick fix:

  await TaskEx.Run(() => isoStorage.SaveASync(currentShows, "myShowsEx")); 

But you can also move TaskEx.Run() inside SaveASync() . And given the name that ends with Async, it should not be void , but:

 Task SaveASyncT Obj, string FileName) { return TaskEx.Run() => { .... } } 

I do not believe that there is an asynchronous version of Serialize, so it remains in TaskEx.Run() .

+2
source

This block can be reduced to:

  using (var readStream = await file.OpenAsync(FileAccessMode.Read)) { return (T)serializer.Deserialize(readStream); } 

since you can directly read / write from a stream in the XmlSerializer class.

You may also find that CreationCollisionOption.ReplaceExisting can cause problems, and OpenIfExists will cause the file to be overwritten by the serializer as needed.

0
source

All Articles