I have a file Add.xaml
Inside, I have my recipe class that store my recipe object inside a list named breakfastRecipe
I then store the list beakfastRecipe inside a breakfast.json file. (using Deserialize/serialize methods i found from another member here)
I have a couple of textboxes where i write the name + ingredient then i use a save button that activate the json serializer. I used test method to test the deserializer if everything was working and it does. on the add.xaml page , the save and load of the object list is working perfectly
I have another page breakfastList.xaml where i want use longlistselector to populate my page with all my recipes. The problem is i don't how to access that breakfast.json file that was created on the other page.
I used the same get/deserializer to load my data
public async void btnGet_Tap()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
try
{
// Getting JSON from file if it exists, or file not found exception if it does not
StorageFile textFile = await localFolder.GetFileAsync("breakfastList.json");
using (IRandomAccessStream textStream = await textFile.OpenReadAsync())
{
// Read text stream
using (DataReader textReader = new DataReader(textStream))
{
//get size
uint textLength = (uint)textStream.Size;
await textReader.LoadAsync(textLength);
// read it
string jsonContents = textReader.ReadString(textLength);
// deserialize back to our products!
//I only had to change this following line in this function
breakfastRecipe = JsonConvert.DeserializeObject<IList<Recipe>>(jsonContents) as List<Recipe>;
// and show it
//displayProduct();
}
}
}
catch (Exception ex)
{
tester.Text = "error";
}
}
When i write in the constructor
breakfastRecipe = new List();
btnGet_Tap();
In my mind, it i'm creating a new list then the btnGet load the data from that .json file that my add.xaml have created but it isn't working...
my question is then how to access the data on my "second page" which is stored in that .json file which was created by my first page
Try moving your btnGet_Tap code into an async function that returns a task and then await in the btnGet_Tap() method. You can then call
Foo().Wait();
if you wish to wait when calling in your constructor.
public async void btnGet_Tap()
{
await Foo();
}
public async Task Foo()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
try
{
// Getting JSON from file if it exists, or file not found exception if it does not
StorageFile textFile = await localFolder.GetFileAsync("breakfastList.json");
using (IRandomAccessStream textStream = await textFile.OpenReadAsync())
{
// Read text stream
using (DataReader textReader = new DataReader(textStream))
{
//get size
uint textLength = (uint)textStream.Size;
await textReader.LoadAsync(textLength);
// read it
string jsonContents = textReader.ReadString(textLength);
// deserialize back to our products!
//I only had to change this following line in this function
breakfastRecipe = JsonConvert.DeserializeObject<IList<Recipe>>(jsonContents) as List<Recipe>;
// and show it
//displayProduct();
}
}
}
catch (Exception ex)
{
tester.Text = "error";
}
}
Related
I'm trying to upload a file using Microsoft's Graph SDK but have hit a problem.
I have pretty much copied verbatim the C# example from here, commented-out the progress part and updated the using statement for C# 8, and here's what I have...
public async Task<bool> UploadFileAsync(string parentFolderId, string filename, byte[] bytes)
{
var graphClient = GetGraphClient();
// Declare the variable outside the `using` statement to get around a little C# problem - https://www.tabsoverspaces.com/233779-using-await-using-iasyncdisposable-with-configureawait
var memoryStream = new MemoryStream(bytes);
await using (memoryStream.ConfigureAwait(false))
{
// Use properties to specify the conflict behavior.
// - in this case, replace.
var uploadProps = new DriveItemUploadableProperties
{
AdditionalData = new Dictionary<string, object> {{"#microsoft.graph.conflictBehavior", "replace"}},
ODataType = null
};
try
{
// Create the upload session.
// - itemPath does not need to be a path to an existing item.
var uploadSession = await graphClient.Drives[_driveId]
.Items[parentFolderId]
.ItemWithPath(filename)
.CreateUploadSession(uploadProps)
.Request()
.PostAsync()
.ConfigureAwait(false);
// Max slice size must be a multiple of 320KB.
const int maxSliceSize = 320 * 1024;
var fileUploadTask = new LargeFileUploadTask<DriveItem>(uploadSession, memoryStream, maxSliceSize);
// Upload the file.
var uploadResult = await fileUploadTask.UploadAsync().ConfigureAwait(false);
if (uploadResult.UploadSucceeded)
{
// The ItemResponse object in the result represents the created item.
return true;
}
return false;
}
catch (ServiceException exception)
{
// ...
}
}
}
However the line...
var uploadSession = await graphClient.Drives[_driveId]
.Items[parentFolderId]
...
...throws an exception:
Microsoft.Graph.ServiceException: Code: BadRequest
Message: Multiple action overloads were found with the same binding parameter for 'microsoft.graph.createUploadSession'.
Can anyone help?
I figured out the cause of the problem - the filename that I was using contained invalid symbols (in my case I was stringifying a DateTime and that contained :).
It's frustrating that this exception doesn't bubble-up correctly and instead I got that "Multiple action overloads" message.
I have a UWP app that I am deploying as an AppPackage, and I am seeing an off error when I attempt to read/save a file in the LocalState folder. It does not happen everytime, so I am thinking the file is locked during the process at some point. The erroe is
No mapping for the Unicode character exists in the target multi-byte code page.
And the code that throws the error
private const string SETTINGS_FILENAME = "settings.json";
private static readonly StorageFolder _settingsFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
public async static Task<ConfigWrapper> LoadSettings()
{
try
{
StorageFile sf = await _settingsFolder.GetFileAsync(SETTINGS_FILENAME);
if (sf == null) return null;
string content = await FileIO.ReadTextAsync(sf, Windows.Storage.Streams.UnicodeEncoding.Utf8);
return JsonConvert.DeserializeObject<ConfigWrapper>(content);
}
catch (Exception e)
{
DiagnosticsClient.TrackException(e);
return null;
}
}
public async static Task<bool> SaveSettings(ConfigWrapper data)
{
try
{
StorageFile file = await _settingsFolder.CreateFileAsync(SETTINGS_FILENAME, CreationCollisionOption.ReplaceExisting);
string content = JsonConvert.SerializeObject(data, Newtonsoft.Json.Formatting.Indented, new JsonSerializerSettings { });
await FileIO.WriteTextAsync(file, content, Windows.Storage.Streams.UnicodeEncoding.Utf8);
return true;
}
catch (Exception e)
{
DiagnosticsClient.TrackException(e);
return false;
}
}
I am making sure to save and read the file in UTF-8, so I am not sure why there would be an encoding error. Is there something I need to do (lock the file for instance) when I save/read?
Many applications save data in a proprietary format. The gibberish you provided is probably such.
Such applications often have a way to "write" or "export" or "save as" the data. Look for such.
i have this two methods for writting and reading from the file.
public static async Task WriteDataToFileAsync(string fileName, string content)
{
byte[] data = Encoding.Unicode.GetBytes(content);
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
using (var s = await file.OpenStreamForWriteAsync())
{
await s.WriteAsync(data, 0, data.Length);
}
}
public async static Task<string> ReadFileContentsAsync()
{
var folder = ApplicationData.Current.LocalFolder;
try
{
var file = await folder.OpenStreamForReadAsync("MenuData.json");
using (var streamReader = new StreamReader(file))
{
Debug.WriteLine(streamReader.ReadToEnd());
return streamReader.ReadToEnd();
}
}
catch (Exception)
{
return string.Empty;
}
}
which are then used in this two methods
public static async void ApiToFileRestaurants()
{
HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAsync("http://bonar.si/api/restaurants").Result;
response.EnsureSuccessStatusCode();
string responseBody = response.Content.ReadAsStringAsync().Result;
await Restaurant.WriteDataToFileAsync("MenuData.json", responseBody);
}
public async static Task<List<Restaurant>> FileToRestaurantList()
{
var responseBody = await Restaurant.ReadFileContentsAsync();
List<Restaurant> parsedRestaurants = (List<Restaurant>)Newtonsoft.Json.JsonConvert.DeserializeObject(responseBody, typeof(List<Restaurant>));
return parsedRestaurants;
}
now my problem here is that ReadFileAsync doesn't return the results which i know are saved in MenuData.json file but instead returns empty string.
I was mostly getting source code for this from msdn
documentation.
Location of the file in my wp power tools looks like that.
I'm a novice programer so i might overlooked something else
Can you try to read the data from file asyncronously by using ReadToEndAsync which basically parses the complete data and sends response as one string.
var file = await folder.OpenStreamForReadAsync("MenuData.json");
using (var streamReader = new StreamReader(file))
{
return await streamReader.ReadToEndAsync();
}
Hope this helps!
i got the solution from one other forum
You're calling streamReader.ReadToEnd() twice. The first time you log
it to the Debug stream, the second is what you actually use as a
result. The method moves the file pointer to the end everytime it's
called and by the second time there's nothing to read.
so removing that debug line almost fixed my problem. I did get the string i wanted to but there was an error somewhere in it so Newtonsoft.Json had a hard time parsing it. So i tried #asitis solution and changed .json to .text and it worked
First of all, I'm developing a WindowsPhone8.1 app which has a JSON (name, telephone number, email-...) file from the web. I store this JSON data in a list (contact is a class which has the parameters from the JSON.
I want to store (local no Cloud) this list on my WindowsPhone (its a List with marked favorites, not the whole list).
I tried it with StorageFolder and StorageFile, unfortunately, I failed. Got a problem with deleting and loading the files.
Developing in Microsoft Visual Studio Premium 2013 Update 3 with C#, Xaml.
I use this class, you need Json package which is available via nuget.
class StorageService : IConfigurationService
{
readonly StorageFolder _local = ApplicationData.Current.LocalFolder;
public async void Save<T>(string key, T obj)
{
var json = JsonConvert.SerializeObject(obj);
var dataFolder = await _local.CreateFolderAsync("DataFolder",
CreationCollisionOption.OpenIfExists);
var file = await dataFolder.CreateFileAsync(key,
CreationCollisionOption.ReplaceExisting);
await FileIO.WriteTextAsync(file, json);
}
public async Task<T> Load<T>(string key)
{
try
{
var dataFolder = await _local.GetFolderAsync("DataFolder");
var file = await dataFolder.OpenStreamForReadAsync(key);
string json;
using (var streamReader = new StreamReader(file))
{
json = streamReader.ReadToEnd();
}
return JsonConvert.DeserializeObject<T>(json);
}
catch (Exception)
{
return default(T);
}
}
}
I am developing a windows application in 8.1 and I am getting a following error.
my application includes a procedure in which I will be moving a file from local storage to SD card.
My code is as follows
namespace MoveFile
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
}
private async void btnCreateFolder_Click(object sender, RoutedEventArgs e)
{
await ReadFile();
//Error is showing here
**await WriteToFile();
}
public async Task WriteToFile()
{
// Get the text data from the textbox.
byte[] fileBytes = System.Text.Encoding.UTF8.GetBytes(this.txtSafakCount.Text.ToCharArray());
//I got the error in this line.....showing interopservice exception
** StorageFolder knownFolder = await KnownFolders.RemovableDevices.CreateFolderAsync("bdfbdfb", CreationCollisionOption.ReplaceExisting);
StorageFolder sdCard = (await knownFolder.GetFoldersAsync()).FirstOrDefault();
// Create a new file named DataFile.txt.
var file = await sdCard.CreateFileAsync("kaaaaammmmfewfwmHoJa.txt", CreationCollisionOption.ReplaceExisting);
// Write the data from the textbox.
using (var s = await file.OpenStreamForWriteAsync())
{
s.Write(fileBytes, 0, fileBytes.Length);
}
}
public async Task ReadFile()
{
// Get the local folder.
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
if (local != null)
{
// Get the DataFolder folder.
var dataFolder = await local.GetFolderAsync("DataFolder");
// Get the file.
await dataFolder.CreateFileAsync("DataFile.txt", CreationCollisionOption.ReplaceExisting);
var file = await dataFolder.OpenStreamForReadAsync("DataFile.txt");
// Read the data.
using (StreamReader streamReader = new StreamReader(file))
{
this.txtSafakCount.Text = streamReader.ReadToEnd();
}
}
}
}
}
I want to know why this exception occurred and how it can be resolved.
Thanks in advance.
You are doing it wrong - first you should get SD card, then create folder. As the name KnownFolders.RemovableDevices says devices (not single device) - so you get the first of them as SD card (note that Universal Apps are not only for phones). So the working code can look like this:
// first get the SD card
StorageFolder sdCard = (await KnownFolders.RemovableDevices.GetFoldersAsync()).FirstOrDefault();
// then perform some actions - create folders, files ...
StorageFolder myFolder = await sdCard.CreateFolderAsync("bdfbdfb", CreationCollisionOption.ReplaceExisting);
Note also that you also need to add Capabilities in package.appxmanifest file, and Declarations if you want to use files (File Type Associations).
You will also find more help at MSDN.