C#/XAML HTTPclient/webrequest GET with await never ends - c#

Why won't this HTTPHandler work? Both getPageBody and getPageContent await forever and never get back to me. Nothing else happens after the await (used a break point).
Any help would be strongly appreciated!
PS: Visiting the page in the browser does work - so the problem must be on the C# end.
public class HTTPHandler
{
public static async Task<List<String>> getPageBody(String page)
{
WebRequest request = WebRequest.Create(
"http://www.mywebsite.com/dev/api/" + page);
request.Credentials = CredentialCache.DefaultCredentials;
WebResponse response = await request.GetResponseAsync();
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
//reader.Close();
//response.Close();
return responseFromServer.Split(';').ToList();
}
public static async Task<List<String>> getPageContents(String page)
{
HttpClient client = new HttpClient();
Task<HttpResponseMessage> resp;
await (resp = client.GetAsync("http://www.mywebsite.com/dev/api/" + page)).ContinueWith(
(getTask) =>
{
getTask.Result.EnsureSuccessStatusCode();
});
//HttpResponseMessage resp = await client.GetAsync("http://mywebsite.com/dev/api/" + page);
Task<String> responseBodyAsText = resp.Result.Content.ReadAsStringAsync();
responseBodyAsText.Wait();
return responseBodyAsText.Result.Split(';').ToList();
}
}

I suspect that further up your call stack, you're using Task.Wait or Task.Result.
If you use Wait or Result on async code, you run the risk of deadlock. I explain this in more detail on my blog and in a recent MSDN article.

Related

How to send POST with form data in C#

I am trying to make a program that requests my website with a username, password, hardware ID and a key in POST.
I have this code here that should send a POST request to my website with that form data, but when it sends, my webserver reports back that it didn't receive the POST data
try
{
string poststring = String.Format("username={0}&password={1}&key={2}&hwid={3}", Username, Password, "272453745345934756392485764589", GetHardwareID());
HttpWebRequest httpRequest =
(HttpWebRequest)WebRequest.Create("mywebsite");
httpRequest.Method = "POST";
httpRequest.ContentType = "application/x-www-form-urlencoded";
byte[] bytedata = Encoding.UTF8.GetBytes(poststring);
httpRequest.ContentLength = bytedata.Length;
Stream requestStream = httpRequest.GetRequestStream();
requestStream.Write(bytedata, 0, bytedata.Length);
requestStream.Close();
HttpWebResponse httpWebResponse =
(HttpWebResponse)httpRequest.GetResponse();
Stream responseStream = httpWebResponse.GetResponseStream();
StringBuilder sb = new StringBuilder();
using (StreamReader reader =
new StreamReader(responseStream, System.Text.Encoding.UTF8))
{
string line;
while ((line = reader.ReadLine()) != null)
{
sb.Append(line);
}
}
return sb.ToString();
}
catch (Exception Error)
{
return Error.ToString();
}
If someone could help me, I would really appreciate it.
As per HttpWebRequest documentation
We don't recommend that you use HttpWebRequest for new development. Instead, use the System.Net.Http.HttpClient class.
HttpClient contains only asynchronous API because Web requests needs awaiting. That's not good to freeze entire Application while it's pending response.
Thus, here's some async function to make POST request with HttpClient and send there some data.
First of all, create HttpClient seperately because
HttpClient is intended to be instantiated once per application, rather than per-use.
private static readonly HttpClient client = new HttpClient();
Then implement the method.
private async Task<string> PostHTTPRequestAsync(string url, Dictionary<string, string> data)
{
using (HttpContent formContent = new FormUrlEncodedContent(data))
{
using (HttpResponseMessage response = await client.PostAsync(url, formContent).ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
}
}
Or C# 8.0
private async Task<string> PostHTTPRequestAsync(string url, Dictionary<string, string> data)
{
using HttpContent formContent = new FormUrlEncodedContent(data);
using HttpResponseMessage response = await client.PostAsync(url, formContent).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
}
Looks easier than your code, right?
Caller async method will look like
private async Task MyMethodAsync()
{
Dictionary<string, string> postData = new Dictionary<string, string>();
postData.Add("message", "Hello World!");
try
{
string result = await PostHTTPRequestAsync("http://example.org", postData);
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
If you're not familiar with async/await, it's time to say Hello.

How to make a http web asyncGET request

I want to make a get request. Here is the code I tested:
public string Get(string uri)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AutomaticDecompression = DecompressionMethods.GZip
| DecompressionMethods.Deflate;
using(HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using(Stream stream = response.GetResponseStream())
using(StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
but the problem is it will freeze GUI and I found this code:
public async Task<string> GetAsync(string uri)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AutomaticDecompression = DecompressionMethods.GZip
| DecompressionMethods.Deflate;
using(HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync())
using(Stream stream = response.GetResponseStream())
using(StreamReader reader = new StreamReader(stream))
{
return await reader.ReadToEndAsync();
}
}
but I am not good at multitasking.
anyhelp how to use this function?
tnx
You are almost there. All you need to do is to call GetAsync function with await and you will get the desired result.
Please do not forget to include async in the signature of calling function. Support you have GetText from where you want to use GetAsync then code snippet would be:
private async void GetText()
{
string str = await GetAsync(url);
}
I don't know what do you want to do, but you can try to remove the usings because you only need to add the usings in the imports section and try to use your method more like this:
public class HttpHandler
{
static HttpClient client = new HttpClient();
public async Task<string> Get(string apiURL)
{
HttpResponseMessage response = await client.GetAsync(apiURL);
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
return await reader.ReadToEndAsync();
}
}

Application works in Debug - Fails when compiled

I have a situation I just don't understand.
I have a c# class library application that works perfectly when I step through it in debug mode within VS2017.
When I compile it in "Debug" mode and call it from a console app it fails when calling a https API endpoint and does not report any error.
This is how I am calling the "CreateOrder":
// send the order to DNAGenotek
DNAGenotek.Model.Order.CreateResponse.CreateOrderResponse orderResponse = await DNAGenotek.Orders.CreateOrder(DNAGenotekAPIKey, DNAGenotekOrder);
This is how I am calling the "CallAPIString" function:
public static async Task<Model.Order.CreateResponse.CreateOrderResponse> CreateOrder(string APIKey, Model.Order.Create.Order order)
{
// convert the object to a string
string orderAsString = JsonConvert.SerializeObject(order);
// create the order
string result = await Helpers.CallAPIString(APIKey, "https://sofia-stage.dnagenotek.com/api/v2/orders", "POST", orderAsString);
DNAGenotek.Model.Order.CreateResponse.CreateOrderResponse orderResponse = JsonConvert.DeserializeObject<Model.Order.CreateResponse.CreateOrderResponse>(result);
return orderResponse;
}
I have attached to the running console .exe and stepped through and it fails on this line when doing a POST
WebResponse httpResponseGETDELETE = await httpWebRequest.GetResponseAsync();
In the following code:
public static async Task<string> CallAPIString(string APIKey, string url, string method, string bodyContent = null)
{
try
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.Method = method;
httpWebRequest.ContentType = "application/json";
httpWebRequest.Headers.Add("Authorization", "Basic " + APIKey);
switch (method)
{
case "GET":
case "DELETE":
WebResponse httpResponseGETDELETE = await httpWebRequest.GetResponseAsync();
using (StreamReader streamReader = new StreamReader(httpResponseGETDELETE.GetResponseStream()))
{
string result = await streamReader.ReadToEndAsync();
return result;
}
case "POST":
case "PUT":
case "PATCH":
using (StreamWriter streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
await streamWriter.WriteLineAsync(bodyContent);
await streamWriter.FlushAsync();
streamWriter.Close();
WebResponse httpResponsePOSTPUT = await httpWebRequest.GetResponseAsync();
using (StreamReader streamReader = new StreamReader(httpResponsePOSTPUT.GetResponseStream()))
{
string result = await streamReader.ReadToEndAsync();
return result;
}
}
default:
return "Method Not Found!";
}
}
catch (Exception e)
{
return e.Message;
}
}
It doesn't even bubble up to the catch line. It just closes the app.
When I watch the network traffic in Fiddler I can see it attempting to open the https connection but it then stalls.
This is what I see in Fiddler:
I am complete stumped how to get to the root cause without an error message?
UPDATE
I have now rewritten my code using the HttpClient and it now fails at the line:
HttpResponseMessage response = await client.PostAsync(url, content);
in this code:
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Basic " + APIKey);
StringContent content = new StringContent(bodyContent, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
return await response.Content.ReadAsStringAsync();
}
OK - this was my fault.
In the console application I was using :
SyncEngine.Functions.Sync("APIKey1", "APIKey2");
When I should have been using:
SyncEngine.Functions.Sync("APIKey1", "APIKey2").GetAwaiter().GetResult();
Sorry guys

C# - Getting response from WebResponse

I'm trying to download XML source code of RSS feed placed in the internet, but when my process reaches WebResponse statement (second line bellow) process stops and nothing next is happening. There si no error, no exception or nothing like that. I'm waiting for tens of minutes and still nothing happening.
WebRequest request = WebRequest.Create(source.Url);
WebResponse response = await request.GetResponseAsync(); // at this line it stops
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream);
string xml = readStream.ReadToEnd().Trim();
readStream.Dispose();
response.Dispose();
Any idea what causing it?
EDIT:
public static async Task<string> GetContent(string uri)
{
WebRequest request = WebRequest.Create(url);
using (WebResponse response = await request.GetResponseAsync().ConfigureAwait(false))
{
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream);
return readStream.ReadToEnd().Trim();
}
}
public async Task<ObservableCollection<Source>> GetArticlesFromSource()
{
sourceDefinitions = await GetSourceDefinitions();
string imageFolderName = "ArticleImages";
string imageFolderPath = localFolder.Path + "\\" + imageFolderName;
StorageFolder imageFolder = await localFolder.CreateFolderAsync(imageFolderName, CreationCollisionOption.ReplaceExisting);
foreach (var source in sourceDefinitions)
{
if (source.Selected == "true")
{
ObservableCollection<Article> articlesStep1 = new ObservableCollection<Article>();
/*WebRequest request = WebRequest.Create(source.Url);
WebResponse response = await request.GetResponseAsync();
Stream receiveStream = response.GetResponseStream();
StreamReader readStream = new StreamReader(receiveStream);*/
string xml = await GetContent("http://www.honzachalupa.cz/").ConfigureAwait(false);
Debug.WriteLine(xml);
...
Your application is almost certainly calling Wait or Result on a returned task further up the call stack, and this will cause a deadlock that I explain in full on my blog.
To fix it, find the upstream Wait/Result call and change it to await. In other words, use "async all the way".

Handling http response codes in GetStringAsync

i'm very new to C#, let alone Windows Phone development :)
I'm trying to send a request, get the JSON response, but if there is an error (such as 401), be able to tell the user such. Here is my code:
async Task<string> AccessTheWebAsync()
{
//builds the credentials for the web request
var credentials = new NetworkCredential(globalvars.username, globalvars.password);
var handler = new HttpClientHandler { Credentials = credentials };
//calls the web request, stores and returns JSON content
HttpClient client = new HttpClient(handler);
Task<string> getStringTask = client.GetStringAsync("https://www.bla.com/content");
String urlContents = await getStringTask;
return urlContents;
}
I know it must be something I'm doing wrong in the way that I send the request and store the response...but i'm just not sure what.
If there is an error, I get a general:
net_http_message_not_success_statuscode
Thank you!
You could use te GetAsync() method instead of the GetStringAsync().
HttpResponseMessage response = await client.GetAsync("https://www.bla.com/content");
if(!response.IsSuccessStatusCode)
{
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
do something...
}
}
String urlContents = await response.Content.ReadAsStringAsync();
This way you can make use of the HttpStatusCode enumerable to check the returned status code.
Instead of using an HttpClient use a plain good old HttpWebRequest :)
async Task<string> AccessTheWebAsync()
{
HttpWebRequest req = WebRequest.CreateHttp("http://example.com/nodocument.html");
req.Method = "GET";
req.Timeout = 10000;
req.KeepAlive = true;
string content = null;
HttpStatusCode code = HttpStatusCode.OK;
try
{
using (HttpWebResponse response = (HttpWebResponse)await req.GetResponseAsync())
{
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
content = await sr.ReadToEndAsync();
code = response.StatusCode;
}
}
catch (WebException ex)
{
using (HttpWebResponse response = (HttpWebResponse)ex.Response)
{
using (StreamReader sr = new StreamReader(response.GetResponseStream()))
content = sr.ReadToEnd();
code = response.StatusCode;
}
}
//Here you have now content and code.
return content;
}

Categories