How to fill forms and submit with Webclient in C# - c#

I'm new at using the the libraries WebClient, HttpResponse and HttpRequest in C#, so bear with me, if my question is confusing to read.
I need to build a WinForm based on C# which can open a URL, which is secured with the basic authorization. I did this with adding this to the header, like this:
using (WebClient wc = new WebClient())
{
wc.Headers.Add(HttpRequestHeader.Authorization, "Basic " +
Convert.ToBase64String(
Encoding.ASCII.GetBytes(username + ":" + password)));
}
So far, so good! Now I would like to fill a form with a number, and I find the source-code from the site, and discover that the name is "number". So I write this:
NameValueCollection formData = new NameValueCollection();
formData["number"] = number
byte[] responseBytes = wc.UploadValues(theurl, "POST", formData);
string response = Encoding.ASCII.GetString(responseBytes);
textBox_HTML.Text = response;
But how do I submit this? I will like to receive my "search-results"...

You should probably be using HttpWebRequest for this. Here's a simple example:
var strId = UserId_TextBox.Text;
var strName = Name_TextBox.Text;
var encoding=new ASCIIEncoding();
var postData="userid="+strId;
postData += ("&username="+strName);
byte[] data = encoding.GetBytes(postData);
var myRequest =
(HttpWebRequest)WebRequest.Create("http://localhost/MyIdentity/Default.aspx");
myRequest.Method = "POST";
myRequest.ContentType="application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
var newStream=myRequest.GetRequestStream();
newStream.Write(data,0,data.Length);
newStream.Close();
var response = myRequest.GetResponse();
var responseStream = response.GetResponseStream();
var responseReader = new StreamReader(responseStream);
var result = responseReader.ReadToEnd();
responseReader.Close();
response.Close();

Try this:
using System.Net;
using System.Collections.Specialized;
NameValueCollection values = new NameValueCollection();
values.Add("TextBox1", "value1");
values.Add("TextBox2", "value2");
values.Add("TextBox3", "value3");
string Url = urlvalue.ToLower();
using (WebClient client = new WebClient())
{
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
byte[] result = client.UploadValues(Url, "POST", values);
string ResultAuthTicket = System.Text.Encoding.UTF8.GetString(result);
}

I have found a solution to my problem. First of all I was confused about some of the basics in http-communication. This was caused by a python-script i wrote, which have a different approach with the communication.
I solved it with generating the POST-data from scratch and open the uri, which was contained in the form-action.

BFree's answer works great. One thing I would note, though, is that the data concatenation should really be url-encoded, otherwise you'd have trouble with things like "=" and "&" signs within the data.
The VB.NET version, urlencoded and with UTF-8 support, is below (note that url-encoding requires a reference to System.Web.dll, which only worked for me after I switched from .NET 4 Compact Framework to the regular .NET 4 Framework).
Imports System.Web
Imports System.Net
Imports System.IO
Public Class WebFormSubmitter
Public Shared Function submit(ByVal address As String,
ByVal values As Dictionary(Of String, String)) As String
Dim encoding As New UTF8Encoding
Dim postData As String = getPostData(values:=values)
Dim data() As Byte = encoding.GetBytes(postData)
Dim request = CType(WebRequest.Create(address), HttpWebRequest)
request.Method = "POST"
request.ContentType = "application/x-www-form-urlencoded"
request.ContentLength = data.Length
Dim newStream = request.GetRequestStream()
newStream.Write(data, 0, data.Length)
newStream.Close()
Dim response = request.GetResponse()
Dim responseStream = response.GetResponseStream()
Dim responseReader = New StreamReader(responseStream)
Return responseReader.ReadToEnd()
End Function
Private Shared Function getPostData(ByVal values As Dictionary(Of String, String)) As String
Dim postDataPairList As New List(Of String)
For Each anEntry In values
postDataPairList.Add(anEntry.Key & "=" & HttpUtility.UrlEncode(anEntry.Value))
Next
Return String.Join(separator:="&", values:=postDataPairList)
End Function
End Class

Posting a form with System.Net.Http.HttpClient and reading the response as string:
var formData = new Dictionary<string, string>();
formData.Add("number", number);
var content = new FormUrlEncodedContent(formData);
using (var httpClient = new HttpClient())
{
var httpResponse = await httpClient.PostAsync(theurl, content);
var responseString = await httpResponse.Content.ReadAsStringAsync();
}

You submitted it already with UploadValues. The question is: what is your "result-search"? What does the page return? HTML? If so - the HTML Agility Pack is the easiest way to parse html.

Related

C# how to consume rest web service

I am having a problem when I try using a rest web service in C#.
When I try via Fiddler it works Ok.
When I try via HTML/Ajax, it works Ok, as well.
When I try via C# (Console Application) I get an error.
This image is captured in fiddler. It is what I get when I try via ajax
this image is also captured in fiddler. It is what I get when I try via C#
As you can see, the JSON field is empty.
This is my C# code
string json = JsonConvert.SerializeObject(abc);
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("MyURL"); //==> I am filling it correctly
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var response = client.PostAsJsonAsync("MyMethod", json).Result; //==> I am filling my method correctly
But I have tried several others and always getting the same problem. (the code bellow is another one I tried)
var requisicaoWeb = WebRequest.CreateHttp("MyURL");
requisicaoWeb.Method = "POST";
requisicaoWeb.ContentType = "application/json";
requisicaoWeb.ContentLength = dados.Length;
requisicaoWeb.UserAgent = "Console app";
requisicaoWeb.Accept = "Accept:application/json,text/javascript,*/*;q=0.01";
//precisamos escrever os dados post para o stream
using (var stream = requisicaoWeb.GetRequestStream())
{
stream.Write(MyJson, 0, dados.Length);
stream.Close();
}
//ler e exibir a resposta
using (var resposta = requisicaoWeb.GetResponse())
{
var streamDados = resposta.GetResponseStream();
StreamReader reader = new StreamReader(streamDados);
object objResponse = reader.ReadToEnd();
var post = objResponse.ToString();//JsonConvert.DeserializeObject<Post>(objResponse.ToString());
streamDados.Close();
resposta.Close();
}
Everything I try in C#, the JSON field on Fiddler is always empty and the "syntax View" description is always "Request Invalid".
Try it's;
public static string HttpPost(string URI, string Parameters)
{
System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
req.ContentType = "application/json; charset=utf-8";
req.Method = "POST";
req.Timeout = 600000;
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters);
req.ContentLength = bytes.Length;
System.IO.Stream os = req.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
System.Net.WebResponse resp = req.GetResponse();
if (resp == null)
return null;
System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream());
return sr.ReadToEnd().Trim();
}
I have just figure it out.
If anybody else has the same problem, here is the answer
string json = JsonConvert.SerializeObject(abc);
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("MyURL"); //==> I am filling it correctly
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var stringContent = new StringContent(JsonConvert.SerializeObject(abc), Encoding.UTF8, "application/json");
var response = client.PostAsync("MyURL", stringContent).Result; //==> I am filling my method correctly

PHP/Curl-SSL operations alternative in C#

I have this piece of code written in PHP, which adds, as i presume, some information about an SSL-certificate to a HTTP-request(It's just a simple http-request, isn't it?). It's added either to body-request or header, that i don't know for sure.
//some code before that
curl_setopt($curl,CURLOPT_SSLCERT,'cert.crt');
curl_setopt($curl,CURLOPT_SSLKEY,'cert.key');
//some code after
//the request itself
$json_response = curl_exec($curl);
The problem is - i don't know how to make this stuff in C#. It'd be easy if i had any knowledge how it's done in curl, like what it exactly does under it's cover.
My current request.
//
var request = CreateHttpRequest(url, method);
var json = param?.ToJson();
if (json != null)
{
var postData = Encoding.UTF8.GetBytes(json);
request.ContentLength = postData.Length;
using (var stream = request.GetRequestStream())
stream.Write(postData, 0, postData.Length);
}
using (var webResponse = request.GetResponse())
using (var streamReader = new StreamReader(webResponse.GetResponseStream(), Encoding.UTF8))
{
var result = streamReader.ReadToEnd();
return result.ParseJson(type);
}
//
private HttpWebRequest CreateHttpRequest(string url, HttpMethod method)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "application/json";
request.Accept = "application/json, application/javascript, text/*";
request.Headers.Add("Accept-Encoding", "gzip,deflate");
request.Method = method.ToString().ToUpper();
return request;
}
In order to use client certificate (loaded from .crt and .key files) in your HTTP-request, add following lines in CreateHttpRequest method before return:
string certificateText = File.ReadAllText("cert.crt");
string privateKeyText = File.ReadAllText("cert.key");
ICertificateProvider provider =
new CertificateFromFileProvider(certificateText, privateKeyText);
request.ClientCertificates.Add(provider.Certificate);
Taken from this answer. To have CertificateFromFileProvider install OpenSSL.X509Certificate2.Provider Nuget package.
Ended up using OpenSSL library.
public X509Certificate2 CreateCertifacte(string pathToCertificate)
{
var keyBytes = File.ReadAllBytes($"{pathToCertificate}/cert.key");
var certBytes = File.ReadAllBytes($"{pathToCertificate}/cert.crt");
var certBio = new BIO(certBytes);
var keyBio = new BIO(keyBytes);
var key = CryptoKey.FromPrivateKey(keyBio, "_");
var cert = new X509Certificate(certBio);
var name = cert.SerialNumber+".pfx";
var stacks = new Stack<X509Certificate>();
new X509Store().AddTrusted(cert);
var certRealPkcs12 = new PKCS12("_", key, cert, stacks);
using (var file = BIO.File(name, "wb"))
{
file.SetClose(BIO.CloseOption.Close); // don't ask me why, i don't know. this one just works.
certRealPkcs12.Write(file);
}
certRealPkcs12.Dispose();
var realCertOut =
new X509Certificate2(File.ReadAllBytes(name), "_");
return realCertOut;
}
Update:
For the netstandard version you can use my fork. Keep in mind that it hasn't been tested all the way through yet (not sure if i ever will), so something wont probably work.

Set a body for WebClient when making a Post Request

So I have an api that I want to call to. The first call is an ahoy call and in the body of the request I need to send the ship_type, piratename and my piratepass. I then want to read the response which has my treasure booty that i will use for later.
I'm able to do this with web request. but i feel like there is a better way to do it with webclient.
(way I currently do it in webrequest)
//Credentials for the Pirate api
string piratename = "IvanTheTerrible";
string piratepass= "YARRRRRRRR";
string URI = "https://www.PiratesSuperSecretHQ.com/sandyShores/api/respectmyauthority";
WebRequest wr = WebRequest.Create(URI);
wr.Method = "POST";
wr.ContentType = "application/x-www-form-urlencoded";
string bodyData = "ship_type=BattleCruiser&piratename=" + piratename + "&piratepass=" + piratepass;
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] byte1 = encoder.GetBytes(bodyData);
wr.ContentLength = byte1.Length;
//writes the body to the request
Stream newStream = wr.GetRequestStream();
newStream.Write(byte1, 0, byte1.Length);
newStream.Close();
WebResponse wrep = wr.GetResponse();
string result;
using (var reader = new StreamReader(wrep.GetResponseStream()))
{
result = reader.ReadToEnd(); // do something fun...
}
Thanks in advance either way.
You can do with this simple code
Uri uri = new Uri("yourUri");
string data = "yourData";
WebClient client = new WebClient();
var result = client.UploadString(uri, data);
Remember that you can use UploadStringTaskAsync if you want to be async
You can try like below as well:
public String wcPost(){
Map<String, String> bodyMap = new HashMap();
bodyMap.put("key1","value1");
WebClient client = WebClient.builder()
.baseUrl("domainURL")
.build();
String responseSpec = client.post()
.uri("URI")
.headers(h -> h.setBearerAuth("token if any"))
.body(BodyInserters.fromValue(bodyMap))
.exchange()
.flatMap(clientResponse -> {
if (clientResponse.statusCode().is5xxServerError()) {
clientResponse.body((clientHttpResponse, context) -> {
return clientHttpResponse.getBody();
});
return clientResponse.bodyToMono(String.class);
}
else
return clientResponse.bodyToMono(String.class);
})
.block();
return responseSpec;
}

How to create HTTP post request

Hello I'm new at programing so my question might be a little bit odd. My boss ask me to create a HTTP post request using a key and a message to access our client.
I already seen the article Handle HTTP request in C# Console application but it doesn't include where I put the key and message so the client API knows its me. Appreciate the help in advance.
I believe you wanted this:
HttpWebRequest httpWReq =
(HttpWebRequest)WebRequest.Create("http://domain.com/page.aspx");
ASCIIEncoding encoding = new ASCIIEncoding();
string postData = "username=user";
postData += "&password=pass";
byte[] data = encoding.GetBytes(postData);
httpWReq.Method = "POST";
httpWReq.ContentType = "application/x-www-form-urlencoded";
httpWReq.ContentLength = data.Length;
using (Stream stream = httpWReq.GetRequestStream())
{
stream.Write(data,0,data.Length);
}
HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
You could use a WebClient:
using (var client = new WebClient())
{
// Append some custom header
client.Headers[HttpRequestHeader.Authorization] = "Bearer some_key";
string message = "some message to send";
byte[] data = Encoding.UTF8.GetBytes(message);
byte[] result = client.UploadData(data);
}
Of course depending on how the API expects the data to be sent and which headers it requires you will have to adapt this code to match the requirements.

Sending a string to a PHP page and having the PHP Page Display The String

What I'm trying to do is have my PHP page display a string that I've created through a function in my C# application, via System.Net.WebClient.
That's really it. In it' s simplest form, I have:
WebClient client = new WebClient();
string URL = "http://wwww.blah.com/page.php";
string TestData = "wooooo! test!!";
byte[] SendData = client.UploadString(URL, "POST", TestData);
So, I'm not even sure if that's the right way to do it.. and I'm not sure how to actually OBTAIN that string and display it on the PHP page. something like print_r(SendData) ??
ANY help would be greatly appreciated!
There are two halves to posting. 1) The code that posts to a page and 2) the page that receives it.
For 1)
Your C# looks ok. I personally would use:
string url = "http://wwww.blah.com/page.php";
string data = "wooooo! test!!";
using(WebClient client = new WebClient()) {
client.UploadString(url, data);
}
For 2)
In your PHP page:
if ( $_SERVER['REQUEST_METHOD'] === 'POST' )
{
$postData = file_get_contents('php://input');
print $postData;
}
Read about reading post data in PHP here:
http://us.php.net/manual/en/wrappers.php.php
http://php.net/manual/en/reserved.variables.httprawpostdata.php
Use This Codes To Send String From C# With Post Method
try
{
string url = "";
string str = "test";
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "POST";
string Data = "message="+str;
byte[] postBytes = Encoding.ASCII.GetBytes(Data);
req.ContentType = "application/x-www-form-urlencoded";
req.ContentLength = postBytes.Length;
Stream requestStream = req.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Close();
HttpWebResponse response = (HttpWebResponse)req.GetResponse();
Stream resStream = response.GetResponseStream();
var sr = new StreamReader(response.GetResponseStream());
string responseText = sr.ReadToEnd();
}
catch (WebException)
{
MessageBox.Show("Please Check Your Internet Connection");
}
and php page
<?php
if (isset($_POST['message']))
{
$msg = $_POST['message'];
echo $msg;
}
?>

Categories