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.
Related
i try to figure it out the black box of the server side that code by python for sending http post. In C# i trying to use httpwebrequest and httpwebresponse to send and receive message back from the server side.
Below is the python code:
**# Request login to server**
import httplib, urllib, requests
import sys, time
from requests.adapters import HTTPAdapter
import select, socket
s = requests.Session()
url = 'http://192.168.1.1/request_login'
data = 'user.login(test,test)' #login account and password set here
r = s.post(url, data=data)
if r.status_code != 200:
print "Failed loging in (%d)" % (r.status_code)
sys.exit(-1)
**# send key file to server**
url = 'http://192.168.1.1/request_sendfile'
files = {'file': (data_xml, open(data_xml, 'rb'), 'application/x-binary', {'Expires': '0'})} # **Don't understand this format**
r = s.post(url, files=files, timeout=30.0)
if r.status_code != 200:
print "Failed sending data file (%d, %s)" % (r.status_code, r.reason)
url = 'http://192.168.1.1/request_sendfile'
data = 'reader.view_log(4)'
r = s.post(url, data=data)
if r.status_code != 200:
print "Failed loging in (%d)" % (r.status_code)
sys.exit(-3)
print "Logs: "
print r.content
sys.exit(-4)
Above is the code for login and sending file to server in one session, i try to use C# do the same way.
I set two http request at the same time, however for the login is success while try to get second http request i get an error of "400" doesn't understand context of verb.
Below is the C# code:
private void httpost()
{
try
{
string Url = "http://192.168.1.1/request_login";
string Urls = "http://192.168.1.1/request_sendfile";
HttpWebRequest request = HttpWebRequest.Create(Url) as HttpWebRequest;
HttpWebRequest requests = HttpWebRequest.Create(Urls) as HttpWebRequest;
string result = null;
request.Method = "POST";
request.KeepAlive = true;
request.ContentType = "login";
string param = "user.login(test,test)";
byte[] bs = Encoding.ASCII.GetBytes(param);
using (Stream reqStream = request.GetRequestStream())
{
reqStream.Write(bs, 0, bs.Length);
}
using (WebResponse response = request.GetResponse())
{
StreamReader sr = new StreamReader(response.GetResponseStream());
HttpWebResponse resp = (HttpWebResponse)request.GetResponse();
if(resp.StatusCode == HttpStatusCode.OK)
{
richTextBox1.AppendText("Login Response Status:" + resp.StatusCode + "\n");
}
else
{
richTextBox1.AppendText("Login Response Failed: " + resp.StatusCode + "\n");
}
request.KeepAlive = true;
result = sr.ReadToEnd();
sr.Close();
}
using (Stream importFile = requests.GetRequestStream())
{
FileStream fs = File.OpenRead(#"data.xml");
byte[] bytes = ReadWholeArray(fs); // turn xml file to byte function
requests.ContentType = "application/x-binary";
requests.Method = "POST";
importFile.Write(bytes, 0, bytes.Length);
}
using (WebResponse responses = requests.GetResponse())
{
StreamReader srs = new StreamReader(responses.GetResponseStream());
result = srs.ReadToEnd();
srs.Close();
}
}
catch (Exception ex)
{
richTextBox1.AppendText("Exception Throw:" + ex.Message);
}
}
I try the python code it request login and send file at the same time.
And below is the code that i don't understand.
files = {'file': (data_xml, open(data_xml, 'rb'), 'application/x-binary', {'Expires': '0'})}
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 ?
I am trying to send JSON Object to Server for data synchronization.
This JSON object contain non-synchronized images and their data.
Real problem is not with he JSON or the Synchronization code.
But it is with the size of the Request i am sending to the server.
if the size cross the limit 1.1MB then i Got this message
The remote server returned an error: (413) Request Entity Too Large.
Please Help me. It is pur C# application not the WCF application.
Domain Hosting provider is Godady.com.
Using Apache server and PHP script.
Every this is working fine for smaller size. but it give exception error when size cross 1.1MB.
Here is My Request Code.
public string SubmitData(string poststring)
{
string result ="false";
if (poststring.ToLower() == "empty")
{
result = "empty";
return result;
}
try
{
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = poststring;
byte[] data = encoding.GetBytes(postData);
WebRequest request = WebRequest.Create("http://blunor.com/dark/data.php");
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Credentials = CredentialCache.DefaultCredentials;
request.ContentLength = data.Length;
Stream stream = request.GetRequestStream();
showMessageBox(data.Length.ToString(), "Message", 1);
stream.Write(data, 0, data.Length);
stream.Close();
WebResponse response = request.GetResponse();
stream = response.GetResponseStream();
StreamReader sr = new StreamReader(stream);
// this block of code check if response is +ve or negtive..
string res_num = sr.ReadToEnd();
if (res_num == "1")
{
result = "true";
}
else
{
result = "false";
}
//block end here.....
sr.Close();
stream.Close();
return result;
}
catch (Exception ex)
{
MessageBox.Show("Error : " + ex.Message);
}
return result;
}
For Server php post_max_size = 128M and Upload_max_filesize = 32M
Please Help......
I'm trying to scrape a website that requires a login. Getting an error that I haven't received before, copied the code from another forum successfully in the past:
Exception Details: System.Net.ProtocolViolationException: Cannot send a content-body with this verb-type.
with the code:
Stream newStream = http.GetRequestStream(); //open connection
Here's the entire code:
#{
var strUserId = "userName";
var strPassword = "password";
var url = "formSubmitLandingSite";
var url2 = "pageToScrape";
HttpWebRequest http = WebRequest.Create(url) as HttpWebRequest;
http.KeepAlive = true;
http.Method = "POST";
http.ContentType = "application/x-www-form-urlencoded";
string postData = "email=" + strUserId + "&password=" + strPassword;
byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(postData);
http.ContentLength = dataBytes.Length;
using (Stream postStream = http.GetRequestStream())
{
postStream.Write(dataBytes, 0, dataBytes.Length);
}
HttpWebResponse httpResponse = http.GetResponse() as HttpWebResponse;
// Probably want to inspect the http.Headers here first
http = WebRequest.Create(url2) as HttpWebRequest;
http.CookieContainer = new CookieContainer();
http.CookieContainer.Add(httpResponse.Cookies);
HttpWebResponse httpResponse2 = http.GetResponse() as HttpWebResponse;
Stream newStream = http.GetRequestStream(); //open connection
newStream.Write(dataBytes, 0, dataBytes.Length); // Send the data.
newStream.Close();
string sourceCode;
HttpWebResponse getResponse = (HttpWebResponse)http.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
{
sourceCode = sr.ReadToEnd();
}
Response.Write(sourceCode);
}
You're creating a new request object here:
http = WebRequest.Create(url2) as HttpWebRequest;
Keep in mind that the default HTTP verb used is GET. Then you try to open the request stream here:
Stream newStream = http.GetRequestStream();
This method is used to enable writing data to the request's content. However, GET requests don't have content. As you do in the code above the error, you'll need to use a different HTTP verb. POST is most common for this, and is what you're using above:
http.Method = "POST";
So just use a POST request again. (Assuming, of course, that's what the server is expecting. In any event, if the server is expecting content then it's definitely not expecting a GET request.)
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.