使用HttpWebRequest发布表单数据


91

我想将一些表单数据发布到不在我自己的Web应用程序内的指定URL中。它具有相同的域,例如“ domain.client.nl”。该Web应用程序有一个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();


6
并非完全重复,因为另一个特别想使用WebClient

Answers:


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 '16

1
实际上,如果您对HttpUtility的源(特别是System.Web中的源)进行反编译,则@sfuqua会看到它返回一种特殊的NameValueCollection类型:return(NameValueCollection)new HttpValueCollection(query,false,true,encoding); 可以将集合正确转换为查询字符串。但是,如果您使用RestSharp的那个,它就不会...
The Senator

有趣的是,正如我已经看到的确切问题一样ToString(),尽管我现在不记得是否在使用RestSharp时。绝对的可能性。感谢您的更正。
sfuqua '16

目前尚不清楚outgoingQueryString示例代码所隐含的工作方式。这两个问题回答-(1)HttpValueCollection和NameValueCollection,以及(2)给定键值对等的查询字符串的任何.NET类
肯尼·埃维特

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'2

检查request.HaveResponse使用前响应
Marco Fantasia

@MarcoFantasia如果您进行检查request.HaveResponse,则必须首先实际获得响应。 HttpWebResponse response = (HttpWebResponse) request.GetResponse(); if (request.HaveResponse) { ... }
是Barry

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

我在Google上搜索了很多:)但是我已经解决了,我用一种肮脏的方式来做。我不是HttpWebRequest,但是我在String内构建了一个html表单,并将其写入浏览器(在onload中,我将进行提交)。
wsplinter

3
@wsplinter:如果您记录了前置失败的解决方案,它将对其他人有帮助。
jgauffin

@jgauffin:如何发布单选按钮值?假设我有3个属于同一组的单选按钮。
2015年

1
显然,这对我来说并没有达到预期的效果,因为UrlEncode将符号@等更改为API调用中未接受的代码。将其更改为使用NameValueCollection作为@ user3389691答案中的showin可以完美地工作。
dhruvpatel '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.