Invoking a POST to an external site with C# (httpwebrequest) - c#

This is driving me nuts and I can't figure out where I am dropping the ball. I've followed a few examples found via the googlemonsta to no avail. Any pointer to where I goofed would be greatly apperciated.
var writer = new StringWriter();
param = "location=" + Server.UrlEncode(param);
byte[] paramStream = Encoding.ASCII.GetBytes(param + "&param2=value");
var URL = "http://www.somesite.com";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 6.0; sv-SE; rv:1.9.1b2) Gecko/20081201 Firefox/3.1b2";
request.ContentLength = paramStream.Length;
using( var stream = request.GetRequestStream())
{
stream.Write(paramStream, 0, paramStream.Length);
}
var response = request.GetResponse();
string result;
using (var sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
}
Thanks!
EDIT: As far as I can tell its hitting the site (i'm getting html back) but the params aren't pushed over. I'm basically getting where the values would appear had it been successful. I've tried removing the first & but didnt get anywhere.
EDIT: Edited code to reflect changes.

Possibly get rid of the & from the start of the first parameter? Other than that it basically looks okay. (Check the parameter names in your real code - where you've got "paramater" in the sample it should almost certainly be "parameter" - but we don't know what your real code looks like or what the real site expects.)
Please give more information about what's actually happening. We know it doesn't work, but there are a lot of different possible failure modes :)
One extra thought occurs - you haven't specified the content length. I'm not sure whether this is filled in automatically by WebRequest. It would be worth using WireShark to check whether or not it's present in the outbound request.
Just as a general point of practice, you should dispose of the WebResponse, and you don't need to call Close if you've already got a using statement for the response stream:
string result;
using (WebResponse response = request.GetResponse())
{
using (var sr = new StreamReader(response.GetResponseStream()))
{
result = sr.ReadToEnd();
}
}

Are you sure you have all the values neccessary for the post? I once had a case where there was a hidden input field on the form that was something like:
<input name="action" type="hidden" id="action" value="login">
and I had to supply that as a param as:
&action=login
Make sure you're not missing anything from the form is what I'm saying...
EDIT: One more thing: I just looked at my code again where I've done this, and noticed that I also had this line in there:
request.ContentLength = bytes.Length;
Not sure if you need that, but I noticed that you weren't setting the length.

It is not something as simple as a carriage-return/new-line after the parameters is it? Looking at some docs on HTTP on the internets, you apparently need a blank line afterwards.
(I would suggest telneting to the web server manually and pasting your request.)

Related

C# WebRequest timeout on second call

The first time I call this function everything works perfect.
When I call it the second time I get an exception Host is not responding correclty
I tried everything for hours but I dont get it to work.
Is it the website or is something wrong with my code?
string url = "https://www.nseindia.com/live_market/dynaContent/live_watch/option_chain/optionKeys.jsp";
string website = "";
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
httpRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
httpRequest.Timeout = 5000;
using (var response = (HttpWebResponse)httpRequest.GetResponse())
{
using (StreamReader Reader = new StreamReader(response.GetResponseStream()))
{
website = Reader.ReadToEnd();
}
}
httpRequest.Abort();
Please, on every question that you are going to do here, try to put as maximum of details as possible. It will become easier for us to help you on your problems. Especially the exceptions that you are having doing the development.
About your code, the implementation of that is not recommended for Microsoft. Looking at the docs https://learn.microsoft.com/en-us/dotnet/api/system.net.httpwebrequest?view=netframework-4.8 there is a part that says: We don't recommend that you use HttpWebRequest for new development. Instead, use the System.Net.Http.HttpClient class.
Try to change your implementation to use the class HttpClient, and see if the error is going to occur again.

MANDATORY_FIELDS_MISSING: lastname does not have a value

I am getting very frustrated. I am using .NET to import a bunch of leads in to vTiger 6.2.0. I am using a simple web request that i have seen plenty of examples working. I have also seen it working from my dev environment and i would intermittently get the above response from the service. I have moved over to using live data (still from my machine). There is no reason for the imports to fail as they all contain a last name.
I have scoured the internet for any relevant information and have come up blank.
I am using a post request in the following way...
byte[] bytes = Encoding.ASCII.GetBytes(requestParameters);
WebRequest request = HttpWebRequest.Create(url) as WebRequest;
request.ContentLength = bytes.Length;
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
using (var swRequest = request.GetRequestStream())
{
swRequest.Write(bytes, 0, bytes.Length);
}
The request URL (minus the domain) looks like this: /webservice.php?operation=create
The requestParameters variable looks like this (anonymised the data where there was data):
operation=create&sessionName=660f54e47e39358ce&element={"leadsource":"blaah","cf_757":"blaah","salutationtype":"0.","firstname":"blaah","lastname":"blaah","email":"blaah","phone":"blaah","description":"blaah","cf_833":"blaah","emailoptout":"1","cf_761":"1","cf_759":"1","cf_763":"1","assigned_user_id":"19x5"}&elementType=Leads
in the response i get back i receive the error below for nearly every record.
MANDATORY_FIELDS_MISSING: lastname does not have a value.
Last name and assigned user are the only mandatory values needed and the assigned user is the id returned from the login.
Is anybody able to provide some help on this? i have spent hours on it with no success.

Login to website using C#

Before everyone gets upset that this has been answered. I have scoured the web looking for how to do this and have tried a number of methods. Login to website, via C# and How to programmatically log in to a website to screenscape? Both of these were helpful but I cannot figure out why I cannot get past the login page. Here is my code:
string url = "https://www.advocare.com/login.aspx";
string url2 = "https://url.after.login";
HttpWebRequest wReq = WebRequest.Create(url) as HttpWebRequest;
wReq.KeepAlive = true;
wReq.Method = "POST";
wReq.AllowAutoRedirect = false;
wReq.ContentType = "application/x-www-form-urlencoded";
string postData = "ctl00$cphContent$txtUserName=Username&ctl00$cphContent$txtPassword=Password";
byte[] dataBytes = UTF8Encoding.UTF8.GetBytes(postData);
wReq.ContentLength = dataBytes.Length;
using (Stream postStream = wReq.GetRequestStream())
{
postStream.Write(dataBytes, 0, dataBytes.Length);
}
HttpWebResponse wResp = wReq.GetResponse() as HttpWebResponse;
string pageSource;
wReq = WebRequest.Create(url2) as HttpWebRequest;
wReq.CookieContainer = new CookieContainer();
wReq.CookieContainer.Add(wResp.Cookies);
HttpWebResponse wResp2 = wReq.GetResponse() as HttpWebResponse;
using (StreamReader sr = new StreamReader(wResp2.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
Everytime I look at pageSource it is the HTML for the login.aspx page. I must be missing something here. Maybe it's not taking the cookie, I don't know. One question I have aside from, why doesn't this work, is in the string postData = "". Are those suppose to be the name or id portion of the html tag? Any help on this is greatly appreciated as I am stumped and will have to find a different way. I would like to continue with the WebRequest and WebResponse instead of using WebBrowser. If I can't, oh well. Thanks again for any help!
What are you trying to do besides login? If its like QAing a site programically, i would suggest using selenium andcreate a c# app based off of that. If u want i can post a link to a base project for a selenium based project.
Don't necessarily view the page source, but look at the actual HTTP POST. Install a HTTP proxy such as Fiddler and then re-visit the page you are trying to emulate. Complete the HTTP POST request, and check out the results produced in the proxy. From there you'll be able to see the actual parameters, cookies, headers, etc. that are being passed and you can then attempt to replicate this in your code. It's often easy to miss something when simply viewing the HTML source but monitoring the network traffic is pretty straight forward.

Communicating with an ASP website

I have a know a website that contains an open database of the result of an academic test.
http://nts.org.pk/NTSWeb/PPL_30Sep2012_Result/search.asp
I am expert with C# but newbie to web development.
Usually, using web browser, we can enter and roll number and server sends back the result. E.G. Use my Roll Num: 3912125
What I need to do is, use a C# application to communicate this roll null number and get anything, of my result. (any string is excepted, I will parse out my result from that string.)
How do I send query? when I don't know a list of possible query strings.
I tried this code:
string queryString = "RollNo=3912125";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(#"http://nts.org.pk/NTSWeb/PPL_30Sep2012_Result/search.asp");
request.UseDefaultCredentials = true;
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
byte[] requestBytes = Encoding.UTF8.GetBytes(queryString);
request.ContentLength = requestBytes.Length;
using (var requestStream = request.GetRequestStream())
{
requestStream.Write(requestBytes, 0, requestBytes.Length);
requestStream.Close();
}
WebResponse response = request.GetResponse();
textBox1.AppendText(((HttpWebResponse)response).StatusDescription);
Stream dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();
textBox1.AppendText(responseFromServer);
reader.Close();
dataStream.Close();
response.Close();
You have to append the querystring to the url like this:
string queryString = "RollNo=3912125";
string url = String.Format(#"http://foo/search.asp?{0}", queryString);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
You should take a look at the code in my answer to C# https login and download file. It gives a good demonstration of how to perform a POST request. As far as knowing what's valid to use for the query-formatted string in your POST, it's simply a matter of looking for appropriate input elements in the page content. It looks like what you have (RollNo) is correct. You may, however, need to also add the submit button value to your request as well depending on how the server behaves, giving you something like. RollNo=3912125&submit=submit.
You're most of the way there. Your queryString should look like RollNo=3912125&Submit=+Search+. When you are calling WebRequest.Create, the Url should in fact be http://nts.org.pk/NTSWeb/PPL_30Sep2012_Result/result.asp.
The rest of your code should work, though the answer #JamieSee recommended to you has some very good advice about wrapping things in using blocks correctly

Can I send an empty HTTP POST WebRequest object from C# to IIS?

Do I need to just slap some random garbage data in a WebRequest object to get by the HTTP status code 411 restriction on IIS?
I have an HttpPost action method in an MVC 3 app that consumes a POST request with all the relevant information passed in the querystring (no body needed).
[HttpPost] public ActionResult SignUp(string email) { ... }
It worked great from Visual Studio's built in web host, Cassini. Unfortunately, once the MVC code was live on IIS [7.5 on 2008 R2], the server is pitching back an HTTP error code when I hit it from my outside C# form app.
The remote server returned an error:
(411) Length Required.
Here is the calling code:
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
using (WebResponse response = request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (StreamReader responseReader = new StreamReader(responseStream)) {
// Do something with responseReader.ReadToEnd();
}
Turns out you can get this to go through by simply slapping an empty content length on the request before you send it.
WebRequest request = WebRequest.Create("http://somewhere.com/signup/?email=a#b.com");
request.Method = "POST";
request.ContentLength = 0;
Not sure how explicitly giving an empty length vs. implying one makes a difference, but IIS was happy after I did. There are probably other ways around this, but this seems simple enough.
I believe you are required to set a Content-Length header anytime you post a request to a web server:
http://msdn.microsoft.com/en-us/library/system.web.httprequest.contentlength.aspx
You could try a GET request to test it.

Categories