Đăng dữ liệu biểu mẫu bằng HttpWebRequest


90

Tôi muốn đăng một số dữ liệu biểu mẫu lên một URL được chỉ định không nằm trong ứng dụng web của riêng tôi. Nó có cùng một miền, chẳng hạn như "domain.client.nl". Ứng dụng web có url "web.domain.client.nl" trong khi url mà tôi muốn đăng là "idp.domain.client.nl". Nhưng mã của tôi không làm gì cả ..... có ai đó biết tôi đang làm gì sai không?

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();


6
Không hoàn toàn trùng lặp, vì người khác muốn sử dụng cụ thể WebClient.

Câu trả lời:


71

Cả tên trường và giá trị phải được mã hóa url. định dạng của dữ liệu bài đăng và chuỗi truy vấn giống nhau

Cách làm .net là một cái gì đó như thế này

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

Điều này sẽ giải quyết việc mã hóa các trường và tên giá trị


10
string postdata = outgoingQueryString.ToString();sẽ cung cấp cho bạn một chuỗi với giá trị "System.Collections.Specialized.NameValueCollection".
sfuqua

1
Trên thực tế @sfuqua nếu bạn dịch ngược mã nguồn cho HttpUtility (cụ thể là mã trong System.Web), bạn sẽ thấy rằng nó trả về kiểu NameValueCollection chuyên biệt: return (NameValueCollection) new HttpValueCollection (truy vấn, sai, đúng, mã hóa); chuyển đổi chính xác bộ sưu tập thành một chuỗi truy vấn. Tuy nhiên, nếu bạn sử dụng cái từ RestSharp thì không ...
The Senator

Thật thú vị, như tôi đã thấy vấn đề chính xác này ToString(), mặc dù bây giờ tôi không thể nhớ liệu nó có xảy ra khi sử dụng RestSharp hay không. Khả năng xác định. Cảm ơn vì sự đúng đắn của bạn.
sfuqua

Không rõ ngay lập tức outgoingQueryStringnó hoạt động như thế nào như được ngụ ý bởi mã ví dụ. Hai câu hỏi này trả lời rằng - (1) HttpValueCollection và NameValueCollection và (2) Bất kỳ lớp .NET nào tạo chuỗi truy vấn đã cho các cặp giá trị khóa hoặc tương tự .
Kenny Evitt,

56

Thử cái này:

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();

6
Tôi muốn viết: request.Method = WebRequestMethods.Http.Post;
Totalys

kiểm tra request.HaveResponse trước phản ứng sử dụng
Marco Fantasia

@MarcoFantasia Nếu bạn kiểm tra, request.HaveResponsebạn phải thực sự nhận được phản hồi trước. HttpWebResponse response = (HttpWebResponse) request.GetResponse(); if (request.HaveResponse) { ... }
Có Barry

40

Bạn đang mã hóa biểu mẫu không chính xác. Bạn chỉ nên mã hóa các giá trị:

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));

biên tập

Tôi đã sai. Theo RFC1866 phần 8.2.1 cả tên và giá trị phải được mã hóa.

Nhưng đối với ví dụ đã cho, tên không có bất kỳ ký tự nào cần được mã hóa, vì vậy trong trường hợp này, ví dụ mã của tôi là đúng;)

Mã trong câu hỏi vẫn không chính xác vì nó sẽ mã hóa dấu bằng, đó là lý do tại sao máy chủ web không thể giải mã nó.

Một cách thích hợp hơn sẽ là:

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));
}

Cảm ơn, nhưng tôi đang gặp lỗi sau: Máy chủ từ xa trả lại lỗi: (412) Điều kiện tiên quyết không thành công.
wsplinter

Tôi google rất nhiều :) Nhưng tôi đã sửa nó, tôi đang làm nó một cách bẩn thỉu. Tôi không phải là HttpWebRequest nhưng tôi xây dựng một biểu mẫu html bên trong một Chuỗi và cài đặt nó vào trình duyệt (trong phần tải lên, tôi sẽ gửi).
wsplinter

3
@wsplinter: Sẽ giúp ích cho những người khác nếu bạn ghi lại giải pháp cho điều kiện tiên quyết không thành công.
jgauffin

@jgauffin: Làm cách nào để đăng các giá trị của nút radio? Giả sử tôi có 3 nút radio thuộc cùng một nhóm.
Asad Refai

1
Rõ ràng, điều này không hoạt động đối với tôi hoàn toàn như mong đợi vì UrlEncode thay đổi các ký hiệu như @ thành mã không được chấp nhận trong lệnh gọi API; thay đổi nó để sử dụng NameValueCollection như showin trong câu trả lời của @ user3389691 hoạt động hoàn hảo.
dhruvpatel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.