0

So here's what I am trying to do and what I have accomplished.

private static T _getjson<T>(string url) where T : new()
        {
            using (var w = new WebClient())
            {
                var json_data = string.Empty;
                // attempt to download JSON data as a string
                try
                {
                    json_data = w.DownloadString(url);
                }
                catch (Exception) { }
                // if string with JSON data is not empty, deserialize it to class and return its instance 
                return !string.IsNullOrEmpty(json_data) ? JsonConvert.DeserializeObject<T>(json_data) : new T();
            }
        }

This method (when called) is used like so:

var onlineornot = ("http://blah.com");
var chatters = _getjson<Rootobject>(onlineornot);

<Rootobject> being a class set up like this:

public class Rootobject
    {
        public _Links _links { get; set; }
        public int chatter_count { get; set; }
        public Chatters chatters { get; set; }
        public Stream stream { get; set; }
        public Stream game { get; set; }
        public _Links2 _links2 { get; set; }
    }

For the most part, it works but it causes my app to hang every time I call _getJson. I was wondering how I could use Async in this case, while maintaining the ability to get the properties from <Rootobject>.

1
  • 1
    _getjson The framework design guidelines are coming to get you, Pat. And WebClient offers async methods. What's the problem with using them? Commented Nov 1, 2017 at 14:19

2 Answers 2

1

The WebClient class has a DownloadStringAsync() method (doc) you can use.

Here is a brief blog post that shows how you can use async/await to prevent your UI from blocking.

ex:

private static async Task<T> _getjson<T>(string url) where T : new()
{
    using (var w = new WebClient())
    {
        var json_data = string.Empty;
        // attempt to download JSON data as a string
        try
        {
            json_data = await w.DownloadStringTaskAsync(url);
        }
        catch (Exception) { }
        // if string with JSON data is not empty, deserialize it to class and return its instance 
        return !string.IsNullOrEmpty(json_data) ? JsonConvert.DeserializeObject<T>(json_data) : new T();
    }
}

public async void Button1_Click(...)
{
    ...
    var onlineornot = ("http://example.com");
    var chatters = await _getjson<Rootobject>(onlineornot);
    ...
}
Sign up to request clarification or add additional context in comments.

8 Comments

as much as i appreciate that response. I have already tried this. This indeed DOES work but does not allow you to call RootObject properties. instead of being able to get public `Chatters chatters { get; set; I get Async properties. Test this code if you dont understand what I mean. when you use chatters.property, it wont be the same as if you used plain DownloadString. It shows me different properties when I use async for deserializing for some reason.
@Pat Miller Are you using the await keyword when calling _getjson()? IE: await _getjson<Rootobject>(onlineornot); instead of _getjson<Rootobject>(onlineornot); If you don't, the call to _getjson will give you a reference to the Task<> object created rather than waiting and giving you a reference to the Rootobject object.
I think you might have solved it you genius <3 :P, let me test lol.
Error CS1503 Argument 1: cannot convert from 'string' to 'System.Uri' and its at this code. json_data = await w.DownloadStringAsync(url);
Ah, yes, DownloadStringTaskAsync() should work, or you can create a Uri object from your string (as I did in the my edit just now): w.DownloadStringAsync(new Uri(url)).
|
1

Quick answer, use WebClient.DownloadStringAsync method: https://msdn.microsoft.com/en-us/library/ms144202(v=vs.110).aspx

Modify your code like this:

private static async Task<T> _getjson<T>(string url) where T : new()
{
    using (var w = new WebClient())
    {
        var json_data = string.Empty;
        // attempt to download JSON data as a string
        try
        {
           json_data = await w.DownloadStringTaskAsync(new Uri(url));
        }
        catch (Exception) { }
        // if string with JSON data is not empty, deserialize it to class and return its instance 
        return !string.IsNullOrEmpty(json_data) ? JsonConvert.DeserializeObject<T>(json_data) : new T();
    }
}

Also, the key thing here is to make sure this is not executed on the main UI thread.

4 Comments

how would i put this method in another thread with a string arg? Also this doesnt allow me to get properties of the RootObject class. When i set a var to _getjson<RootObject>(url) I cant call properties from that var. like i cant get "game" from the class when using chatters.game if I made chatters = _getjson<RootObject>(url). you know what i mean?
Is the RootObject an abstract root class? If so, change the where T : new() to where T : RootObject. Then you have access to the properties. Is that what you are asking?
youre answer was correct as well <3. I thank you a lot.
DownloadStringAsync returns void. Do you mean DownloadStringTaskAsync?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.