unable to send json data in c# - c#

I am sending my JSON string to this url http://myipaddress/WindowsApp/Registration?data=
I am using the following code which is as follows :
internal static async Task<String> getHttpResponse(HttpWebRequest request,string postData)
{
String received = null;
byte[] requestBody = Encoding.UTF8.GetBytes(postData);
using(var postStream=await request.GetRequestStreamAsync())
{
await postStream.WriteAsync(requestBody, 0, requestBody.Length);
}
try
{
var response = (HttpWebResponse)await request.GetResponseAsync();
if(response != null)
{
var reader = new StreamReader(response.GetResponseStream());
received = await reader.ReadToEndAsync();
}
}
catch(WebException ae)
{
var reader = new StreamReader(ae.Response.GetResponseStream());
string responseString = reader.ToString();
Debug.WriteLine("################ EXCEPTIONAL RESPONSE STRING ################");
Debug.WriteLine(responseString);
return responseString;
}
return received;
}
and I am calling this method when I click on one of my buttons in XAML as follows :
HttpWebRequest request = HttpWebRequest.Create(Classes.Constants.SERVER_URL) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/json";
postData = JsonConvert.SerializeObject(user);
string receivedString = await getHttpResponse(request, postData);
Debug.WriteLine("############# RECEIVED STRING #############");
Debug.WriteLine(receivedString);
So, the problem I am facing is that I am unable to get the string on the server.
Note : I am able to get the json string when my server implements its method with a url : http://myipaddress/WindowsApp/Registration
(without parameter "?data=") and also sends me response string. But fails when the term "?data=" is implemented and used in the server url.
So what am I going wrong in my code? Please help.

So, from what I see in the code you posted, from client side perspective(since we don't see the server side code)you are sending a request to the server in the body of the request.
There are two ways to POST: one way in the body of the request, the other one in the query string.
Seems to me that you are mixing the two.
When you do a POST request to your server to the address without the ?data=
then you send the request in the body.
Solutions:
If you want to POST in the body of the request, POST to the address without the ?data= parameter in the query string
If you want to send it trough the query string, you need to add the value after the ?data=
something like:
http://myipaddress/WindowsApp/Registration?data=MyValue

If I have understood everything correctly, you are trying to send a POST request to the server and to get a response from the server?
The POST request methods documentation says, that POST request must be used to submit data, not to get a response.
Note that query strings (name/value pairs) is sent in the HTTP message body of a POST request like this:
POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
name1=value1&name2=value2

Your Url should be http://myipaddress/WindowsApp/Registration since you are posting your data in the payload.

Related

.Net Core 3.1 Api Integration Test of DELETE Request with body [duplicate]

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

GDax API GET request always returns Error 400

I'm trying to get the order book from GDAX (link to documentation of the call) but when doing it from the c# executable I always get Error 400 - Bad request.
When taking the actual URL and pasting it into my browser, it works fine.
String URL = "https://api.gdax.com/products/BTC-USD/book?level=2";
WebRequest request = WebRequest.Create(URL);
WebResponse response = request.GetResponse();
The actual issue with your API call is , the API is expecting a user-agent string while making the request: Below is the code in working condition:
try
{
String URL = "http://api.gdax.com/products/BTC-USD/book?level=2";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.UserAgent = ".NET Framework Test Client";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var encoding = ASCIIEncoding.ASCII;
using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
{
string responseText = reader.ReadToEnd();
}
}
catch(WebException ex)
{
HttpWebResponse xyz = ex.Response as HttpWebResponse;
var encoding = ASCIIEncoding.ASCII;
using (var reader = new System.IO.StreamReader(xyz.GetResponseStream(), encoding))
{
string responseText = reader.ReadToEnd();
}
}
Basically ProtocolError indicates that you have received the response but there is an error related to protocol, which you can observe, when you read the response content from exception. I have added catch to handle the exception and read ex.Response (which is HttpWebResponse) and could see that the API is asking for user-agent to be suppllied while making the call. I got to see the error as "{"message":"User-Agent header is required."}"
You can ignore the code inside the exception block, I used it only to see what is the actual response message, which contains actual error details
Note: I have boxed WebRequest to HttpWebRequest to have additional http protocol related properties and most importantly "UserAgent" property which is not available with the WebRequest class.
You need to Accept the certificarte, Google for access to a https webrequest.
Like this

Passing body content when calling a Delete Web API method using System.Net.Http

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

Can't access Web of Trust (WoT) API w/ JSON.Net

I'm new to JSON & am using VS 2013/C#. Here's the code for the request & response. Pretty straightforward, no?
Request request = new Request();
//request.hosts = ListOfURLs();
request.hosts = "www.cnn.com/www.cisco.com/www.microsoft.com/";
request.callback = "process";
request.key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string output = JsonConvert.SerializeObject(request);
//string test = "hosts=www.cnn.com/www.cisco.com/www.microsoft.com/&callback=process&key=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
try
{
var httpWebRequest = (HttpWebRequest) WebRequest.Create("http://api.mywot.com/0.4/public_link_json2?);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = output;
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse) httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var responseText = streamReader.ReadToEnd();
}
}
catch (WebException e)
{
MessageBox.Show(e.ToString());
}
//response = true.
//no response = false
return true;
}
When I run this, I get a 405 error indicating method not allowed.
It seems to me that there are at least two possible problems here: (1) The WoT API (www.mywot.com/wiki/API) requires a GET request w/ a body, & httpWebRequest doesn't allow a GET in the httpWebRequest.Method; or (2) the serialized string isn't serialized properly.
NOTE: In the following I've had to remove the leading "http://" since I don't have enough rep to post more than 2 links.
It should look like:
api.mywot.com/0.4/public_link_json2?hosts=www.cnn.com/www.cisco.com/www.microsoft.com/&callback=process&key=xxxxxxxxxxxxxx
but instead looks like:
api.mywot.com/0.4/public_link_json2?{"hosts":"www.cnn.com/www.cisco.com/www.microsoft.com/","callback":"process","key":"xxxxxxxxxxxxxxxxxxx"}.
If I browse to:api.mywot.com/0.4/public_link_json2?hosts=www.cnn.com/www.cisco.com/www.microsoft.com/&callback=process&key=xxxxxxxxxxxxxx; I get the expected response.
If I browse to: api.mywot.com/0.4/public_link_json2?{"hosts":"www.cnn.com/www.cisco.com/www.microsoft.com/","callback":"process","key":"xxxxxxxxxxxxxxxxxxx"}; I get a 403 denied error.
If I hardcode the request & send as a GET like below:
var httpWebRequest = (HttpWebRequest) WebRequest.Create("api.mywot.com/0.4/public_link_json2? + "test"); it also works as expected.
I'd appreciate any help w/ this & hope I've made the problem clear. Thx.
Looks to me like the problem is that you are sending JSON in the URL. According to the API doc that you referenced, the API is expecting regular URL encoded parameters (not JSON), and it will return JSON to you in the body of the response:
Requests
The API consists of a number of interfaces, all of which are called using normal HTTP GET requests to api.mywot.com and return a response in XML or JSON format if successful. HTTP status codes are used for returning error information and parameters are passed using standard URL conventions. The request format is as follows:
http://api.mywot.com/version/interface?param1=value1&param2=value2
You should not be serializing your request; you should be deserializing the response. All of your tests above bear this out.

C# api responce and request

I currently have the code
try
{
string url = "http://myanimelist.net/api/animelist/update/" + "6.xml";
WebRequest request = WebRequest.Create(url);
request.ContentType = "xml/text";
request.Method = "POST";
request.Credentials = new NetworkCredential("username", "password");
byte[] buffer = Encoding.GetEncoding("UTF-8").GetBytes("<episode>4</episode>");
Stream reqstr = request.GetRequestStream();
reqstr.Write(buffer, 0, buffer.Length);
reqstr.Close();
MessageBox.Show("Updated");
}
catch (Exception s)
{
MessageBox.Show(s.Message);
}
I am trying do send data to myanimelist.net
The code they have written for is this
URL: http://myanimelist.net/api/animelist/update/id.xml
Formats: xml
HTTP Method(s): POST
Requires Authentication:true
Parameters:
id. Required. The id of the anime to update.
Example: http://myanimelist.net/api/animelist/update/21.xml
data. Required. A parameter specified as 'data' must be passed. It must contain anime values in XML format.
Response: 'Updated' or detailed error message.
The usage code example the have stated is this, does anyone know how to do this in c# or what was wrong with my original code?
Usage Examples:
CURL: curl -u user:password -d data="XML" http://myanimelist.net/api/animelist/update/21.xml
edit: When i lauch myanimelist.net it shows that it has not been updated, i am sure that my username and password credentials are correct
Edit 2 : I have now added a response which comes up with the error
"The remote server returned an error: (501) Not Implemented."
You're not actually performing the request, so once you're done writing to the request stream itself, perform the actual web request:
string result;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
}
Also, the content type should be text/xml or application/xml - the API may be complaining about that. Read the documentation for their API carefully and ensure what you're sending is correct.

Categories

Resources