How to submit http form using C# - c#

I have a simple html file such as
<form action="http://www.someurl.com/page.php" method="POST">
<input type="text" name="test"><br/>
<input type="submit" name="submit">
</form>
Edit: I may not have been clear enough with the question
I want to write C# code which submits this form in the exact same manner that would occur had I pasted the above html into a file, opened it with IE and submitted it with the browser.

Here is a sample script that I recently used in a Gateway POST transaction that receives a GET response. Are you using this in a custom C# form? Whatever your purpose, just replace the String fields (username, password, etc.) with the parameters from your form.
private String readHtmlPage(string url)
{
//setup some variables
String username = "demo";
String password = "password";
String firstname = "John";
String lastname = "Smith";
//setup some variables end
String result = "";
String strPost = "username="+username+"&password="+password+"&firstname="+firstname+"&lastname="+lastname;
StreamWriter myWriter = null;
HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);
objRequest.Method = "POST";
objRequest.ContentLength = strPost.Length;
objRequest.ContentType = "application/x-www-form-urlencoded";
try
{
myWriter = new StreamWriter(objRequest.GetRequestStream());
myWriter.Write(strPost);
}
catch (Exception e)
{
return e.Message;
}
finally {
myWriter.Close();
}
HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();
using (StreamReader sr =
new StreamReader(objResponse.GetResponseStream()) )
{
result = sr.ReadToEnd();
// Close and clean up the StreamReader
sr.Close();
}
return result;
}

Your HTML file is not going to interact with C# directly, but you can write some C# to behave as if it were the HTML file.
For example: there is a class called System.Net.WebClient with simple methods:
using System.Net;
using System.Collections.Specialized;
...
using(WebClient client = new WebClient()) {
NameValueCollection vals = new NameValueCollection();
vals.Add("test", "test string");
client.UploadValues("http://www.someurl.com/page.php", vals);
}
For more documentation and features, refer to the MSDN page.

You can use the HttpWebRequest class to do so.
Example here:
using System;
using System.Net;
using System.Text;
using System.IO;
public class Test
{
// Specify the URL to receive the request.
public static void Main (string[] args)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create (args[0]);
// Set some reasonable limits on resources used by this request
request.MaximumAutomaticRedirections = 4;
request.MaximumResponseHeadersLength = 4;
// Set credentials to use for this request.
request.Credentials = CredentialCache.DefaultCredentials;
HttpWebResponse response = (HttpWebResponse)request.GetResponse ();
Console.WriteLine ("Content length is {0}", response.ContentLength);
Console.WriteLine ("Content type is {0}", response.ContentType);
// Get the stream associated with the response.
Stream receiveStream = response.GetResponseStream ();
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader readStream = new StreamReader (receiveStream, Encoding.UTF8);
Console.WriteLine ("Response stream received.");
Console.WriteLine (readStream.ReadToEnd ());
response.Close ();
readStream.Close ();
}
}
/*
The output from this example will vary depending on the value passed into Main
but will be similar to the following:
Content length is 1542
Content type is text/html; charset=utf-8
Response stream received.
<html>
...
</html>
*/

Response.Write("<script> try {this.submit();} catch(e){} </script>");

I needed to have a button handler that created a form post to another application within the client's browser. I landed on this question but didn't see an answer that suited my scenario. This is what I came up with:
protected void Button1_Click(object sender, EventArgs e)
{
var formPostText = #"<html><body><div>
<form method=""POST"" action=""OtherLogin.aspx"" name=""frm2Post"">
<input type=""hidden"" name=""field1"" value=""" + TextBox1.Text + #""" />
<input type=""hidden"" name=""field2"" value=""" + TextBox2.Text + #""" />
</form></div><script type=""text/javascript"">document.frm2Post.submit();</script></body></html>
";
Response.Write(formPostText);
}

I had a similar issue in MVC (which lead me to this problem).
I am receiving a FORM as a string response from a WebClient.UploadValues() request, which I then have to submit - so I can't use a second WebClient or HttpWebRequest. This request returned the string.
using (WebClient client = new WebClient())
{
byte[] response = client.UploadValues(urlToCall, "POST", new NameValueCollection()
{
{ "test", "value123" }
});
result = System.Text.Encoding.UTF8.GetString(response);
}
My solution, which could be used to solve the OP, is to append a Javascript auto submit to the end of the code, and then using #Html.Raw() to render it on a Razor page.
result += "<script>self.document.forms[0].submit()</script>";
someModel.rawHTML = result;
return View(someModel);
Razor Code:
#model SomeModel
#{
Layout = null;
}
#Html.Raw(#Model.rawHTML)
I hope this can help anyone who finds themselves in the same situation.

Related

Why "Cookies Disabled" occurs when the same Httprequest function is called again?

To workaround the "Cookies Disabled" issue, I use
CookieContainer myContainer = new CookieContainer();
request.CookieContainer = myContainer;
This works when the getIDfromWeb function is first called.
However, when the getIDfromWeb function is called again, "Cookies disabled" occurs.
How should I workaround this issue?
To reproduce the same issue, you need to meet the "Cookies Disabled" issue when you do not include "request.CookieContainer = myContainer;" otherwise your url may not need authentication.
Although I can get the information by placing my URL on the IE address bar and hitting enter, I met authorization error when implementing this from C#. I use httpwebrequest and cookies to workaround issue but found I met "Cookies disabled" issue when I called the function the second time.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication3
{
class Program
{
const string baseURL = "http://intranet/rest/reserveid.php";
static void Main(string[] args)
{
Console.WriteLine("Key1 sample:");
Console.WriteLine(getIDfromWeb("key1"));
Console.WriteLine("key1. sample2:");
Console.WriteLine(getIDfromWeb("key1"));
Console.ReadKey();
}
static string getIDfromWeb(string idType)
{
int startPos = 0;
string url = "";
switch (idType)
{
case "key1":
startPos = 19;
url = baseURL + "?querystringforkey1";
break;
case "key2":
startPos = 15;
url = baseURL + "?querystringforkey2";
break;
}
CookieContainer myContainer = new CookieContainer();
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Credentials = CredentialCache.DefaultNetworkCredentials;
request.CookieContainer = myContainer;
request.PreAuthenticate = true;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
var 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.
reader.Close();
response.Close();
return responseFromServer.Substring(startPos, (responseFromServer.IndexOf("}]") - startPos - 1));
}
}
}
Its work for me.
Here is Updated your code, Please check.
static void Main(string[] args)
{
Console.WriteLine("Key1 sample:");
Console.WriteLine(getIDfromWeb("key1"));
Console.WriteLine("key1. sample2:");
Console.WriteLine(getIDfromWeb("key2"));
Console.ReadKey();
}
Replace below line
Console.WriteLine(getIDfromWeb("key2"));

GetResponse() Error in the PayPal functionality when trying to checkout

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.

NULL JSON posted onto PHP server using HTTP requests from C#

I'm trying to post a JSON string on a PHP page using HTTP response methods as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Web.Script.Serialization;
using System.Web;
namespace http_requests
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost/abc/products.php");
//httpWebRequest.ContentType = "application/json";
//httpWebRequest.Method = "POST";
//using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
//{
// string json = new JavaScriptSerializer().Serialize(new
// {
// user = "Foo",
// password = "Baz"
// });
// streamWriter.Write(json);
// streamWriter.Flush();
// streamWriter.Close();
// var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
// using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
// {
// var result = streamReader.ReadToEnd();
// }
//}
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://localhost/ABC/products.php");
request.Method = WebRequestMethods.Http.Post;
string DataToPost = new JavaScriptSerializer().Serialize(new
{
user = "Foo",
password = "Baz"
});
byte[] bytes = Encoding.UTF8.GetBytes(DataToPost);
string byteString = Encoding.UTF8.GetString(bytes);
Stream os = null;
//string postData = "firstName=" + HttpUtility.UrlEncode(p.firstName) +
request.ContentLength = bytes.Length;
request.ContentType = "application/x-www-form-urlencoded";
os = request.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
//StreamWriter writer = new StreamWriter(request.GetRequestStream());
//writer.Write(DataToPost);
//writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
//StreamReader reader = new StreamReader(response.GetResponseStream());
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
richTextBox1.AppendText("R : " + result);
Console.WriteLine(streamReader.ReadToEnd().Trim());
}
//richTextBox1.Text = response.ToString();
}
}
}
I tried it in many different ways (converting to bytes too) but still posts a NULL array.
PHP Code:
<?php
$json = $_POST;
if (isset($json)) {
echo "This var is set so I will print.";
//var_dump($json);
var_dump(json_decode(file_get_contents('php://input')));
}
?>
When I try to get tha response from server and print onto a text box, it prints right:
R : This var is set so I will print.object(stdClass)#1 (2) {
["user"]=>
string(3) "Foo"
["password"]=>
string(3) "Baz"
}
but i'm unable to check it on my PHP page, it says:
This var is set so I will print.NULL
Not sure if its posting a JSON onto PHP or not, but it sure does posts a NULL.
I want to see the JSON on PHP page, Any help would be appreciated.
Thank you,
Revathy
There is nothing wrong with your c# client side code, the problem is that visiting a site in your browser is a seperate request from the c# post, so you wont see anything.
As per my comment, if you want to see the data in a browser after a post i c#, you will need to save and retrieve it.
Here is a simple example using a text file to save post data and display it:
//if post request
if($_SERVER['REQUEST_METHOD']=='POST'){
//get data from POST
$data = file_get_contents('php://input');
//save to file
file_put_contents('data.txt', $data);
die('Saved');
}
//else if its a get request (eg view in browser)
var_dump(json_decode(file_get_contents('data.txt')));

how to log in to this web page automatically

http://www.conquerclub.com/game.php?game=13025037
Please does anyone know how I can programatically log onto this address and then get all the html of the page back as a string Using something like HttpWebRequest/HttpWebResponse.
username - "testuser1"
password - "testing"
(I've created an account on the site with these credentials so it will actually logon)
So far I've got this
private void toolStripButton1_Click(object sender, EventArgs e)
{
var request = WebRequest.Create("http://www.conquerclub.com/game.php?game=13025037");
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
richTextBox1.Text = reader.ReadToEnd();
}
This automatically re-directs and returns the html of the login page. How do I pass the username and password to login automatically so it retrieves the game page instead?
I know there are quite a few similar questions on this and I've spent several hours trying different things but can't get anything to work.
Edit:-
Looked into this further and this site uses cookies for logging in.
Tried this code but is still just returning the login page.
private void toolStripButton1_Click(object sender, EventArgs e)
{
string loginUri = "http://www.conquerclub.com/login.php";
string username = "testuser1";
string password = "testing";
string reqString = "username=" + username + "&password=" + password;
byte[] requestData = Encoding.UTF8.GetBytes(reqString);
CookieContainer cc = new CookieContainer();
var request = (HttpWebRequest)WebRequest.Create(loginUri);
request.Proxy = null;
request.AllowAutoRedirect = false;
request.CookieContainer = cc;
request.Method = "post";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = requestData.Length;
using (Stream s = request.GetRequestStream())
s.Write(requestData, 0, requestData.Length);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
if (response.Cookies != null)
{
foreach (Cookie c in response.Cookies)
Console.WriteLine(c.Name + " = " + c.Value);
}
}
string newloginUri = "http://www.conquerclub.com/game.php?game=13025037";
HttpWebRequest newrequest = (HttpWebRequest)WebRequest.Create(newloginUri);
newrequest.Proxy = null;
newrequest.CookieContainer = cc;
using (HttpWebResponse newresponse = (HttpWebResponse)newrequest.GetResponse())
using (Stream resSteam = newresponse.GetResponseStream())
using (StreamReader sr = new StreamReader(resSteam))
richTextBox1.Text = sr.ReadToEnd();
}
Have found that the code at the bottom to log into the game page can be made to work by first logging in manually while using fiddler on firefox then copy and pasting the cookies and hard coding them into newrequest like this.
string newloginUri = "http://www.conquerclub.com/game.php?game=13025037";
HttpWebRequest newrequest = (HttpWebRequest)WebRequest.Create(newloginUri);
newrequest.Proxy = null;
newrequest.CookieContainer = new CookieContainer();
newrequest.CookieContainer.Add(new Uri("http://www.conquerclub.com"), new Cookie("PHPSESSID","86bte1ipainiq760vm2flv4h13"));
newrequest.CookieContainer.Add(new Uri("http://www.conquerclub.com"), new Cookie("phpbb3_jer7c_u", "648113"));
newrequest.CookieContainer.Add(new Uri("http://www.conquerclub.com"), new Cookie("phpbb3_jer7c_k", ""));
newrequest.CookieContainer.Add(new Uri("http://www.conquerclub.com"), new Cookie("phpbb3_jer7c_sid", "3eebb0771a68c4a58581e495c34b2c93"));
using (HttpWebResponse newresponse = (HttpWebResponse)newrequest.GetResponse())
using (Stream resSteam = newresponse.GetResponseStream())
using (StreamReader sr = new StreamReader(resSteam))
richTextBox1.Text = sr.ReadToEnd();
This returns the game page as I want it to but can't figure out how to get the login working so that it will return the right cookies. On debugging the code the cookies that come back are completely different to the ones I'm seeing in fiddler so looks like it's just not logging in.
The code that you've written does a GET of the URL given; however, to retrieve the content of the page when you log in you need to pretend that your WebRequest is actually filling in the form, by passing in all the form variables and issuing a POST request instead.
http://msdn.microsoft.com/en-us/library/debx8sh9.aspx gives a good walkthrough of the steps you require. The following isn't 100% complete, but should give you a step in the right direction:
var request = WebRequest.Create("http://www.conquerclub.com/login.php");
request.Method = "POST";
var parameters = new Dictionary<string, string> {
{ "username", "testuser1" },
{ "password", "testing" },
{ "redirect", "game.php?game=13025037" },
{ "direct", "63###www.conquerclub.com###" },
{ "protocol", "HTTP" },
{ "submit", "Login" } };
var content = string.Join( "&", ( from p in parameters select p.Key + "=" + HttpUtility.UrlEncode( p.Value) ).ToArray() ); ;
byte[] bytes = new byte[content.Length * sizeof(char)];
System.Buffer.BlockCopy(content.ToCharArray(), 0, bytes, 0, bytes.Length);
request.ContentLength = bytes.Length;
request.ContentType = "application/x-www-form-urlencoded";
Stream dataStream = request.GetRequestStream();
dataStream.Write( bytes, 0, bytes.Length );
dataStream.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadToEnd();
Note that content includes various values that aren't visible on-screen; these can be seen by viewing the form's source, or (easier) by using the 'Network' tab on your browser debug toolbar of choice and monitoring the data being sent when the form is submitted.
You need to mimic the process of logging in. Look at the HTML code for the login page, and find out three things:
The <form> that sends the request, specifically the target (found in the attribute action) of the form.
Find out the method of sending the data (found in the attribute method)
Find the ID of the fields that represent the user name and password.
Having those you can easily construct a WebRequest that mimics a login.
Note, that this assumes a straight forward login screen (no AJAX, no CAPTCHAs).

Uploading images to Imgur.com using C#

I just recieve my unique developer API key from Imgur and I'm aching to start cracking on this baby.
First a simple test to kick things off. How can I upload an image using C#? I found this using Python:
#!/usr/bin/python
import pycurl
c = pycurl.Curl()
values = [
("key", "YOUR_API_KEY"),
("image", (c.FORM_FILE, "file.png"))]
# OR: ("image", "http://example.com/example.jpg"))]
# OR: ("image", "BASE64_ENCODED_STRING"))]
c.setopt(c.URL, "http://imgur.com/api/upload.xml")
c.setopt(c.HTTPPOST, values)
c.perform()
c.close()
looks like the site uses HTTP Post to upload images. Take a look at the HTTPWebRequest class and using it to POST to a URL: Posting data with HTTPRequest.
The Imgur API now provide a complete c# example :
using System;
using System.IO;
using System.Net;
using System.Text;
namespace ImgurExample
{
class Program
{
static void Main(string[] args)
{
PostToImgur(#"C:\Users\ashwin\Desktop\image.jpg", IMGUR_ANONYMOUS_API_KEY);
}
public static void PostToImgur(string imagFilePath, string apiKey)
{
byte[] imageData;
FileStream fileStream = File.OpenRead(imagFilePath);
imageData = new byte[fileStream.Length];
fileStream.Read(imageData, 0, imageData.Length);
fileStream.Close();
string uploadRequestString = "image=" + Uri.EscapeDataString(System.Convert.ToBase64String(imageData)) + "&key=" + apiKey;
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("http://api.imgur.com/2/upload");
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ServicePoint.Expect100Continue = false;
StreamWriter streamWriter = new StreamWriter(webRequest.GetRequestStream());
streamWriter.Write(uploadRequestString);
streamWriter.Close();
WebResponse response = webRequest.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader responseReader = new StreamReader(responseStream);
string responseString = responseReader.ReadToEnd();
}
}
}
Why don't you use the NuGet for this: called Imgur.API and for upload
you would have a method like this:
/*
The refresh token and all the values represented by constans are given when you allow the application in your imgur panel on the response url
*/
public OAuth2Token CreateToken()
{
var token = new OAuth2Token(TOKEN_ACCESS, REFRESH_TOKEN, TOKEN_TYPE, ID_ACCOUNT, IMGUR_USER_ACCOUNT, int.Parse(EXPIRES_IN));
return token;
}
//Use it only if your token is expired
public Task<IOAuth2Token> RefreshToken()
{
var client = new ImgurClient(CLIENT_ID, CLIENT_SECRET);
var endpoint= new OAuth2Endpoint(client);
var token = endpoint.GetTokenByRefreshTokenAsync(REFRESH_TOKEN);
return token;
}
public async Task UploadImage()
{
try
{
var client = new ImgurClient(CLIENT_ID, CLIENT_SECRET, CreateToken());
var endpoint = new ImageEndpoint(client);
IImage image;
//Here you have to link your image location
using (var fs = new FileStream(#"IMAGE_LOCATION", FileMode.Open))
{
image = await endpoint.UploadImageStreamAsync(fs);
}
Debug.Write("Image uploaded. Image Url: " + image.Link);
}
catch (ImgurException imgurEx)
{
Debug.Write("Error uploading the image to Imgur");
Debug.Write(imgurEx.Message);
}
}
Also you can find all the reference here: Imgur.API NuGet

Categories