I'm using https://timercheck.io/YOURTIMERNAME/60 to create timer, and when the timer end the API Manager to return both an error code and some JSON content
This is the JSON data when timer end:
{"errorMessage":"504: timer timed out"}
When the timer still countdown:
{"timer":"neo308CCEACbid","request_id":"e54f484e-1e64-11e6-9552-3950b2ec2d5c","status":"ok","now":1463732937,"start_time":1463732935,"start_seconds":180,"seconds_elapsed":2,"seconds_remaining":178,"message":"Timer still running"}
Because of the error code, i get error on Visual Studio and App force close on my Android. I only want to get the errorMessage in JSON. I'm using Visual Studio 2015 and Xamarin to make this project.
Thanks in advance
UPDATE:
I'm using this to get web response
private async Task<string> FetchUserAsync(string url)
{
// Create an HTTP web request using the URL:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.ContentType = "application/json";
request.Method = "GET";
// Send the request to the server and wait for the response:
using (WebResponse response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (var sr = new StreamReader(response.GetResponseStream()))
{
string strContent = sr.ReadToEnd();
return strContent;
}
}
}
And call it like this:
CekTimer dataWaktu = JsonConvert.DeserializeObject<CekTimer>(await FetchUserAsync(url));
I assume you are using HttpClient and GetStringAsync, and that the HttpResponse Status code is a 504 too, like in the Json Content.
The shortcut methods like GetStringAsync all make a call to EnsureSuccessStatusCode, which of cause throws an exception on a 504 (see source here).
You can just make a direct get Request:
var client = new HttpClient();
var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, yourUri));
var json = await response.Content.ReadAsStringAsync();
I found the answer of my problem, because of webservice return error code, just simply use WebException and get the StatusCode like this :
private async Task<string> FetchUserAsync(string url)
{
try
{
// Create an HTTP web request using the URL:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.ContentType = "application/json";
request.Method = "GET";
// Send the request to the server and wait for the response:
using (WebResponse response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (var sr = new StreamReader(response.GetResponseStream()))
{
string strContent = sr.ReadToEnd();
return strContent;
}
}
}
catch (WebException e)
{
string a = ((HttpWebResponse)e.Response).StatusCode.ToString();
//Toast.MakeText(this, a, ToastLength.Long).Show();
if (a == "GatewayTimeout")
{
return "{'errorMessage':'504: timer timed out'}";
}
else
{
internetDropDialog();
return "";
}
}
}
I think it isn't the best answer, but it can help you to move on from this problem
Related
I have a scenario where I need to call my Web API Delete method constructed like the following:
// DELETE: api/products/{id}/headers
[HttpDelete("{id}/headers")]
public void DeleteProductHeaders(int id, [FromBody] string query)
{
}
The trick is that in order to get the query over I need to send it through the body and DeleteAsync does not have a param for json like post does. Does anyone know how I can do this using System.Net.Http client in c#?
// Delete a product's headers
public void DeleteProductHeaders(int id, string query)
{
using (var client = GetClient())
{
HttpResponseMessage response;
try
{
// HTTP DELETE
response = client.DeleteAsync($"api/products/{id}/headers").Result;
}
catch (Exception ex)
{
throw new Exception("Unable to connect to the server", ex);
}
}
return retVal;
}
Here is how I accomplished it
var request = new HttpRequestMessage(HttpMethod.Delete, "http://www.example.com/");
request.Content = new StringContent(JsonConvert.SerializeObject(object), Encoding.UTF8, "application/json");
await this.client.SendAsync(request);
I think the reason HttpClient is designed that way is although HTTP 1.1 spec allows message body on DELETE requests, essentially it is not expected to do so as the spec doesn't define any semantics for it as it is defined here. HttpClient strictly follows HTTP spec thus you see it doesn't allow you to add a message body to the request.
So, I think your option from the client side includes using HttpRequestMessage described in here. If you want to fix it from the backend and if your message body would work well in query params you can try that instead of sending the query in message body.
I personally think DELETE should be allowed to have a message body and should not be ignored in a server as there are certainly use cases for that like the one you mentioned here.
In any case for more productive discussion on this please have a look at this.
My API as below:
// DELETE api/values
public void Delete([FromBody]string value)
{
}
Calling from C# server side
string URL = "http://localhost:xxxxx/api/values";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "DELETE";
request.ContentType = "application/json";
string data = Newtonsoft.Json.JsonConvert.SerializeObject("your body parameter value");
request.ContentLength = data.Length;
StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
requestWriter.Write(data);
requestWriter.Close();
try
{
WebResponse webResponse = request.GetResponse();
Stream webStream = webResponse.GetResponseStream();
StreamReader responseReader = new StreamReader(webStream);
string response = responseReader.ReadToEnd();
responseReader.Close();
}
catch
{
}
Before I upgraded to the newest .NetCore I was able to run the HttpWebRequest, add the headers and content Type and pull the stream of the JSON file from Twitch. Since the upgrade this is not working. I receive a Web Exception each time I go to get the response Stream. Nothing has changed with twitch because it still works with the old Bot. The old code is below:
private const string Url = "https://api.twitch.tv/kraken/streams/channelname";
HttpWebRequest request;
try
{
request = (HttpWebRequest)WebRequest.Create(Url);
}
request.Method = "Get";
request.Timeout = 12000;
request.ContentType = "application/vnd.twitchtv.v5+json";
request.Headers.Add("Client-ID", "ID");
try
{
using (var s = request.GetResponse().GetResponseStream())
{
if (s != null)
using (var sr = new StreamReader(s))
{
}
}
}
I have done some research and found that I may need to start using either an HttpClient or HttpRequestMessage. I have tried going about this but when adding headers content type the program halts and exits. after the first line here: (when using HttpsRequestMessage)
request.Content.Headers.ContentType.MediaType = "application/vnd.twitchtv.v5+json";
request.Content.Headers.Add("Client-ID", "rbp1au0xk85ej6wac9b8s1a1amlsi5");
You are trying to add a ContentType header, but what you really want is to add an Accept header (your request is a GET and ContentType is used only on requests which contain a body, e.g. POST or PUT).
In .NET Core you need to use HttpClient, but remember that to correctly use it you need to leverage the use of async and await.
Here it is an example:
using System.Net.Http;
using System.Net.Http.Headers;
private const string Url = "https://api.twitch.tv/kraken/streams/channelname";
public static async Task<string> GetResponseFromTwitch()
{
using(var client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.twitchtv.v5+json"));
client.DefaultRequestHeaders.Add("Client-ID", "MyId");
using(var response = await client.GetAsync(Url))
{
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync(); // here we return the json response, you may parse it
}
}
}
I have a scenario where I need to call my Web API Delete method constructed like the following:
// DELETE: api/products/{id}/headers
[HttpDelete("{id}/headers")]
public void DeleteProductHeaders(int id, [FromBody] string query)
{
}
The trick is that in order to get the query over I need to send it through the body and DeleteAsync does not have a param for json like post does. Does anyone know how I can do this using System.Net.Http client in c#?
// Delete a product's headers
public void DeleteProductHeaders(int id, string query)
{
using (var client = GetClient())
{
HttpResponseMessage response;
try
{
// HTTP DELETE
response = client.DeleteAsync($"api/products/{id}/headers").Result;
}
catch (Exception ex)
{
throw new Exception("Unable to connect to the server", ex);
}
}
return retVal;
}
Here is how I accomplished it
var request = new HttpRequestMessage(HttpMethod.Delete, "http://www.example.com/");
request.Content = new StringContent(JsonConvert.SerializeObject(object), Encoding.UTF8, "application/json");
await this.client.SendAsync(request);
I think the reason HttpClient is designed that way is although HTTP 1.1 spec allows message body on DELETE requests, essentially it is not expected to do so as the spec doesn't define any semantics for it as it is defined here. HttpClient strictly follows HTTP spec thus you see it doesn't allow you to add a message body to the request.
So, I think your option from the client side includes using HttpRequestMessage described in here. If you want to fix it from the backend and if your message body would work well in query params you can try that instead of sending the query in message body.
I personally think DELETE should be allowed to have a message body and should not be ignored in a server as there are certainly use cases for that like the one you mentioned here.
In any case for more productive discussion on this please have a look at this.
My API as below:
// DELETE api/values
public void Delete([FromBody]string value)
{
}
Calling from C# server side
string URL = "http://localhost:xxxxx/api/values";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "DELETE";
request.ContentType = "application/json";
string data = Newtonsoft.Json.JsonConvert.SerializeObject("your body parameter value");
request.ContentLength = data.Length;
StreamWriter requestWriter = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII);
requestWriter.Write(data);
requestWriter.Close();
try
{
WebResponse webResponse = request.GetResponse();
Stream webStream = webResponse.GetResponseStream();
StreamReader responseReader = new StreamReader(webStream);
string response = responseReader.ReadToEnd();
responseReader.Close();
}
catch
{
}
I try to load json like this
private async Task<JsonValue> FetchAsync(string url)
{
// Create an HTTP web request using the URL:
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new Uri(url));
request.ContentType = "application/json";
request.Method = "GET";
// Send the request to the server and wait for the response:
using (WebResponse response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (Stream stream = response.GetResponseStream())
{
// Use this stream to build a JSON document object:
JsonValue jsonDoc = await Task.Run(() => JsonObject.Load(stream));
Console.Out.WriteLine("Response: {0}", jsonDoc.ToString());
// Return the JSON document:
return jsonDoc;
}
}
}
but in this JsonObject.Load(stream)); I have error:
Error CS0117 'JsonObject' does not contain a definition for 'Load'
As I read on MSDN JsonObject has Load method.
What's wrong in my code?
I know it is late for this post but maybe i can help somebody else.
You should add this line to your project:
using System.Json
Right-click on references and then click add reference. Check System.Json box and then click ok.
When I run the program contained below the first HTTPS request succeeds, but the second request fails. Both url's are valid and both can be accessed successfully in a browser. Any suggestions as to what needs to be done to access the second url successfully?
using System;
using System.IO;
using System.Net;
public class Program
{
private static void Main(string[] args)
{
var content = "";
bool status;
var url1 = "https://mail.google.com";
var url2 = "https://my.ooma.com";
status = DoHttpRequest(url1, out content);
OutputStatus(url1, status, content);
status = DoHttpRequest(url2, out content);
OutputStatus(url2, status, content);
Console.ReadLine();
}
private static void OutputStatus(string url, bool status, string content)
{
if (status) Console.WriteLine("Url={0}, Status=Success, content length = {1}", url, content.Length);
else Console.WriteLine("Url={0}, Status=Fail, ErrorMessage={1}", url, content);
}
private static bool DoHttpRequest(string url, out string content)
{
content = "";
var request = (HttpWebRequest) WebRequest.Create(url);
try
{
request.Method = "GET";
request.CookieContainer = null;
request.Timeout = 25000; // 25 seconds
var response = (HttpWebResponse) request.GetResponse();
var streamReader = new StreamReader(response.GetResponseStream());
content = streamReader.ReadToEnd();
return true;
}
catch (WebException ex)
{
content = ex.Message;
return false;
}
}
}
Historically, most problems of this description that I've seen occur when you forget to call .Close() on the object returned from GetResponseStream(). The problem exists because when you forget to close the first request, the second request deadlocks waiting for a free connection.
Typically this hang happens on the 3rd request, not the second.
Update: Looking at your repro, this has nothing to do with the order of the requests. You're hitting a problem because this site is sending a TLS Warning at the beginning of the HTTPS handshake, and .NET will timeout when that occurs. See http://blogs.msdn.com/b/fiddler/archive/2012/03/29/https-request-hangs-.net-application-connection-on-tls-server-name-indicator-warning.aspx. The problem only repros on Windows Vista and later, because the warning is related to a TLS extension that doesn't exist in the HTTPS stack on WinXP.
Increse your request TimeOut.
request.Timeout = 60000; //60 second.
May be your network connection is a bit slow. I run with 25 seconds, okay. (Yeah, the second url is a bit longer to get response, than the first one.)