Data formulir posting menggunakan HttpWebRequest

91

Saya ingin memposting beberapa data formulir ke URL tertentu yang tidak ada di dalam aplikasi web saya sendiri. Ini memiliki domain yang sama, seperti "domain.client.nl". Aplikasi web memiliki url "web.domain.client.nl" dan url yang ingin saya kirimi adalah "idp.domain.client.nl". Tapi kode saya tidak melakukan apa-apa ..... apakah seseorang tahu apa yang saya lakukan salah?

Wouter

StringBuilder postData = new StringBuilder();
postData.Append(HttpUtility.UrlEncode(String.Format("username={0}&", uname)));
postData.Append(HttpUtility.UrlEncode(String.Format("password={0}&", pword)));
postData.Append(HttpUtility.UrlEncode(String.Format("url_success={0}&", urlSuccess)));
postData.Append(HttpUtility.UrlEncode(String.Format("url_failed={0}", urlFailed)));

ASCIIEncoding ascii = new ASCIIEncoding();
byte[] postBytes = ascii.GetBytes(postData.ToString());

// set up request object
HttpWebRequest request;
try
{
    request = (HttpWebRequest)HttpWebRequest.Create(WebSiteConstants.UrlIdp);
}
catch (UriFormatException)
{
    request = null;
}
if (request == null)
    throw new ApplicationException("Invalid URL: " + WebSiteConstants.UrlIdp);

request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = postBytes.Length;
request.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)";

// add post data to request
Stream postStream = request.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
postStream.Flush();
postStream.Close();
wsplinter.dll
sumber
Kemungkinan duplikat: stackoverflow.com/questions/5401501/…
Dariusz
6
Bukan duplikat, karena yang lain secara khusus ingin digunakan WebClient.

Jawaban:

72

Nama bidang dan nilainya harus dienkode url. format data posting dan string kueri sama

Cara .net melakukannya adalah seperti ini

NameValueCollection outgoingQueryString = HttpUtility.ParseQueryString(String.Empty);
outgoingQueryString.Add("field1","value1");
outgoingQueryString.Add("field2", "value2");
string postdata = outgoingQueryString.ToString();

Ini akan menangani pengkodean bidang dan nama nilai

pengguna3389691
sumber
10
string postdata = outgoingQueryString.ToString();akan memberi Anda string dengan nilai "System.Collections.Specialized.NameValueCollection".
sfuqua
1
Sebenarnya @sfuqua jika Anda mendekompilasi sumber untuk HttpUtility (khususnya yang ada di System.Web) Anda akan melihat bahwa ia mengembalikan jenis NameValueCollection khusus: return (NameValueCollection) new HttpValueCollection (query, false, true, encoding); yang dengan benar mengonversi koleksi menjadi string kueri. Namun, jika Anda menggunakan yang dari RestSharp, itu tidak ...
Senator
Menarik, karena saya telah melihat masalah yang sebenarnya dengan ini ToString(), meskipun sekarang saya tidak dapat mengingat apakah itu saat menggunakan RestSharp. Kemungkinan yang pasti. Terima kasih atas koreksinya.
sfuqua
Tidak segera jelas bagaimana cara outgoingQueryStringkerjanya seperti yang tersirat oleh kode contoh. Kedua pertanyaan ini menjawab bahwa - (1) HttpValueCollection dan NameValueCollection dan (2) Setiap kelas .NET yang membuat string kueri diberi pasangan nilai kunci atau sejenisnya .
Kenny Evitt
57

Coba ini:

var request = (HttpWebRequest)WebRequest.Create("http://www.example.com/recepticle.aspx");

var postData = "thing1=hello";
    postData += "&thing2=world";
var data = Encoding.ASCII.GetBytes(postData);

request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;

using (var stream = request.GetRequestStream())
{
    stream.Write(data, 0, data.Length);
}

var response = (HttpWebResponse)request.GetResponse();

var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
Parisa Shamsaie
sumber
6
Saya lebih suka menulis: request.Method = WebRequestMethods.Http.Post;
Totalys
periksa request.HaveResponse before use response
Marco Fantasia
@MarcoFantasia Jika Anda memeriksa, request.HaveResponseAnda harus benar-benar mendapatkan tanggapan terlebih dahulu. HttpWebResponse response = (HttpWebResponse) request.GetResponse(); if (request.HaveResponse) { ... }
Ya Barry
41

Anda salah mengkodekan formulir. Anda hanya boleh mengenkode nilai:

StringBuilder postData = new StringBuilder();
postData.Append("username=" + HttpUtility.UrlEncode(uname) + "&");
postData.Append("password=" + HttpUtility.UrlEncode(pword) + "&");
postData.Append("url_success=" + HttpUtility.UrlEncode(urlSuccess) + "&");
postData.Append("url_failed=" + HttpUtility.UrlEncode(urlFailed));

edit

Saya salah Menurut RFC1866 bagian 8.2.1 nama dan nilai harus dikodekan.

Tetapi untuk contoh yang diberikan, nama tidak memiliki karakter yang perlu dikodekan, jadi dalam hal ini contoh kode saya benar;)

Kode dalam pertanyaan masih salah karena akan menyandikan tanda sama dengan yang merupakan alasan mengapa server web tidak dapat mendekodekannya.

Cara yang lebih tepat adalah:

StringBuilder postData = new StringBuilder();
postData.AppendUrlEncoded("username", uname);
postData.AppendUrlEncoded("password", pword);
postData.AppendUrlEncoded("url_success", urlSuccess);
postData.AppendUrlEncoded("url_failed", urlFailed);

//in an extension class
public static void AppendUrlEncoded(this StringBuilder sb, string name, string value)
{
    if (sb.Length != 0)
        sb.Append("&");
    sb.Append(HttpUtility.UrlEncode(name));
    sb.Append("=");
    sb.Append(HttpUtility.UrlEncode(value));
}
jgauffin.dll
sumber
Terima kasih, tapi sekarang saya mendapatkan kesalahan berikut: Server jarak jauh mengembalikan kesalahan: (412) Prekondisi Gagal.
wsplinter
Saya banyak google :) Tapi saya memperbaikinya, saya melakukannya dengan cara yang kotor. Saya bukan HttpWebRequest tetapi saya membuat formulir html di dalam String dan menghubungkannya ke browser (dalam onload saya akan melakukan pengiriman).
wsplinter
3
@wsplinter: Ini akan membantu orang lain jika Anda mendokumentasikan solusi untuk prasyarat gagal.
jgauffin
@jgauffin: Bagaimana cara mengirim nilai tombol radio? Asumsikan saya memiliki 3 tombol radio milik grup yang sama.
Asad Refai
1
Rupanya, ini tidak bekerja untuk saya seperti yang diharapkan karena UrlEncode mengubah simbol seperti @ menjadi kode yang tidak diterima dalam panggilan API; mengubahnya menjadi menggunakan NameValueCollection sebagai showin di jawaban @ user3389691 berfungsi sempurna.
dhruvpatel