Опублікувати дані форми за допомогою 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.