HttpWebRequestを使用してフォームデータを投稿する


91

自分のWebアプリケーション内にない指定のURLにフォームデータを投稿したい。「domain.client.nl」などの同じドメインがあります。WebアプリケーションのURLは「web.domain.client.nl」で、投稿先のURLは「idp.domain.client.nl」です。しかし、私のコードは何もしません.....誰かが私が間違っていることを知っていますか?

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
他のユーザーが特に使用したいので、完全に重複しているわけではありませんWebClient

回答:


71

フィールド名と値の両方を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 2016年

1
実際に@sfuquaは、HttpUtility(特にSystem.Webのソース)のソースを逆コンパイルすると、特殊なNameValueCollectionタイプを返すことがわかります。return(NameValueCollection)new HttpValueCollection(query、false、true、encoding); コレクションをクエリ文字列に正しく変換します。ただし、RestSharpからのものを使用する場合、それは使用できません...
セネター、

興味深いのは、この正確な問題をToString()で見たのと同じですが、RestSharpを使用していたのかどうかは思い出せません。確かな可能性。訂正ありがとうございます。
sfuqua 2016

outgoingQueryString例のコードで示されているように、どのように機能していたかはすぐにはわかりませんでした。これらの2つの質問は、(1)HttpValueCollectionとNameValueCollection、(2)キー値のペアなどを指定してクエリ文字列を作成するすべての.NETクラスに答えます
ケニーエビット2016年

56

これを試して:

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 2017

リクエストを確認してください。使用前にHaveResponse応答
Marco Fantasia

@MarcoFantasiaチェックrequest.HaveResponseすると、最初に実際応答を取得する必要があります。 HttpWebResponse response = (HttpWebResponse) request.GetResponse(); if (request.HaveResponse) { ... }
はいバリー

40

フォームを正しくエンコードしていません。値のみをエンコードする必要があります。

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

編集する

私は間違っていました。RFC1866セクション8.2.1によると、名前と値の両方をエンコードする必要があります。

しかし、与えられた例では、名前にはエンコードする必要のある文字が含まれていないため、この場合、私のコード例は正しいです;)

質問のコードは等号をエンコードするため、依然として正しくありません。これは、Webサーバーが等号をデコードできない理由です。

より適切な方法は次のとおりです。

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 2013

私はたくさんグーグルします:)しかし、私はそれを修正しました、私は汚れた方法でそれをしています。私はHttpWebRequestを行いませんが、String内にhtmlフォームを作成し、それをブラウザーに書き込みます(onloadで送信を行います)。
wsplinter 2013

3
@wsplinter:前提条件の解決策が失敗したことを文書化すると、他の人の役に立ちます。
jgauffin 14

@jgauffin:ラジオボタンの値を投稿するにはどうすればよいですか?同じグループに属する3つのラジオボタンがあるとします。
Asad Refai 2015

1
どうやら、UrlEncodeが@などの記号をAPI呼び出しで受け入れられなかったコードに変更するため、これは期待どおりには機能しませんでした。@ user3389691の回答のshowinのようにNameValueCollectionを使用するように変更すると、完璧に機能します。
dhruvpatel 2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.