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
}
}
}
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
{
}
So I am experimenting a little bit with HttpWebRequests and the System.Net; namespace in general and I did a GET request using POSTMAN and I got 3 cookies, now I tried doing the same request with C# but it doesnt seem to return any cookies at all.
Or it might but it's probably me who's doing this in a bad manner.
What is the propper way of doing a GET request and capturing the cookies so that I can later use them for a POST.
This is what I've got.
And it seems as if cookieContainer is empty once it finishes running, I tried debugging aswell.
public static void TestGET()
{
var request = (HttpWebRequest)WebRequest.Create("https://www.instagram.com/accounts/emailsignup/");
var cookieContainer = new CookieContainer();
using (var httpWebResponse = (HttpWebResponse)request.GetResponse())
{
using (var streamReader = new StreamReader(httpWebResponse.GetResponseStream()))
{
foreach (Cookie cookie in httpWebResponse.Cookies)
{
cookieContainer.Add(cookie);
}
}
}
}
Are you talking about the 3 Set-Cookies values in the response header. If so the code below will get those.
If you're using HttpWebResponse (this is what you're using)
using (var httpWebResponse = (HttpWebResponse)request.GetResponse())
{
var result = httpWebResponse.Headers["Set-Cookie"];
}
If you're using HttpResponseMessage:
if (httpResponse.Headers.TryGetValues("Set-Cookie", out values))
{
var session = values;
}
The cookie container is empty because httpWebResponse.Cookies is empty as well.
References:
How to read HTTP header from response using .NET HttpWebRequest API?
How to get an specific header value from the HttpResponseMessage
I have a problem with the POST method. I have a REST server programmed in C#, and I want to consume this REST service in C#, but I don't know how. The problem is that my method accepts a POST, receives a JSON payload and returns an HTTPStatusCode and a number:
id_task= planificadorService.CreaTarea(tareaDTO);//tareaDTO is a JSON
if (id_tarea == 0)
{
response = Request.CreateResponse(HttpStatusCode.NotFound, "Cannot create task ");
return response;
}
response = Request.CreateResponse(HttpStatusCode.Created);
response.Content = new StringContent(JsonConvert.SerializeObject(id_task), Encoding.UTF8, "application/json");
return response;
It was easy to do it using the GET method with the WebRequest and HttpWebResponse classes, but I don't know how to do it with the POST method. After many attempts, I ended up with something like this:
public void PostTareas(Tarea tarea)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url_base + "/v1/tareas");
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
string json = JsonConvert.SerializeObject(tarea);
var client = new HttpClient()
{
BaseAddress = new Uri(url_base + "/v1/tareas")
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response;
response.Content= new StringContent(JsonConvert.SerializeObject(tarea).ToString(), Encoding.UTF8, "application/json");
response = client.PostAsync(url_base + "/v1/tareas", json)).Result;
}
I'm on the right track? How can I do this so that I am able to access the Json content? Thanks
P.D- Excuse my english, it is not my native language and I know there may be faults in expressing myself
With WebRequest you need to write the JSON in the POST request payload, use WebRequest.GetRequestStream:
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url_base + "/v1/tareas");
...
using(var requestStream = request.GetRequestStream()) {
// Write the serialized json into the stream, it will be send as payload
using(TextWriter writer = new StreamWriter(requestStream)) {
writer.WriteLine(JsonConvert.Serialize(tarea));
}
}
var response = request.GetResponse();
or you can use HttpClient and call PostAsync, as you're doing in your second part of your code. Either way is fine, but stick to one :)
You should also consider using a high(er) level library, like RestSharp. Ultimately consider exposing your server API with Swagger via Swashbuckle, generate a client with swagger-codegen and spend your time at the higher level abstraction of the API, not the HTTP/Json layer.
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'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