I'm working on a Windows Phone 8 app.
I'm having issue appending to my JSON file.
It works fine if I keep the app open but once I close it and come back in it starts back writing from the beginning of the file.
Relevant code:
private async void btnSave_Click(object sender, RoutedEventArgs e)
{
// Create a entry and intialize some values from textbox...
GasInfoEntries _entry = null;
_entry = new GasInfoEntries();
_entry.Gallons = TxtBoxGas.Text;
_entry.Price = TxtBoxPrice.Text;
_GasList.Add(_entry);
//TxtBlockPricePerGallon.Text = (double.Parse(TxtBoxGas.Text) / double.Parse(TxtBoxPrice.Text)).ToString();
// Serialize our Product class into a string
string jsonContents = JsonConvert.SerializeObject(_GasList);
// Get the app data folder and create or open the file we are storing the JSON in.
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFile textfile = await localFolder.CreateFileAsync("gasinfo.json", CreationCollisionOption.OpenIfExists); //if get await operator error add async to class (btnsave)
//open file
using (IRandomAccessStream textstream = await textfile.OpenAsync(FileAccessMode.ReadWrite))
{
//write JSON string
using (DataWriter textwriter = new DataWriter(textstream))
//using (DataWriter textwriter = new DataWriter(textstream))
{
textwriter.WriteString(jsonContents);
await textwriter.StoreAsync(); //writes buffer to store
}
}
}
private async void btnShow_Click(object sender, RoutedEventArgs e)
{
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("gasinfo.json");
using (IRandomAccessStream textstream = await textfile.OpenReadAsync())
{
//read text stream
using (DataReader textreader = new DataReader(textstream))
{
//get size ...not sure what for think check the file size (lenght) then based on next 2 commands waits until its all read
uint textlength = (uint)textstream.Size;
await textreader.LoadAsync(textlength);
//read it
string jsonContents = textreader.ReadString(textlength);
// deserialize back to gas info
_GasList = JsonConvert.DeserializeObject<List<GasInfoEntries>>(jsonContents) as List<GasInfoEntries>;
displayGasInfoEntries();
}
}
}
catch
{
txtShow.Text = "something went wrong";
}
}
private void displayGasInfoEntries()
{
txtShow.Text = "";
StringBuilder GasString = new StringBuilder();
foreach (GasInfoEntries _entry in _GasList)
{
GasString.AppendFormat("Gallons: {0} \r\n Price: ${1} \r\n", _entry.Gallons, _entry.Price); // i think /r/n means Return and New line...{0} and {1} calls "variables" in json file
}
txtShow.Text = GasString.ToString();
}
Thanks
Do you call the btnShow_Click each time you've started the app? Because otherwise the _GasList will be empty; if you now call the btnSave_Click all previous made changes will be lost.
So please make sure, that you restore the previously saved json data before you add items to the _GasList.
Related
I'm trying to read an external json to display data on screen. What am I doing worng here?
public void QuarterlyReport(object sender, EventArgs e)
{
JObject qData1 = JObject.Parse(System.IO.File.ReadAllText(#"~/json/quarterlyData.json"));
// read JSON directly from a file
using (StreamReader file = System.IO.File.OpenText(#"~/json/quarterlyData.json"))
using (JsonTextReader reader = new JsonTextReader(file))
{
JObject Qdata2 = (JObject) JToken.ReadFrom(reader);
}
string Qdata = Newtonsoft.Json.JsonConvert.SerializeObject(qData1);
}
public async Task<FileStreamResult> Index()
{
var _reportingService = new ReportingService("https://mysite.jsreportonline.net", "myemail#gmail.com", "password");
var report = await _reportingService.RenderAsync("VyxOYwH7Ze", new { Qdata });
//add the stream to be used by browser
MemoryStream ms = new MemoryStream();
//copy whatever JS is sending to us
report.Content.CopyTo(ms);
//start at content point
ms.Position = 0;
//send this to browser
return File(ms, report.ContentType.MediaType);
}
I can't seem to get the vaule into the variable Qdata. What is it that I am doing wrong in the method?
The line where you declare Qdata:
string Qdata = Newtonsoft.Json.JsonConvert.SerializeObject(qData1);
is not in the same scope as this line:
var report = await _reportingService.RenderAsync("VyxOYwH7Ze", new { Qdata });
Yes, the problem was that
JObject qData1 = JObject.Parse(System.IO.File.ReadAllText(#"~/json/quarterlyData.json"));
And
string Qdata = Newtonsoft.Json.JsonConvert.SerializeObject(qData1);
Needed to be in the same scope as
var report = await _reportingService.RenderAsync("VyxOYwH7Ze", new { Qdata });
I have a html string and it has local css,js paths. But Html is not working with these local paths. We searced but in every example, they have loaded html with writing inline. But I have to work disconnect and there is so much css,js assests. If i write inline, i am worried about it will load slow and i think it so senseless. Then i decided to change a local html file and load html from that file.
How can i load html from a local file?
This is my example code:
StorageFolder localFolder =
Windows.Storage.ApplicationData.Current.LocalFolder;
string desiredName = "mobile.html";
StorageFile newFile =
await localFolder.CreateFileAsync(desiredName,CreationCollisionOption.OpenIfExists);
using (var stream = await newFile.OpenStreamForWriteAsync())
{
stream.Write(fileBytes, 0, fileBytes.Length);
}
webViewFormResponse.Source = new Uri(newFile.Path);
newFile.Path like this: C:\Data\Users\DefApps\APPDATA\Local\Packages\9f4082ad-ad69-4cb8-8749-751ee4c5e46d_x2xndhe6jjw20\LocalState\mobile.html
You can use the NavigateToLocalStreamUri method of the WebView
e.g.
In WebView Loaded event
private void WebView_Loaded(object sender, RoutedEventArgs e)
{
Uri uri = MyWebView.BuildLocalStreamUri("LocalData", "mobile.html");
LocalUriResolver resolver = new LocalUriResolver();
MyWebView.NavigateToLocalStreamUri(uri, resolver);
}
And the Uri resolver class
public sealed class LocalUriResolver : IUriToStreamResolver
{
public IAsyncOperation<IInputStream> UriToStreamAsync(Uri uri)
{
if (uri == null)
{
throw new Exception();
}
string path = uri.AbsolutePath;
return GetContent(path).AsAsyncOperation();
}
private async Task<IInputStream> GetContent(string uriPath)
{
try
{
Uri localUri = new Uri("ms-appdata:///local" + uriPath);
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(localUri);
IRandomAccessStream stream = await file.OpenReadAsync();
return stream.GetInputStreamAt(0);
}
catch (Exception)
{
throw new Exception("Invalid path");
}
}
}
I'm making a windows phone 8 app of an app I made for windows store, and I am using PhotoChooser task to let the user upload a profile picture.
In the store version i used streams and FileOpenPicker, but i don't know how to use streams with PhotoChooser task.
This is how i did it in windows store, and its perfect:
StorageFile image;
public bunForm()
{
image = null;
this.InitializeComponent();
}
private async void choosePic(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
openPicker.ViewMode = PickerViewMode.Thumbnail;
// Filter to include a sample subset of file types
openPicker.FileTypeFilter.Clear();
openPicker.FileTypeFilter.Add(".bmp");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".jpg");
// Open a stream for the selected file
var file = await openPicker.PickSingleFileAsync();
if (file != null)
{
image = file;
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
bunPic.Visibility = Visibility.Visible;
// Ensure a file was selected
if (file != null)
{
// Ensure the stream is disposed once the image is loaded
using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
// Set the image source to the selected bitmap
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);// bitmapImage.UriSource.ToString();
bunPic.Source = bitmapImage;
}
}
}
}
And here is how i'm trying it at windows Phone 8:
But (openPicker.PickSingleFileAsync();) line gives me error.
public BunForm()
{
InitializeComponent();
image = null;
this.photoChooserTask = new PhotoChooserTask();
this.photoChooserTask.Completed += new EventHandler<PhotoResult>(photoChooserTask_Completed);
}
StorageFile image;
private void choosePic(object sender, RoutedEventArgs e)
{
photoChooserTask.Show();
}
private async void photoChooserTask_Completed(object sender, PhotoResult e)
{
//this is the only line that gives me error
var file = await openPicker.PickSingleFileAsync();
///
if (file != null)
{
image = file;
var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
if (file != null)
{
// Ensure the stream is disposed once the image is loaded
using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
MessageBox.Show(e.ChosenPhoto.Length.ToString());
//Code to display the photo on the page in an image control named myImage.
System.Windows.Media.Imaging.BitmapImage bmp = new System.Windows.Media.Imaging.BitmapImage();
bmp.SetSource(e.ChosenPhoto);
myImage.Source = bmp;
}
}
}
Debug.WriteLine("pic done");
}
I was wondering how i can save the image in storage file in windows phone 8?
As noted on MSDN pages - OpenFilePicker cannot be used in C# WP8 apps, but you can use the PhotoChooserTask with ease for uploadng the profile picture:
// first invoke the task somewhere
PhotoChooserTask task = new PhotoChooserTask();
task.Completed += task_Completed;
task.Show();
// handle the result
async void task_Completed(object sender, PhotoResult e)
{
// no photo selected
if (e.ChosenPhoto == null) return;
// get the file stream and file name
Stream photoStream = e.ChosenPhoto;
string fileName = Path.GetFileName(e.OriginalFileName);
// persist data into isolated storage
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (Stream current = await file.OpenStreamForWriteAsync())
{
await photoStream.CopyToAsync(current);
}
...
// how to read the data later
StorageFile file2 = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
Stream imageStream = await file2.OpenStreamForReadAsync();
// display the file as image
BitmapImage bi = new BitmapImage();
bi.SetSource(imageStream);
// assign the bitmap to Image in XAML: <Image x:Name="img"/>
img.Source = bi;
}
Accoriding to this
Windows Phone 8
This API is supported in native apps only.
You can't use FileOpenPicker class.
There are already answers to the problem OpenFilePicker not working
Given some list of objects:
List<Car> carlist = new List<Car>();
How can I serialize this list as an XML or binary file and deserialize it back?
I have this so far but it doesn't work.
//IsolatedStorageFile isFile = IsolatedStorageFile.GetUserStoreForApplication();
//IsolatedStorageFileStream ifs = new IsolatedStorageFileStream("myxml.xml", FileMode.Create,isFile);
//DataContractSerializer ser = new DataContractSerializer();
//XmlWriter writer = XmlWriter.Create(ifs);
//ser.WriteObject(writer, carlist);
I'm using these methods to Save and Load from a XML file in/to the IsolatedStorage :
public static class IsolatedStorageOperations
{
public static async Task Save<T>(this T obj, string file)
{
await Task.Run(() =>
{
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
IsolatedStorageFileStream stream = null;
try
{
stream = storage.CreateFile(file);
XmlSerializer serializer = new XmlSerializer(typeof (T));
serializer.Serialize(stream, obj);
}
catch (Exception)
{
}
finally
{
if (stream != null)
{
stream.Close();
stream.Dispose();
}
}
});
}
public static async Task<T> Load<T>(string file)
{
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
T obj = Activator.CreateInstance<T>();
if (storage.FileExists(file))
{
IsolatedStorageFileStream stream = null;
try
{
stream = storage.OpenFile(file, FileMode.Open);
XmlSerializer serializer = new XmlSerializer(typeof (T));
obj = (T) serializer.Deserialize(stream);
}
catch (Exception)
{
}
finally
{
if (stream != null)
{
stream.Close();
stream.Dispose();
}
}
return obj;
}
await obj.Save(file);
return obj;
}
}
You can customize the error handling in the catch().
Also, you can adjust the Load method to your needs, in my case I am trying to load from a file and if doesn't exist, it creates a default one and puts the default serialized object of the type provided according to the constructor.
UPDATE :
Let's say you have that list of cars :
List< Car > carlist= new List< Car >();
To save, you can just call them as await carlist.Save("myXML.xml"); , as it is an asynchronous Task(async).
To load, var MyCars = await IsolatedStorageOperations.Load< List< Car> >("myXML.xml"). (I think, I haven't used it like this, as a List so far...
DataContactJsonSerializer performs better than XmlSerializer. It creates smaller files and handles well lists inside properties.
I have a byte[] containing picture data. I want to set this picture data as a display picture of a StoredContact in windows phone 8. I have tried:
byte[] data = ...
ContactStore store = await ContactStore.CreateOrOpenAsync(ContactStoreSystemAccessMode.ReadWrite, ContactStoreApplicationAccessMode.ReadOnly);
StoredContact contact = await store.FindContactByRemoteIdAsync(remoteId);
using (IInputStream stream = new MemoryStream(data).AsInputStream())
{
await contact.SetDisplayPictureAsync(stream);
}
but i get System.UnauthorizedAccessException on the AsInputStream()-call. I have the ID_CAP_CONTACTS-capability set and the contact belongs to a custom data store, to which i have write access. Anyone know how to solve this?
EDIT:
I get the data from a web request, using the following to extract the byte data:
DataContractJsonSerializer serializer = new DataContractJsonSerializer(new PhotoObject().GetType());
var result = (PhotoObject)serializer.ReadObject(stream);
byte[] data = Convert.FromBase64String(result.Data);
[DataContract]
class PhotoObject
{
[DataMember(Name = "size")]
public string Size { get; set; }
[DataMember(Name = "data")]
public string Data { get; set; }
}
I finally managed to get around this problem. The first thing I did was to create the stream using:
new MemoryStream(data, 0, data.Length, true, true).AsInputStream();
instead of
new MemoryStream(data).AsInputStream();
This got rid of the UnauthorizedException, however it gave me an ArgumentException: "Value does not fall within the expected range" on the SetDisplayPictureAsync-call instead. I still do not know why it works, but i got around this by writing the data to temporary file, which I then open and pass to SetDisplayPictureAsync. This is my code for doing this:
//Write bytes to file then open file and pass stream to setdisplaypicture.
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
var folder = await localFolder.CreateFolderAsync("Photo_Temp_Folder", CreationCollisionOption.OpenIfExists);
var file = await folder.CreateFileAsync("photo_" + contact.Id, CreationCollisionOption.ReplaceExisting);
uint written = 0;
using (var writeStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
while (written < data.Length)
{
written += await writeStream.WriteAsync(data.AsBuffer());
}
}
using (var accessStream = await file.OpenAsync(FileAccessMode.Read))
{
await contact.SetDisplayPictureAsync(accessStream);
await contact.SaveAsync();
}
await file.DeleteAsync();
Hope it helps someone.