So I'm following the WingTip Toy tutorial, and I know its sort of old but it was error free until I got to the point where I needed to checkout with PayPal using the sandbox developing tool
This is the code where the error occurs
//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
return result;
And this is the error im getting when i run it
[ProtocolViolationException: You must write ContentLength bytes to the request stream before calling [Begin]GetResponse.]
Please note I'm a beginner
Edit: The full code is here
public string HttpCall(string NvpRequest)
{
string url = pEndPointURL;
string strPost = NvpRequest + "&" + buildCredentialsNVPString();
strPost = strPost + "&BUTTONSOURCE=" + HttpUtility.UrlEncode(BNCode);
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Timeout = Timeout;
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
try
{
using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
{
myWriter.Write(strPost);
}
}
catch (Exception)
{
// No logging for this tutorial.
}
//Retrieve the Response returned from the NVP API call to PayPal.
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
string result;
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
result = sr.ReadToEnd();
}
return result;
}
objRequest.ContentLength = strPost.Length;
What are you trying to do here? The framework sets the content length automatically. The content length is in bytes but you have given the number of characters.
That's why the error complains: You have written a different number of characters than you said you would write.
Delete that line.
Your code would become a lot simpler if you used HttpClient. Should be about 5 lines.
Related
I'm quite new to c# and I'm having an issue when trying to call an API to post some CSV data using the following code:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://myurl");
request.Method = "POST";
request.Headers.Add("X-Api-Key:" + apiKey);
request.Headers.Add("X-Api-Secret:" + apiSecret);
request.ContentType = "text/csv";
using (StreamWriter swCSVData = new StreamWriter(request.GetRequestStream()))
{
StreamReader csvReader = new StreamReader(File.OpenRead("C:\\Test\\conf-ato-sprmbrinfo-batch-001.csv"));
while (!csvReader.EndOfStream)
{
swCSVData.WriteLine(csvReader.ReadLine());
}
csvReader.Close();
}
HttpWebResponse response = null;
try
{
Console.WriteLine("Attempting response....");
response = (HttpWebResponse)request.GetResponse();
Console.WriteLine("Got response....");
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (StreamReader reader = new StreamReader(responseStream))
{
strResponseValue = reader.ReadToEnd();
}
}
}
Console.WriteLine(strResponseValue);
File.WriteAllText("C:\\Test\\apioutput.txt",strResponseValue);
}
catch ( Exception ex)
{
strResponseValue = "{\"errorMessages\":[\"" + ex.Message.ToString() + "\"],\"errors\":{}}";
}
If I run this code using the post test at ptsv2.com, then I can see that the api call looks like I would expect and I get a response. However, when I change my code to point to my required URL it seems to just hang on the following line:
response = (HttpWebResponse)request.GetResponse();
Does anyone have any idea as to why this could be happening?
Also happy for any recommendations to make my code better.
Thanks in advance.
It turns out this was a security issue once I could see the exception being returned. I had to add the following line of code for my request:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Thanks to the people who took the time to comment on my original question.
I made an API in server side with PHP + Laravel framework which accept both GET & Post requests with some special parameters.
It's address is : http://beresun.ir/API/Orders/0
and it gets these parameters :
token > string ,
restaurant_id > integer ,
admin_id > integer ,
token_id > integer .
if we send a request with GET method with these parameters, for example it will be :
http://beresun.ir/API/Orders/0?token=2JEuksuv86DcFmLrQa7nna4QDeowuGTqpyUK0pf9wSlbe6D5hLtEVxvzMT5gAZG0xBKy00HxS3J79mcr8F54dBD0uIg5HX5fzPOAP&restaurant_id=1&admin_id=2&token_id=40 which returns a json data , you can click on the link to see the results .
the response json data includes some information about customers and it's products.
now I want to make a windows application for this service with C# and request data from this API with POST or GET methods :
I want to use this API to get Json data from Web server and save them in my Windows application , So I created two functions in one of my Form Classes :
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
public partial class MainActivity : Form
{
string token = "2JEuksuv86DcFmLrQa7nna4QDeowuGTqpyUK0pf9wSlbe6D5hLtEVxvzMT5gAZG0xBKy00HxS3J79mcr8F54dBD0uIg5HX5fzPOAP";
int restaurant_id = 1;
int admin_id = 2;
int token_id = 40;
private void SendWebrequest_Get_Method()
{
try
{
String postData = "token=" + token +
"&restaurant_id=" + restaurant_id +
"&admin_id=" + admin_id +
"&token_id=" + token_id;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://beresun.ir/API/Orders/0?" + postData);
request.ContentType = "application/json; charset=utf-8";
request.Accept = "application/json";
request.Method = WebRequestMethods.Http.Get;
WebResponse response = request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream());
String json_text = sr.ReadToEnd();
dynamic stuff = JsonConvert.DeserializeObject(json_text);
if (stuff.error != null)
{
MessageBox.Show("problem with getting data", "Error");
}
else
{
MessageBox.Show(json_text, "success");
}
sr.Close();
}
catch (Exception ex)
{
MessageBox.Show("Wrong request ! " + ex.Message, "Error");
}
}
private void SendWebrequest_POST_Method()
{
try
{
// Create a request using a URL that can receive a post.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://beresun.ir/API/Orders/5");
// Set the Method property of the request to POST.
request.Method = "POST";
request.Credentials = CredentialCache.DefaultCredentials;
((HttpWebRequest)request).UserAgent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)";
// Create POST data and convert it to a byte array.
string postData = "token=" + token +
"&restaurant_id=" + restaurant_id +
"&admin_id=" + admin_id +
"&token_id=" + token_id;
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/json; charset=utf-8";
// Set the ContentLength property of the WebRequest.
request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = request.GetRequestStream();
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Close();
// Get the response.
WebResponse response = request.GetResponse();
// Display the status.
MessageBox.Show(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
MessageBox.Show(responseFromServer);
// Clean up the streams.
reader.Close();
dataStream.Close();
response.Close();
}
catch (Exception ex)
{
MessageBox.Show("Wrong request ! " + ex.Message, "Error");
}
}
}
Now Here is the problem , when I test the API it works fine , but when I request data from my application , it returns error and not working .
Can anyone explain me how I should request data from this API , to get data , I searched a lot , and I used many different methods , but none of them worked for me . maybe because this API returns very much Json data or maybe request timeout happen. I don't know , I couldn't find the problem . So I asked it Here.
I don't know what I should do .
Thanks
Oki so i run your code :
private string TestURL = "http://beresun.ir/API/";
string token = "2JEuksuv86DcFmLrQa7nna4QDeowuGTqpyUK0pf9wSlbe6D5hLtEVxvzMT5gAZG0xBKy00HxS3J79mcr8F54dBD0uIg5HX5fzPOAP";
int restaurant_id = 1;
int admin_id = 2;
int token_id = 40;
public async Task<string> test()
{
try
{
using (var Client = new HttpClient())
{
Client.BaseAddress = new Uri(TestURL);
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
string postData = "token=" + token +
"&restaurant_id=" + restaurant_id +
"&admin_id=" + admin_id +
"&token_id=" + token_id;
HttpResponseMessage responce = await Client.GetAsync("Orders/0?" + postData);
if (responce.IsSuccessStatusCode)
{
var Json = await responce.Content.ReadAsStringAsync();
// !
return Json;
}
else
{
// deal with error or here ...
return null;
}
}
}
catch (Exception e)
{
return null;
}
}
and its working am getting the json file ,, i think your mistake is in postData is string Not String ! a simple type can amazing harm !
try this:
private string URL = "Your Base domain URL";
public async Task<YourModel> getRequest()
{
using (var Client = new HttpClient())
{
Client.BaseAddress = new Uri(URL);
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage responce = await Client.GetAsync("Your Method or the API you callig");
if (responce.IsSuccessStatusCode)
{
var Json = await responce.Content.ReadAsStringAsync();
var Items= JsonConvert.DeserializeObject<YourModel>(Json);
// now use you have the date on Items !
return Items;
}
else
{
// deal with error or here ...
return null;
}
}
}
My remote server is throwing a web exception as bad request. But I know there is more information included in the error than what I get. If I look at the details from the exception it does not list the actual content of the response. I can see the content-type, content-length and content-encoding only. If I run this same message through another library (such as restsharp) I will see detailed exception information from the remote server. How can I get more details from the response since I know the remote server is sending them?
static string getXMLString(string xmlContent, string url)
{
//string Url;
string sResult;
//Url = ConfigurationManager.AppSettings["UserURl"] + url;
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/xml";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(xmlContent);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
sResult = result;
}
}
return sResult;
}
EDIT : Have you tried with a simple try-catch to see if you can get more details ?
try
{
var response = (HttpWebResponse)(request.GetResponse());
}
catch(Exception ex)
{
var response = (HttpWebResponse)ex.Response;
}
In my recherches in an answer for you, I noticed that in code there was something about encoding, that you didn't specified. Look here for exemple with such code.
var encoding = ASCIIEncoding.ASCII;
using (var reader = new System.IO.StreamReader(response.GetResponseStream(), encoding))
{
string responseText = reader.ReadToEnd();
}
Or here, in the doc, also.
// Creates an HttpWebRequest with the specified URL.
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);
// Sends the HttpWebRequest and waits for the response.
HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
// Gets the stream associated with the response.
Stream receiveStream = myHttpWebResponse.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader readStream = new StreamReader( receiveStream, encode );
Console.WriteLine("\r\nResponse stream received.");
Have you tried with such ?
I have the following code:
string url = string.Format("http://{0}:{1}/{2}/xml",Address.Host,Address.Port,Address.ContextRoot);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
req.UserAgent = "Foo";
req.ContentType = "text/xml; charset=\"UTF-8\"";
req.KeepAlive = false;
using (Stream reqStream = req.GetRequestStream())
{
SoapEnvelope s = new SoapEnvelope(Address, null);
XmlDocument xmlDoc = s.GenerateXml(message);
xmlDoc.Save(reqStream);
}
result = ReceiveAnswer(req);
private string ReceiveAnswer(HttpWebRequest req)
{
using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
using (Stream resStream = res.GetResponseStream())
using (StreamReader reader = new StreamReader(resStream))
{
if (res.StatusCode != HttpStatusCode.OK)
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Failed to post data to http://{0}:{1}", Address.Host, Address.Port).AppendLine();
sb.AppendFormat("Response: {0} {1}", res.StatusCode, res.StatusDescription);
res.Close();
throw new WebException(sb.ToString());
}
String resData = reader.ReadToEnd();
return resData;
}
}
This code works fine, when I'm connecting to an existing server, but I've just tested, that if the server I specify does not exist then this part: (HttpWebResponse)req.GetResponse() will hang. I expected to get a webexception or something in this scenario, because I want to catch it.
I've read it somewhere that this Response has a timeout of 100 seconds, I've waited more than that, but nothing happened. Then I set the Timeout property to 15 seconds, but that didn't help either.
Anyone knows what should I do?
There was no problem with my code, an other part of the company's code causes the problem.
Be very careful with what you're doing.
Timeout method does not apply to the time waiting for the response to be caught.
Timeout counts for the entire life of your connection (meaning request + response).
If you're then setting a too-low timeout time, your program will never catch it. Maybe you could try to raise the Timeout number?
When I run this code to call the Google API, all I get is a 'Bad Request' error, but I don't know where I'm going wrong.
The code is being returned no problem from the authorization page on Google, it's when the code gets to the part below that it fails. Please could someone tell me where I'm going wrong here?
I'm aware that there are libraries for this, but I'm trying to understand how to do this the RESTful way as a learning exercise.
Thanks
var code = Request.QueryString["code"];
var accessToken = string.Empty;
var req0 = WebRequest.Create("https://accounts.google.com/o/oauth2/token");
req0.Method = "POST";
string postData = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri= {3}&grant_type=authorization_code",
code, //the code i got back
"xxxx.apps.googleusercontent.com",
"xxx",
Url.Encode("http://localhost/home/callback")
); //my return URI
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
req0.ContentType = "application/x-www-form-urlencoded";
req0.ContentLength = byteArray.Length;
using (Stream dataStream = req0.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
}
try
{
using (WebResponse response = req0.GetResponse())
{
using (var dataStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(dataStream))
{
string responseFromServer = reader.ReadToEnd();
var ser = new JavaScriptSerializer();
accessToken = ser.DeserializeObject(responseFromServer).ToString();
}
}
}
}
catch (WebException wex)
{
Debug.WriteLine(wex.ToString());
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
The Google API is very finicky when it comes to what you have entered into the API Console for your client id return URI, and what you enter in your code to call it.
I was missing the trailing forward slash. That was all. Lesson learnt...
Thanks to Jon and Sandeep for help point me in the right direction by comparing what was in the network traffic, and what I should have been sending.