Posting to a REST webservice from .NET? - c#

I was trying to hit a web service using the instructions here:
http://help.seeclickfix.com/kb/api/creating-an-issue
I came up with the code below:
string paramContent = "api_key=afs684eas3ef86saef78s68aef68sae&issue[summary]=abeTest&issue[lat]=39.26252982783172&issue[lng]=-121.01738691329956&issue[address]=111 Abe St., Nevada City, CA";
byte[] paramBytes = Encoding.UTF8.GetBytes(paramContent);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://seeclickfix.com/api/issues.xml");
req.Method = "POST";
req.ContentLength = paramBytes.Length;
//req.ContentType = "application/x-www-form-urlencoded";
using (Stream reqStream = req.GetRequestStream())
{
reqStream.Write(paramBytes, 0, paramBytes.Length);
}
using (HttpWebResponse resp = (HttpWebResponse)req.GetResponse()) //HERE!
{
if (resp.StatusCode != HttpStatusCode.OK)
{
string message = String.Format("POST failed. Received HTTP {0}", resp.StatusCode);
throw new ApplicationException(message);
}
StreamReader sr = new StreamReader(resp.GetResponseStream());
string response = sr.ReadToEnd();
Console.WriteLine(response + System.Environment.NewLine);
}
But at the line with the HERE! comment it throws the error:
The remote server returned an error: (500) Internal Server Error.
Can anyone see any problems with the way I am trying to implement this?

The 500 error you are getting indicates a problem on the server, not necessarily a problem with your code. You are successfully sending a request and receiving a response.
The problem could be a bug in the server, or a problem with the content of your request that the server can't handle. (Either way the server is failing to provide a valid error message like their documentation suggests it would)
You should start by making sure the content of your request is valid. See the example on the seeclickfix url you posted. Try directly posting with curl like they show, but use the content of your own message like so:
curl -v -d 'api_key=afs684eas3ef86saef78s68aef68sae&issue[summary]=abeTest&issue[lat]=39.26252982783172&issue[lng]=-121.01738691329956&issue[address]=111 Abe St., Nevada City, CA' http://seeclickfix.com/api/issues.xml
I expect you'll still get a 500 error (I just tried it and I got a 500 error).
Bottom line, it looks like their api is broken, not your logic.

You didn't do anything wrong. I tried making the request using Fiddler and it returned the same 500 status code.
If there was something wrong with the data you passed then they should have returned a 4XX response code.

Related

WebService Call from .net C# getting error : (502) Bad Gateway

Trying to call WebServices from C# and getting below error:
System.Net.WebException: 'The remote server returned an error: (502) Bad Gateway
Code:
WebRequest request = WebRequest.Create("https://xxxxx/cgi/webservice.pl?function=get_latest_ts_values&site_list=130105B&datasource=AT&varfrom=10.00&varto=10.00&lookback=60&format=csv");
request.Method = "GET";
WebResponse response = request.GetResponse();
using (Stream dataStream = response.GetResponseStream() )
{
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
Console.WriteLine(responseFromServer);
Console.ReadLine();
}
But works fine when i use Postman or just copy url in browser and also works fine with below python code:
import requests
dataload = {}
dataurl = "https://xxxxx/cgi/webservice.pl?function=get_latest_ts_values&site_list=130105B&datasource=AT&varfrom=10.00&varto=10.00&lookback=60"
headers = {}
response = requests.request("GET", dataurl, headers=headers, data=dataload)
for dataresp in response:
print(dataresp)
What am I doing wrong with C# code?
The uri for the WebRequest has the query parameter &format=csv. Maybe this is why you are getting a 502. The Python request is missing that query parameter. Did you try the WebRequest by removing that part?
Could be incorrect content type or user agent having the wrong information. Postman could be setting these values without your knowledge. Might try in the exception seeing if there is a a response stream and read it through a streamreader to see if there is any more information you're not seeing to point you in the correct direction.
Ended up using RestSharp and it works fine. (https://www.nuget.org/packages/RestSharp)
string Uri = "https://xxxx/cgi/webservice.pl?xxxx";
var client = new RestSharp.RestClient(Uri);
client.Timeout = -1;
var request = new RestRequest(Method.GET);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

HttpWebRequest random 'request timed out' exception

I am currently developing in Unity (in particular using C#) and I'm stuck with HttpWebRequest - HttpWebResponse random timeouts.
I have some methods that send a POST request to a server I host on my local machine (XAMPP) to use various php scripts which are going to fetch informations from MySQL Database (hosted with XAMPP) and give back those info in JSON format.
Then I handle these JSON informations with my C# scripts.
The problem is that when I run the first test all is good:I can get the JSON data from my Server and show it in the Debug Console.
When I run the second test,a WebException is raised with error:
WebException - The request timed out
After that second test,if I run again and again,the problem keeps presenting in a random way.
I followed all the guidelines I found on the internet on how to setup a webrequest - webresponse properly,in particular I tried to use ServicePoint.DefaultConnectionLimit and ServicePoint.MaxServicePointIdleTime,without any result.
The general structure of my methods (regarding the web request/response part) is something like that:
public void WebMethod(){
string post_url = "http://localhost/service.php?someparam=1&someparam=2";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(post_url);
request.Method = "POST";
request.KeepAlive = false;
request.Timeout = 5000;
request.Proxy = null;
string Response = "";
try
{
using (HttpWebResponse resp = request.GetResponse() as HttpWebResponse)
{
using (Stream objStream = resp.GetResponseStream())
{
using (StreamReader objReader = new StreamReader(objStream, Encoding.UTF8))
{
Response = objReader.ReadToEnd();
objReader.Close();
}
objStream.Flush();
objStream.Close();
}
resp.Close();
}
}catch(WebException e)
{
Debug.Log(e.Message);
}
finally
{
request.Abort();
}
//tried this one after reading some related answers here on StackOverflow,without results
//GC.Collect();
Debug.Log("SERVER RESPONSE:" + Response);
//Response Handling
}
I know that it may be something related to a wrong abort on the HttpWebRequest / Response or maybe related to the HTTP 1.1 connections limit,but I can't figure out any solution at the moment.
Any help is appreciated.

How can I avoid a "Bad Request - Invalid Hostname" error when making a REST call from a Compact Framework client?

I used this code from here to try to call a REST Controller method on a Web API server app from a Compact Framework client:
public static void SendXMLFile3(string uri, string data)
{
WebRequest request = WebRequest.Create (uri);
request.Method = "POST";
string postData = data;
byte[] byteArray = Encoding.UTF8.GetBytes (postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream ();
dataStream.Write (byteArray, 0, byteArray.Length);
dataStream.Close ();
WebResponse response = request.GetResponse ();
MessageBox.Show(((HttpWebResponse) response).StatusDescription);
dataStream = response.GetResponseStream ();
StreamReader reader = new StreamReader (dataStream);
string responseFromServer = reader.ReadToEnd();
MessageBox.Show(responseFromServer);
reader.Close ();
dataStream.Close ();
response.Close ();
}
...I had earlier tried this code, which I got from the book "Microsoft .NET Compact Framework":
public static void SendXMLFile2(string uri, string data)
{
WebRequest req = WebRequest.Create(uri);
req.Method = "Post";
req.ContentType = "text/plain; charset=utf-8";
byte[] encodedBytes = Encoding.UTF8.GetBytes(data);
req.ContentLength = encodedBytes.Length;
Stream requestStream = req.GetRequestStream();
requestStream.Write(encodedBytes, 0, encodedBytes.Length);
requestStream.Close();
WebResponse result = req.GetResponse();
MessageBox.Show(result.ToString());
}
...but I get "400 - Bad Request" with the new (as well as the old) code.
My initial attempt also does not work, with the same result (400):
public static string SendXMLFile(string xmlFilepath, string uri, int timeout)
{
HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create(uri);
myHttpWebRequest.AllowWriteStreamBuffering=false;
string postData = "<Command><DSD><line_id>1</line_id><invoice_no>david_dsd</invoice_no>. . .</DSD></Command>"; // TODO: if this works, replace it with the real data
myHttpWebRequest.Method="POST";
UTF8Encoding encodedData = new UTF8Encoding();
byte[] byteArray=encodedData.GetBytes(postData);
myHttpWebRequest.ContentType = "application/xml";
myHttpWebRequest.ContentLength=byteArray.Length;
Stream newStream=myHttpWebRequest.GetRequestStream();
newStream.Write(byteArray,0,byteArray.Length);
newStream.Close();
HttpWebResponse myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse();
return myHttpWebResponse.StatusDescription;
}
There is much more about the plethora of variations I have tried here, where I have reached my length-of-post limit.
UPDATE
Note that the Server code doesn't know/care that the file is XML:
[HttpPost]
[Route("api/inventory/sendXML/{userId}/{pwd}/{filename}")]
public async Task SendInventoryXML(String userId, String pwd, String fileName)
{
Task task = Request.Content.ReadAsStreamAsync().ContinueWith(t =>
{
var stream = t.Result;
using (FileStream fileStream = File.Create(String.Format(#"C:\HDP\{0}.xml", fileName), (int)stream.Length))
{
byte[] bytesInStream = new byte[stream.Length];
stream.Read(bytesInStream, 0, (int)bytesInStream.Length);
fileStream.Write(bytesInStream, 0, bytesInStream.Length);
}
});
}
UPDATE 2
I tried Charles to see if it would pick up the local HTTP traffic, but it is also deaf to such (like Fiddler, without special ministrations, anyway). This is what Charles looks like after getting the "400 - Bad Request" error:
UPDATE 3
I found this suggestion somewhere to get Fiddler to show local HTTP traffic:
Tools--> Fiddler Options. Choose Connections tab. Check the 'USe PAC Script' option.
...but it didn't work - I still see no HTTP traffic when getting the "400 (Bad Request)" message.
UPDATE 4
I am now seeing "400 (Bad Request)" in Fiddler 2, too; to get it, I enter any of the following in Postman (don't see this in Fiddler when calling from CE/CF/handheld app):
http://SHANNON2:21608/api/inventory/sendXML/su/su/blablee // Hostname
http://SHANNON2.:21608/api/inventory/sendXML/su/su/blablee // Hostname with Fiddler-fooler appended "."
http://192.168.125.50:21608/api/inventory/sendXML/su/su/blablee // IP Address
(Fiddler does not capture anything if I replace the hostname or IP Address with "localhost")
Note: For these URLs in Postman, I have "Post" (as opposed to GET, etc.) selected, and an XML file attached.
Inspectors.Headers in Fiddler shows:
POST /api/inventory/sendXML/su/su/blablee HTTP/1.1
Although I consider this a minor debugging victory, I still don't see why I'm getting the "400" error.
Fiddler tells me, in the Inspectors.WebView pane:
Bad Request - Invalid Hostname
--------------------------------------------------------------------------------
HTTP Error 400. The request hostname is invalid.
How can that be? When I run it from Postman, I hit the breakpoint in the server - if the hostname is invalid, why is it being reached?
UPDATE 5
Testing the call from Fiddler Composer and Postman, the only way I can reach the breakpoint in the server code is by using "localhost" - replacing that with the PC's IPAddress (192.168.125.50) or HostName (SHANNON2) does not reach the breakpoint. While "interesting," calling "localhost" from the handheld device is obviously not an option.
UPDATE 6
Related new question here.
UPDATE 7
The crux of the biscuit was adding at the command prompt either this:
netsh http add urlacl url=http://shannon2:80/ user=everyone
...or this:
netsh http add urlacl url=http://shannon2:8080/ user=everyone
See Update 5 here for more details
Adding my observations, if you are facing the issue Bad Request - Invalid Hostname while calling the API from Postman. Something like this.
Consider adding the Host in Headers, it will work.
Updated after someone is not able to view the image: If the images are not loading, then basically this you have to do:
Basically, you have to add Content-Length and Host. Postman auto calculates when the request is sent. These can be enabled in postman by unhiding auto-generated headers in Postman. or you can set by your own.
The crux of the biscuit was adding at the command prompt either this:
netsh http add urlacl url=http://shannon2:80/ user=everyone
...or this:
netsh http add urlacl url=http://shannon2:8080/ user=everyone
See Update 5 here for more details

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.

Why is the google server returning error 401 when trying to get token?

i'm currently trying to develop an api for google reader and when i'm trying to get the token, the following error is being generated:
System.Net.WebException: The remote server returned an error: (401) Unauthorized.
at System.Net.HttpWebRequest.GetResponse()
first i'm getting the session... and this works perfectly. then the following method i being called to get the token:
public String setToken()
{
HttpWebResponse response;
HttpWebRequest request;
cookie = new Cookie("SID", this.sessionID, "/", ".google.com");
String url = "http://www.google.com/reader/api/0/token";
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.CookieContainer = new CookieContainer();
request.CookieContainer.Add(this.cookie);
response= (HttpWebResponse)request.GetResponse();
using (var stream = response.GetResponseStream())
{
StreamReader r = new StreamReader(stream);
this.token = r.ReadToEnd();
}
return this.token;
}
the exception is being generated in this line:
response= (HttpWebResponse)request.GetResponse();
does anyone know what might be causing this error please?
PS. I read the question : Why am I getting a 401 (Unauthorized) error when POSTing to Google Reader API? however he was getting this error when he tried to post.
Google has changed, according to Eric Mann:
"As it turns out, Google has changed the authentication portion of the Reader API. Now, instead of passing the SID in a cookie when you make a request, you set an authentication header with the “Auth” key originally passed with the SID."
Source

Categories

Resources