Handling http response codes in GetStringAsync - c#

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;
}

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.

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

Getting the response of Asynchronous http web request using POST method in asp.net core

I am using asp.net core. I am able to get the response from the http webrequest using GET method. To get the response via http webrequest using POST am facing 405 error.(Remote server not found)
Here is my code using GET Method.
public static void Main(string[] args)
{
var task = MakeAsyncRequest("http://localhost:8080/nifi-api/flow/status", "text/html");
Console.ReadLine();
}
public static Task<string> MakeAsyncRequest(string url, string contentType)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = contentType;
request.Method = "GET";
request.Proxy = null;
Task<WebResponse> task = Task.Factory.FromAsync(
request.BeginGetResponse,
asyncResult => request.EndGetResponse(asyncResult),
(object)null);
return task.ContinueWith(t => ReadStreamFromResponse(t.Result));
}
private static string ReadStreamFromResponse(WebResponse response)
{
using (Stream responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
{
string results = reader.ReadToEnd();
if (!string.IsNullOrEmpty(results))
{
Data data = new Data();
data = JsonConvert.DeserializeObject<Data>(results);
}
return results;
}
}
Please let me know how to get the response using async POST method in asp.net core. Thanks in advance.
Maybe this way?
HttpClient httpClient = new HttpClient();
var response = await httpClient.PostAsync("http://localhost:8080/nifi-api/flow/status", new StringContent("Json string", Encoding.UTF8, "application/json"));

Problems with a REST request in windows phone 8 using C#

I am trying to access to some rest services of a specific web server for my WP8 app and I canĀ“t do it well. For example, this is the code that I use when I try to login the user. I have to pass a string that represents a Json object ("parameters") with the username and the password and the response will be a json object too. I can't find the way to pass this pasameters in the rest request.
This is the code;
public void login(string user, string passwrd)
{
mLoginData.setUserName(user);
mLoginData.setPasswd(passwrd);
string serviceURL = mBaseURL + "/service/user/login/";
string parameters = "{\"username\":\"" + mLoginData.getUserName() + "\",\"password\":\"" + mLoginData.getPasswd() + "\"}";
//MessageBox.Show(parameters);
//MessageBox.Show(serviceURL);
//build the REST request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(serviceURL);
request.ContentType = "application/json";
request.Method = "POST";
//async request launchs "Gotresponse(...) when it has finished.
request.BeginGetResponse(new AsyncCallback(GotResponse), request);
}
private void GotResponse(IAsyncResult ar)
{
try
{
string data;
// State of request is asynchronous
HttpWebRequest myHttpWebRequest = (HttpWebRequest)ar.AsyncState;
using (HttpWebResponse response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(ar))
{
// Read the response into a Stream object.
Stream responseStream = response.GetResponseStream();
using (var reader = new StreamReader(responseStream))
{
data = reader.ReadToEnd();
}
responseStream.Close();
}
}
catch (Exception e)
{
string exception = e.ToString();
throw;
}
}
I tried too with the webClient and the httpClient classes too but without any result.
Thanks and sorry for my bad english.
I solved it with the HttpClient class. This is the code.
public async void login(string user, string passwrd)
{
string serviceURL = "";
string parameters = "";
HttpClient restClient = new HttpClient();
restClient.BaseAddress = new Uri(mBaseURL);
restClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, serviceURL);
req.Content = new StringContent(parameters, Encoding.UTF8, "application/json");
HttpResponseMessage response = null;
string responseBodyAsText = "";
try
{
response = await restClient.SendAsync(req);
response.EnsureSuccessStatusCode();
responseBodyAsText = await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException e)
{
string ex = e.Message;
}
if (response.IsSuccessStatusCode==true)
{
dynamic data = JObject.Parse(responseBodyAsText);
}
else
{
if (response.StatusCode == HttpStatusCode.Unauthorized)
{
MessageBox.Show("User or password were incorrect");
}
else
{
MessageBox.Show("NNetwork connection error");
}
}
}
I wasn't setting the header values of the request correctly.
I hope this can help someone.

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

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.

Categories