Опублікувати дані форми за допомогою HttpWebRequest


91

Я хочу опублікувати деякі дані форми за вказаною URL-адресою, яка не знаходиться у моїй власній веб-програмі. Він має той самий домен, такий як "domain.client.nl". Веб-додаток має URL-адресу "web.domain.client.nl", а URL-адреса, на яку я хочу розмістити повідомлення, - "idp.domain.client.nl". Але мій код нічого не робить ..... хтось знає, що я роблю не так?

Вутер

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

Можливий дублікат: stackoverflow.com/questions/5401501/…
— Dariusz

6
Не зовсім дублікат, як інший спеціально хоче використовувати WebClient.

Відповіді:


72

І назва поля, і значення повинні бути закодовані за URL-адресою. Формат даних повідомлення та рядка запиту однакові

Спосіб ведення .net приблизно такий

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

Це подбає про кодування полів та назв значень


10
string postdata = outgoingQueryString.ToString();дасть вам рядок зі значенням "System.Collections.Specialized.NameValueCollection".
— sfuqua

1
Насправді @sfuqua, якщо ви декомпілюєте джерело для HttpUtility (зокрема, те, що в System.Web), ви побачите, що воно повертає спеціалізований тип NameValueCollection: return (NameValueCollection) new HttpValueCollection (запит, хибне, істинне, кодування); який правильно перетворює колекцію у рядок запиту. Якщо ви використовуєте той із RestSharp, однак, це не робить ...
— Сенатор,

Цікаво, оскільки я бачив саме цю проблему ToString(), хоча зараз не можу згадати, чи це було під час використання RestSharp. Певна можливість. Дякую за виправлення.
— sfuqua

Не одразу було зрозуміло, як outgoingQueryStringпрацює, як передбачається в прикладі коду. Ці два запитання відповідають на: (1) HttpValueCollection та NameValueCollection та (2) Будь-який .NET-клас, який робить рядок запиту із заданими парами значень ключа тощо .
— Кенні Евітт,

57

Спробуйте це:

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
Я б скоріше написав: request.Method = WebRequestMethods.Http.Post;
— Totalys

Запит на перевірку. Майте відповідь перед відповіддю на використання
— Марко Фантазія

@MarcoFantasia Якщо ви позначите цей пункт, спочатку request.HaveResponseвам слід отримати відповідь. HttpWebResponse response = (HttpWebResponse) request.GetResponse(); if (request.HaveResponse) { ... }
— Так Баррі

41

Ви неправильно кодуєте форму. Слід кодувати лише значення:

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

редагувати

Я помилився. Відповідно до розділу 8.2.1 RFC1866 кодуються як імена, так і значення.

Але в наведеному прикладі імена не мають символів, які потрібно кодувати, тому в цьому випадку мій приклад коду правильний;)

Код у питанні все ще неправильний, оскільки він би кодував знак рівності, що є причиною того, чому веб-сервер не може його декодувати.

Більш правильним способом було б:

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

Дякую, але зараз я отримую таку помилку: Віддалений сервер повернув помилку: (412) Помилка передумови.
— wsplinter

Я багато гуглю :) Але я це виправив, роблю це брудно. Я не HttpWebRequest, але я будую HTML-форму всередині рядка і передаю її в браузер (під час завантаження я буду робити подання).
— wsplinter

3
@wsplinter: Це допомогло б іншим, якщо ви задокументували, що рішення попередньої умови не вдалося.
— jgauffin 02

@jgauffin: Як опублікувати значення перемикачів? Припустимо, у мене є 3 перемикачі, що належать до однієї групи.
— Асад Рефай,

1
Очевидно, це не спрацювало для мене зовсім так, як очікувалось, оскільки UrlEncode змінює символи типу @ на код, який не приймався в виклику API; змінивши його на використання NameValueCollection як showin у відповіді @ user3389691 працює ідеально.
— dhruvpatel
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.