WPF async httpclient not returning string - c#

public RSS_Reader()
{
this.InitializeComponent();
}
public static async Task<string> DownloadPageAsync(string pageURL)
{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("http://www.parliament.uk/g/RSS/news-feed/?pageInstanceId=209&limit=20");
HttpContent content = response.Content;
string result = await content.ReadAsStringAsync();
return result;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var parameter = e.Parameter as string;
strURL = parameter.ToString();
Task<string> strXML = DownloadPageAsync(strURL);
ListBoxRss.Items.Add(strXML.Result);
}
Part of a wp8 app I've been making. There's the main landing page of the app which links to the second page from where I took the code above. Second page never actually loads and it just hangs on the first page.
What have I done wrong?
Thanks.

You should make the OnNavigatedTo method async and await the DownloadPageAsync method:
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
var parameter = e.Parameter as string;
strURL = parameter.ToString();
string strXML = await DownloadPageAsync(strURL);
ListBoxRss.Items.Add(strXML);
}

Related

Using async with c# windows form

I'm new to working with API's so bare with me. I'm trying to load 3 images into picture boxes by using the Bing Image Search API but I'm having trouble with my async method. From my POV everything looks like it should be working just fine. (I used this documentation for my code https://learn.microsoft.com/en-us/bing/search-apis/bing-image-search/quickstarts/sdk/image-search-client-library-csharp). Any advice would be greatly appreciated.
private static string _subscriptionKey = "MY_API_KEY";
private static string _baseUri = "https://api.bing.microsoft.com/v7.0/images/search";
private static string searchString = "car";
private static string _clientIdHeader = null;
private const string QUERY_PARAMETER = "?q="; // Required
private const string MKT_PARAMETER = "&mkt="; // Strongly suggested
private void searchButton_Click(object sender, EventArgs e)
{
RunAsync().Wait();
static async Task RunAsync()
{
try
{
// Remember to encode the q query parameter.
var queryString = QUERY_PARAMETER + Uri.EscapeDataString(searchString);
queryString += MKT_PARAMETER + "en-us";
HttpResponseMessage response = await MakeRequestAsync(queryString);
_clientIdHeader = response.Headers.GetValues("X-MSEdge-ClientID").FirstOrDefault();
// This example uses dictionaries instead of objects to access the response data.
var contentString = await response.Content.ReadAsStringAsync();
Dictionary<string, object> searchResponse = JsonConvert.DeserializeObject<Dictionary<string, object>>(contentString);
if (response.IsSuccessStatusCode)
{
PrintImages(searchResponse);
}
}
catch (Exception)
{
}
async Task<HttpResponseMessage> MakeRequestAsync(string queryString)
{
string count = "3";
string offset = "0";
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", _subscriptionKey);
return await client.GetAsync(string.Format("{0}q={1}&count={1}", _baseUri + queryString, count, offset));
}
void PrintImages(Dictionary<string, object> response)
{
var images = response["value"] as Newtonsoft.Json.Linq.JToken;
foreach (Newtonsoft.Json.Linq.JToken image in images)
{
string imagePic = (image["contentUrl"]).ToString();
optionOnePicture.ImageLocation = imagePic;
optionTwoPicture.ImageLocation = imagePic;
optionThreePicture.ImageLocation = imagePic;
}
}
}
Don't block on async code. Instead, use await:
private async void searchButton_Click(object sender, EventArgs e)
{
await RunAsync();
...
}
Side note: this code is using async void because the method is an event handler. Normally, you would want to avoid async void.

Async Method not Returning a String

I am trying to get some weather data from Open Weather Maps and l use HTTPClient and API ASP.NET in C#.
My code keeps returning:
System.Threading.Tasks.Task`1[System.String]
I've made my methods async and await but I still get the above returned. I thought making it await would return the value.
I am just trying to get the string from Open Weather Maps, I'll worry about parsing it to JSON once I have this working. Here is my code, "MY_APPID" is replaced with my API key, I just removed it here.
My main:
private async Task<string> GetLocationJson()
{
const string APPID = "(MY_APPID)";
const string LOCATIONID = "2172797";
string jsonAsString = "";
string callStringJson = "api.openweathermap.org/data/2.5/weather?id=" + LOCATIONID + "&appid=" + APPID;
ApiCalls weatherApi = new ApiCalls(callStringJson);
jsonAsString = await weatherApi.GetLocationJson();
return jsonAsString;
}
//ShowLocationJson is called on button click
protected void ShowLocationJson(object sender, EventArgs e)
{
litOutput.Text = GetLocationJson().ToString();
}
And my ApiCalls Class is:
public class ApiCalls
{
HttpClient client = new HttpClient();
Uri url;
public ApiCalls(string link)
{
url = new Uri("https://" + link);
}
public async Task<string> GetLocationJson()
{
string content = await client.GetStringAsync(url);
return content;
}
}
url variable is being passed the correct values so I know it's ok up to there.
Im using ASP.NET Framework 4.5 as well
As Steve and mason have already noticed you have to await all methods returning Task. You need to change your ShowLocationMethod to:
protected async void ShowLocationJson(object sender, EventArgs e)
{
litOutput.Text = await GetLocationJson();
}
You receive System.Threading.Tasks.Task1[System.String] because you call method ToString() of Task object. The default implementation of the ToString method returns the fully qualified name of the type of the object: Task<String>

Xamarin Forms Webpage call never returns result

I have this code:
public async Task<List<Template>> GetTemplates(User user)
{
var postData = new List<KeyValuePair<string, string>>();
postData.Add(new KeyValuePair<string, string>("un", user.Username));
postData.Add(new KeyValuePair<string, string>("pw", user.Password));
var content = new FormUrlEncodedContent(postData);
var weburl = "myapp.org/get_templates.php";
var response = await PostResponseTemplates<Template>(weburl, content);
return response;
}
public async Task<List<Template>> PostResponseTemplates<List>(string weburl, FormUrlEncodedContent content)
{
var response = await client.PostAsync(weburl, content);
var json = response.Content.ReadAsStringAsync().Result;
.......
}
But the webcall never returns the result after this line: var response = await client.PostAsync(weburl, content);.
What am I doing wrong?
UPDATE
Here is the void where I call the function right now:
public MemeTemplateList()
{
InitializeComponent();
LoadTemplateList();
}
private void LoadTemplateList()
{
var templateList = App.RestService.GetTemplates(App.User);
....
How to create this async and run it in the page constructor?
Mixing async-await and blocking calls like .Result
public async Task<List<Template>> PostResponseTemplates<List>(string weburl, FormUrlEncodedContent content) {
var response = await client.PostAsync(weburl, content);
var json = response.Content.ReadAsStringAsync().Result; //<--THIS WILL DEADLOCK
//...omitted for brevity
can cause deadlock. Which is why the function does not return.
Remove .Result and make the code async all the way though
public async Task<List<Template>> PostResponseTemplates<List>(string weburl, FormUrlEncodedContent content) {
var response = await client.PostAsync(weburl, content);
var json = await response.Content.ReadAsStringAsync(); //<--THIS
//...omitted for brevity
I would also suggest changing the function definition from being generic
public async Task<List<Template>> PostResponseTemplates(string weburl, FormUrlEncodedContent content) {
//...
}
Since the type is already known within the function
List<Template> response = await PostResponseTemplates(weburl, content);
Finally make sure everything is async all the way up the call stack
public MemeTemplateList() {
InitializeComponent();
//Subscribe to event
loadingTemplates += onLoadingTemplates;
//raise the event to load the templates.
LoadTemplateList();
}
private event EventHandler loadingTemplates = delegate { };
//ASYNC VOID ONLY ALLOWED ON EVENT HANDLER!!!!!!!
private async void onLoadingTemplates(object sender, EventArgs args) {
List<Template> templateList = await App.RestService.GetTemplates(App.User);
//....
}
private void LoadTemplateList() {
loadingTemplates(this, EventArgs.Empty);
}
Reference Async/Await - Best Practices in Asynchronous Programming

Xamarin HttpClient stuck and does not return control

I can't understand why the main thread doesn't give back control to process the result.
public partial class NewTravelPage : ContentPage
{
public NewTravelPage()
{
InitializeComponent();
}
protected async override void OnAppearing()
{
var locator = CrossGeolocator.Current;
var position = await locator.GetPositionAsync();
var vanues = await VenueLogic.getVenues(position.Latitude, position.Longitude);
venueListView.ItemsSource = vanues;
}
}
I call the method getVenues:
public class VenueLogic
{
public async static Task<List<Venue>> getVenues(double latitude, double longitude)
{
List<Venue> vanues = new List<Venue>();
var url = VenueRoot.GenerateUrl(latitude, longitude);
using (HttpClient client = new HttpClient())
{
var res = await client.GetAsync("https://stackoverflow.com");
// here the code gives control to the main thread and stucks
var response = await res.Content.ReadAsStringAsync();
var venueRoot = JsonConvert.DeserializeObject<VenueRoot>
(response);
vanues = venueRoot.response.venues as List<Venue>;
}
return vanues;
}
}
Used .NetStandard;
Please, help! I can't understand where the deadlock happens
Your async void on a non event handler means your fire and forget call will not be able to catch any exceptions that may have been thrown.
Reference Async/Await - Best Practices in Asynchronous Programming
Fix that by using an event handler
public partial class NewTravelPage : ContentPage {
public NewTravelPage() {
InitializeComponent();
appearing += onAppearing;
}
protected override void OnAppearing() {
appearing(this, EventArgs.Empty);
}
event EventHandler appearing = delegate { };
private async void onAppearing(object sender, EventArgs args) {
try {
var locator = CrossGeolocator.Current;
var position = await locator.GetPositionAsync();
var vanues = await VenueLogic.getVenues(position.Latitude, position.Longitude);
venueListView.ItemsSource = vanues;
} catch( Exception ex) {
//handler error (Log?)
}
}
}
Which would help in catching any exception to identify any problems.
Next, Referencing You're using HttpClient wrong
public class VenueLogic {
static HttpClient client = new HttpClient();
public async static Task<List<Venue>> getVenues(double latitude, double longitude) {
var url = VenueRoot.GenerateUrl(latitude, longitude);
var response = await client.GetAsync(url);
var jsonContent = await response.Content.ReadAsStringAsync();
var venueRoot = JsonConvert.DeserializeObject<VenueRoot>(jsonContent);
List<Venue> vanues = venueRoot.response.venues as List<Venue>;
return vanues;
}
}
create a single client and use that for the lifetime of the application.
Finally I would suggest you look into using Dependency injection to inject service instances where needed instead of using those static helpers
Reference Explicit Dependencies Principle

Convert Task<String> to String in Windows 8 apps

I writing a Windows 8 app. I have a code :
public async Task<string> readweb()
{
var uri = new Uri(#"http://stackoverflow.com/");
var httpClient = new HttpClient();
var data = await httpClient.GetStringAsync(uri);
string text = data;
return text;
}
i want to get web-data by string data = readweb(); but it error "cannot convert task to string". Help me! Thanks!
Do like this,
public async Task<string> readweb()
{
var uri = new Uri(#"http://stackoverflow.com/");
var httpClient = new HttpClient();
var data = await httpClient.GetStringAsync(uri);
string text = data;
return text;
}
private async void Something()
{
var data = await readweb();
}

Categories