I am making a UWP app in which I am trying to save storage files picked by user to the local settings by serializing them, and I want to deserialize them and use them again when I want to. it saves IReadOnlyList object to the local settings just fine, but at the time of deserializing it gives and exception, that this method cant return storage files because it doesnt have a constructor for this, something like this. I am posting the code of my both methods of saving and loading data. please see it and help me...
public static void SaveState<T>(string key, T value)//save method
{
//key is provided by me so that i can use it to load the data later.
var localSettings = ApplicationData.Current.LocalSettings;
localSettings.Values[key] = JsonConvert.SerializeObject(value);
}
public static T LoadState<T>(string key)//loading data
{
var localSettings = ApplicationData.Current.LocalSettings;
if (localSettings.Values.ContainsKey(key))//exception occurs on the below line
return JsonConvert.DeserializeObject<T>(((string)localSettings.Values[key]));
return default(T);
}
and I use these methods as follows:-
var files = StateService.LoadState<IReadOnlyList<StorageFile>>(Playlist);
//StateService is the class which has these static methods...
Note: when i try to load data with a key which has no data against it in the local settings, it doesnt give any exception and just returns an empty list.but when its supposed to return a filled list of IReadOnlyList then it gives and exception...
I think that JsonConvert.DeserializeObject tries to instantiate IReadOnlyList<StorageFile> but interfaces cannot be instantiated... you should use for example List<StorageFile> as T for setting and reading the list...
I did something like that before and I had the same problem. I did different approach instead of trying to save the StorageFile I saved the json content with the key and always my data is in string ( the json data) and I can use JsonConvert.DeserializeObject<T> without problems.
Related
Currently trying to make a system that will change a button's color based on if the streamer on the button is live or not. I have a way to download the json string into a variable but I don't know what to do with that. I know I have to check if the variable "stream" in the json output is null which means the streamer is offline but I have 0 clue on how to do that.
I'll edit it with the code that I currently have. I got the json being properly parsed, doing r.stream gives me the appropriate data, but I can't figure out how to figure out if the stream is live or not. This is supposed to check on button press which will refresh the data.
private void Refresh_Click(object sender, RoutedEventArgs e)
{
string url = #"https://api.twitch.tv/kraken/streams/camoduck?client_id=xskte44y2wfqin464ayecyc09nikcj";
var json = new WebClient().DownloadString(url);
Rootobject r = JsonConvert.DeserializeObject<Rootobject>(json);
Console.WriteLine(r.stream);
if r.stream.game = "Grand Theft Auto V"
{
_1GUnit1.Background = Brushes.Red;
}
}
.......
var json = new WebClient().DownloadString(url);
var r = JsonConvert.DeserializeObject<Rootobject>(json);
Console.WriteLine(r.stream);
if (r.stream==null) //How a null check can be done
{
_1GUnit1.Background = Brushes.Red;
}
BTW: If you are using "http://json2csharp.com/", It is propably RootObject not Rootobject
Without you providing more details about what doesn't work in your case, I can't give an in-depth explanation or guidance.
What I can suggest is that you a use an API wrapper, e.g. TwitchLib.
That should help you get started and should provide enough documentation for your case.
You should do more reading on the Twitch API and search for examples. When the stream is offline, consider dropping in some sort of template as there is no data to from the request to parse. When a stream is online, you will have access to the stream object's properties. For example, if your success function returns data, you can assign the results as:
game = data.stream.game;
logo = data.stream.channel.logo;
name = data.stream.channel.name;
url = data.stream.channel.url;
stream = data.stream.stream_type;
This assumes you've setup the appropriate variables (you didn't provide any code).
I would also recommend you spend some time learning how to debug in the browser. More specifically in this case, learn how to inspect your result data. This will demystify what's in the object as you'll see the data and its properties, etc.
Have a look at the following Stack post:
Inspecting large JSON data in Chrome
I've implemented a file upload in ASP.Net MVC. I've created a view model that received the uploaded file as an HttpPostedFileWrapper and within the controller action I can save the file to disk.
However, I want to perform the actual save in service method which is in a class library that doesn't implement System.Web. I can't therefore pass the HttpPostedFileWrapper object to the service method.
Does anyone know how to achieve this, either by receiving the file as a different object or converting it to something else prior to passing it. The only way I can think of is to read the content of the file into a MemoryStream, and pass this along with the other parameters such as filename individually, but just wondered if there was a better way?
Thanks
The best approach would probably be retrieving the image data (as a byte[]) and the name of the image (as a string) and passing those along to your service, similar to the approach you mentioned :
public void UploadFile(HttpPostedFileWrapper file)
{
// Ensure a file is present
if(file != null)
{
// Store the file data
byte[] data = null;
// Read the file data into an array
using (var reader = new BinaryReader(file.InputStream))
{
data = reader.ReadBytes(file.ContentLength);
}
// Call your service here, passing along the data and file name
UploadFileViaService(file.FileName, data);
}
}
Since a byte[] and a string are very basic primatives, you should have no problem passing them to another service. A Stream is likely to work as well, but they can be prone to issues like being closed, whereas a byte[] will already have all of your content.
I'm working on an UWP application where a user can input data which is placed in a listview. All fine and dandy, but how can I save the user data to a separate file and load it the next time a user boots up the app?
I've tried to find a solution, but I had great difficulty to understand these code snippets and on how to apply these (since I'm fairly new to C# and App development). Would somebody like to explain how I can achieve the saving/loading of the data and explain what the code does?
Thanks in advance! :)
You can create a file like this:
StorageFile ageFile = await local.CreateFileAsync("Age.txt", CreationCollisionOption.FailIfExists);
I can read and write to a file like this:
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
var ageFile = await local.OpenStreamForReadAsync(#"Age.txt");
// Read the data.
using (StreamReader streamReader = new StreamReader(ageFile))
{
//Use like a normal streamReader
}
if you are trying to write, use OpenStreamForWriteAsync;
If I understood well, you have some kind of object structure that serves as a model for your ListView. When the application is started, you want to read a file where the data is present. When closing the application (or some other event) write the file with the changes done. Right?
1) When your application is loaded / closed (or upon modifications or some event of your choice), use the Windows.Storage API to read / write the text into the file.
2) If the data you want to write is just a liste of strings, you can save this as is in the file. If it is more complicated, I would recommend serializing it in JSON format. Use JSON.NET to serialize (object -> string) and deserialize (object <- string) the content of your file and object structure.
Product product = new Product();
product.Name = "Apple";
...
string json = JsonConvert.SerializeObject(product);
Is there a way to store custom properties within a file I upload? i.e. I need a simple way to store a metadata for the files I upload.
The only way I found is, to store the data in the "description" property, like:
string id = await FetchFileId(fileName);
var fileData = new Dictionary<string, object>();
fileData.Add("description", "here goes json data or something similar");
LiveOperationResult operationResult = await client.PutAsync(id, fileData);
Is there a better way?
Unfortunately there's no supported way to set custom metadata right now. We don't recommend using the 'description' property for that, either, as it's meant to be a human-readable description that's displayed in OneDrive apps.
I have a text file with a list of 300,000 words and the frequency with wich they occur. Each line is in the format Word:FequencyOfOccurence.
I want this information to be accessible from within the C# code. I can't hard code the list since it is too long, and I'm not sure how to go about accessing it from a file on the server. Ideally I'd ideally like the information to be downloaded only if it's used (To save on bandwidth) but this is not a high priority as the file is not too big and internet speeds are always increasing.
It doesn't need to be useable for binding.
The information does not need to be editable once the project has been built.
Here is another alternative. Zip the file up and stick it in the clientBin folder next to the apllication XAP. Then at the point in the app where the content is needed do something like this:-
public void GetWordFrequencyResource(Action<string> callback)
{
WebClient client = new WebClient();
client.OpenReadAsync += (s, args) =>
{
try
{
var zipRes = new StreamResourceInfo(args.Result, null)
var txtRes = Application.GetResourceStream(zipRes, new Uri("WordFrequency.txt", UriKind.Relative));
string result = new StreamReader(txtRes.Stream).ReadToEnd();
callback(result);
}
catch
{
callback(null); //Fetch failed.
}
}
client.OpenReadAsync(new Uri("WordFrequency.zip", UriKind.Relative"));
}
Usage:-
var wordFrequency = new Dictionary<string, int>();
GetWordFrequencyResource(s =>
{
// Code here to burst string into dictionary.
});
// Note code here is asynchronous with the building of the dictionary don't attempt to
// use the dictionary here.
The above code allows you to store the file in an efficient zip format but not in the XAP itself. Hence you can download it on demand. It makes use of the fact that a XAP is a zip file so Application.GetResourceStream which is designed to pull resources from XAP files can be used on a zip file.
BTW, I'm not actually suggesting you use a dictionary, I'm just using a dictionary as simple example. In reality I would imagine the file is in sorted order. If that is the case you could use a KeyValuePair<string, int> for each entry but create a custom collection type that holds them in an array or List and then use some Binary search methods to index into it.
Based on your comments, you could download the word list file if you are required to have a very thin server layer. The XAP file containing your Silverlight application is nothing more than a ZIP file with all the referenced files for your Silverlight client layer. Try adding the word list as content that gets compiled into the XAP and see how big the file gets. Text usually compresses really well. In general, though, you'll want to be friendly with your users in how much memory your application consumes. Loading a huge text file into memory, in addition to everything else you need in your app, may untimately make your app a resource hog.
A better practice, in general, would be to call a web service. The service could would perform whatever look up logic you need. Here's a blog post from a quick search that should get you started: (This was written for SL2, but should apply the same for SL3.)
Calling web services with Silverlight 2
Even better would be to store your list in a SQL Server. It will be much easier and quicker to query.
You could create a WCF service on the server side that will send the data to the Silverlight application. Once you retrieve the information you could cache it in-memory inside the client. Here's an example of calling a WCF service method from Silverlight.
Another possibility is to embed the text file into the Silverlight assembly that is deployed to the client:
using (var stream = Assembly.GetExecutingAssembly()
.GetManifestResourceStream("namespace.data.txt"))
using (var reader = new StreamReader(stream))
{
string data = reader.ReadToEnd();
// Do something with the data
}