Take Delay on HttpWebRequest.GetRequestStream - c#

I am using HttpWebRequest.GetRequestStream to connect on the other PHP link from Dot Net to POST some data from .Net to PHP. But its worked fine the first two times when the control come to the line "Stream newrStream = myrRequest.GetRequestStream();" and taking delay for some second from third time onwards.How to slove this problem.
My coding is:
ASCIIEncoding Encode = new ASCIIEncoding();
string postDat = "Name=xxx";
byte[] datas = Encode.GetBytes(postDat);
HttpWebRequest myrRequest = HttpWebRequest)WebRequest.Create("http://www.xxx.php");
myrRequest.Method = "POST";
myrRequest.ContentType = "application/x-www-form-urlencoded";
myrRequest.ContentLength = datas.Length;
Stream newrStream = myrRequest.GetRequestStream();
// Send the data.
newrStream.Write(datas, 0, datas.Length);
newrStream.Close();

The first thing to keep in mind is to review the URI, parameters and headers being sent, specifically:
Reserved characters. Send reserved characters by the URI can bring
problems ! * ' ( ) ; : # & = + $ , / ? # [ ]
URI Length: You should not exceed 2000 characters
Length headers:Most web servers do limit size of headers they
accept. For example in Apache default limit is 8KB.
Keep in mind that if you want to send data from a longer length is recommended to send in the body of the message:
string uri = string.Format("https://my-server.com/api/document?queryParameter={1}", "value");
WebRequest req = WebRequest.Create(uri);
req.Method = "POST";
string data = "Some data"; //Body data
ServicePointManager.Expect100Continue = false;
using (var streamWriter = new StreamWriter(req.GetRequestStream()))
{
streamWriter.Write(data);
streamWriter.Flush();
streamWriter.Close();
}
HttpWebResponse resp = req.GetResponse() as HttpWebResponse;
Stream GETResponseStream = resp.GetResponseStream();
StreamReader sr = new StreamReader(GETResponseStream);
var response = sr.ReadToEnd(); //Response
resp.Close(); //Close response
sr.Close(); //Close StreamReader

Related

Why HttpWebRequest and method POST data is not seen by the server

When I post to server using HttpWebRequest and method POST, the NameValueCollection in the asp code has no values. I have identical code working with other server pages, the only difference is the string data posted is a bit different.
code that posts is from a c# desktop application:
string responseFromServer = string.Empty;
System.Net.HttpWebRequest request = null;
System.IO.StreamReader reader = null;
System.Net.HttpWebResponse response = null;
string http = string.Empty;
http = "http://www.apageonmywebsite.aspx";
request = HttpWebRequest.Create(http) as HttpWebRequest;
request.Method = "POST";
UTF8Encoding encoding = new UTF8Encoding();
//send a namevalue pair -that is what the website expects via the request object
string postData = "TRIALID=" + System.Web.HttpUtility.UrlEncode(trialUserID, encoding);
byte[] byte1 = encoding.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byte1.Length;
request.Timeout = 20000;
System.IO.Stream newStream = request.GetRequestStream();
newStream.Write(byte1, 0, byte1.Length);
newStream.Close();
System.Threading.Thread.Sleep(1000);
response = (HttpWebResponse)request.GetResponse();
System.IO.Stream dataStream = response.GetResponseStream();
reader = new System.IO.StreamReader(dataStream);
responseFromServer = reader.ReadToEnd();
if (responseFromServer.Contains("\r"))
{
responseFromServer = responseFromServer.Substring(0, responseFromServer.IndexOf("\r"));
}
Server code:
NameValueCollection postedValues = Request.Form; // Request.Form worked locally, failed on server(count=0)
IEnumerator myEnumerator = postedValues.GetEnumerator();
try
{
foreach (string s in postedValues.AllKeys)
{
if (s == "TRIALID")
{
regcode += postedValues[s];
break;
}
}
}
catch (Exception ex)
{
Response.Clear();
Response.Write("FAILED");
this.resultMsg = "FAILED. Exception: " + ex.Message;
LogResult();
return;
}
if (string.IsNullOrEmpty(regcode))
{
Response.Write("postedvalues count=" + postedValues.Count.ToString() + ": no regcode:");
this.resultMsg ="postedvalues count=" + postedValues.Count.ToString() + ": no regcode:";
LogResult();
return;
}
In the sending application, responseFromServer is postedvalues count=0:no regcode:
So the data is posted but not "seen" on the server.
The trialUserID field used in the urlencode method is a string containing user domain name plus user name from the Environment object plus the machine name.
Answer to my own question is that the url needs to be https not http.
I converted my asp.net website to https one year ago and when I created the app that sends the posted data I assumed that since the entire website is configured to automatically redirect to https that should take care of it. Clearly, the webrequest needs the https hardcoded in the url.
Just tried to click the Accept button but that is not allowed for two days since I answered my own question.

Setting ContentLength on HttpWebRequest gives me a timeout error

I am creating an android app that connects to my website's api using C# and xamarin. After debugging for a while I realised that when I set the ContentLength the apps seams to hang and then throws an TIMEOUT exception.
I have tried to not set the ContentLength but then the body seams to not send with the request.
public void Post(object data, string route){
string JSON = JsonConvert.SerializeObject(data);
var web = (HttpWebRequest)WebRequest.Create("http://httpbin.org/post");
//web.ContentLenfth = JSON.length;
web.ContentType = "application/json";
web.Method = "POST";
try{
var sw = new StreamWriter(webRequest.GetRequestStream());
sw.Write(JSON);
var webResponse = (HttpWebResponse)webRequest.GetResponse();
var sr = new StreamReader(webResponse.GetResponseStream());
var result = sr.ReadToEnd();
...
}
...
}
If ContentLengt is set the app hangs until the timeout function is called
else the test-url I am posting to tells me that I did not send a body
What do I have to do in order to send a successful POST request ?
You should set the length to be the length of the byte array you are sending (not the length of the string)
You can get the byte array from the json string by doing:
var bytes = Encoding.UTF8.GetBytes(JSON);
Then you can set the content length:
web.ContentLength = bytes.length;
And send the bytes:
using (var requestStream = web.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
}

C# How to keep connection alive while parsing html

I'm trying to create a little script, that lets you login automatically to a php website.
When I looked at the POST script that is being sent through https, I realized that there is a hidden inputform with a hash string (in the login form hidden with css visibility) which is being send in the data form with the email + password
Example:
login=USERNAME&passwort=PASSWORD&loginhash=1b9f29d68152619b469c3744de3a1f54
So actually I would need to do a simple GET action before the post to parse the string out and then do the POST with the loginhash but how do I keep that connection alive without getting a new hash that is not matching anymore?
//GET
WebRequest req = WebRequest.Create(url);
WebResponse resp = req.GetResponse();
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
reqHtml = sr.ReadToEnd();
}
cookieHeader = resp.Headers["Set-cookie"];
//Parsing html and storing to var loginhash
//POST
string formData = string.Format("login={0}&loginhash={1}&passwort={2}", "USERNAME", loginhash, "PASSWORD");
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
req.Headers.Add("Cookie", cookieHeader);
byte[] bytes = Encoding.ASCII.GetBytes(formData);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
Update:
Realized, that my theory is actually wrong as I sent two GET's with curl so that curl would pipeline/reuse the connection before. At the end there were still two different hashes in the responses. Maybe the Hash is just a distraction ?

Trying to upload with a PUT request

I am trying to change the price of an article using the websites API
the documentation for it is at https://www.mkmapi.eu/ws/documentation/API_1.1:Stock
When run the class I get an error 417 Expectation Failed, which is described from the documentation as:
Typically you get a 417 Expectation Failed HTTP status code, when your request has an XML body without the corresponding header and/or the body not sent as text, but its byte representation. Another possible reason for a 417 is, when you send body data with more than 1.024 bytes without adding the header Expect: to your request.
Any help would be appreciated. I should also say that the authentication is not the problem I can download my article prices.
public void UpdateMarketPrice(string MarketID, string NewPrice)
{
// https://www.mkmapi.eu/ws/documentation/API_1.1:Stock
String finalResult;
String method = "PUT";
String url = "https://www.mkmapi.eu/ws/v1.1/stock";
HttpWebRequest request = WebRequest.CreateHttp(url) as HttpWebRequest;
OAuthHeader header = new OAuthHeader();
request.Headers.Add(HttpRequestHeader.Authorization, header.getAuthorizationHeader(method, url));
request.Method = method;
request.ContentType = "text/xml; encoding='utf-8'";
XElement xmlDoc =
new XElement("request",
new XElement("article",
new XElement("idArticle", MarketID),
new XElement("idLanguage", 1),
new XElement("comments", "Edited through the API"),
new XElement("count", 7),
new XElement("price", 11),
new XElement("condition", "NM"),
new XElement("isFoil", false),
new XElement("isSigned", false),
new XElement("isPlayset", false)
)
);
String finalXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + xmlDoc.ToString();
MessageBox.Show(finalXML);
byte[] bytes = Encoding.ASCII.GetBytes(finalXML);
request.ContentLength = bytes.Length;
using (Stream putStream = request.GetRequestStream())
{
putStream.Write(bytes, 0, bytes.Length);
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
finalResult = reader.ReadToEnd();
}
MessageBox.Show(finalResult);
}
I have read that HttpWebRequest adds an "expect 100 continue" header to requests unless you turn it off. There are servers that possibly don't support this header. And will produce this 417 Expectation Failed message.
You could try setting it to false:
System.Net.ServicePointManager.Expect100Continue = false;
So the header isn't sent.
I've seen this suggested sollution to other similar questions also.
Maybe use StreamWriter ?
using (Stream putStream = request.GetRequestStream())
{
using (var writeStream = new StreamWriter(putStream, Encoding.ASCII))
{
writeStream.Write(finalXML);
}
request.ContentLength = putStream.Length; // I am not sure about that
}

How to get access token for google oauth?

I am using C# (ASP.NET). I want to use Google OAuth for accessing the user profile detail in my app. I successfully got the authorization code but having a problem in getting the access token.
I prefer the Google tutorials. In tutorial, I read that I have to send the request and get the response from google. For that, I use System.Net.HttpWebRequest/HttpWebResponse (am I going in the right way). I have used this code...
byte[] buffer = Encoding.ASCII.GetBytes("?code=" + code + "&client_id=xxx&client_secret=xxx&redirect_uri=xxxx&grant_type=authorization_code");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://accounts.google.com");
req.Method = "POST";
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = buffer.Length;
Stream strm = req.GetRequestStream();
strm.Write(buffer, 0, buffer.Length);
strm.Close();
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
Response.Write(((HttpWebResponse)resp).StatusDescription);
But, I got the error:
The remote server returned an error: (405) Method Not Allowed.
Update: Here variable code is authorization code.
I think you are sending the POST request to the wrong endpoint, the correct one is https://accounts.google.com/o/oauth2/token
As I had similar problems in the process of implementing Google auth, I will post the code that works.. The last mentioned problem: error (400) Bad request could be caused by leading '?' in the above code..
string codeClient = "code="+ t +"&client_id=number.apps.googleusercontent.com&";
string secretUri = "client_secret=yoursecret&" + "redirect_uri=path&"
+ "grant_type=authorization_code";
postString = codeClient + secretUri;
string url = "https://accounts.google.com/o/oauth2/token";
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url.ToString());
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
UTF8Encoding utfenc = new UTF8Encoding();
byte[] bytes = utfenc.GetBytes(postString);
Stream os = null;
try
{
request.ContentLength = bytes.Length;
os = request.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
}
catch
{ }
try
{
HttpWebResponse webResponse = (HttpWebResponse) request.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseStreamReader = new StreamReader(responseStream);
result = responseStreamReader.ReadToEnd();//parse token from result
My code is working, I have done mistakes in above two lines. It should be like this
byte[] buffer = Encoding.ASCII.GetBytes("code=" + code + "&client_id=xxx&client_secret=xxx&redirect_uri=xxxx&grant_type=authorization_code");
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token");
Remaining code is correct.
The original request seems to be somewhat outdated. But I found that the Google's code examples contain lots of "Best Practices" housekeeping code that's hard to separate from the essential operations.
I recently published a document that represents all the REST operations as curl commands. It's hard to be conversant in every language, but curl seems universal. Most people know it- otherwise, it's pretty easy to grasp. In my curl examples, the -d flag indicates a POST operation. Otherwise, the parameters are appended to the URL.
http://www.tqis.com/eloquency/googlecalendar.htm
public string ReceiveTokenGmail(string code, string GoogleWebAppClientID, string GoogleWebAppClientSecret, string RedirectUrl)
{
string postString = "code=" + code + "&client_id=" + GoogleWebAppClientID + #"&client_secret=" + GoogleWebAppClientSecret + "&redirect_uri=" + RedirectUrl;
string url = "https://accounts.google.com/o/oauth2/token";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.ToString());
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
UTF8Encoding utfenc = new UTF8Encoding();
byte[] bytes = utfenc.GetBytes(postString);
Stream os = null;
try
{
request.ContentLength = bytes.Length;
os = request.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
}
catch
{ }
string result = "";
HttpWebResponse webResponse = (HttpWebResponse)request.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseStreamReader = new StreamReader(responseStream);
result = responseStreamReader.ReadToEnd();
return result;
}
It was surprisingly difficult to find the correct and simple way of getting access token by auth code. (Especially because it has taken some time for me and then even with the correct code I got “invalid_grant” error because my auth code expired while searching :) )
So here is the code:
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets()
{
// Use ones from "Web SDK configuration" section if you created your app in Firebase.
ClientId = "…",
ClientSecret = "…"
},
Scopes = new[] { "email" },
}
);
TokenResponse token = await flow.ExchangeCodeForTokenAsync(string.Empty, "4/…", string.Empty, CancellationToken.None);
As you can see, userId can be just empty, as well as redirectUri.
Don’t forget to add the Google.Apis.Auth Nuget package reference.

Categories

Resources