C#中的HttpWebRequest类型为"application/x-www-form-urlencoded" - 如何在内容主体中发送"&"符号?

50

我正在使用C#编写一个小型API连接的应用程序。

我连接到一个具有接受长字符串(即ics文件的内容)的方法的API。

我这样做:

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);
request.Method = "POST";
request.AllowAutoRedirect = false;
request.CookieContainer = my_cookie_container;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.ContentType = "application/x-www-form-urlencoded";

string iCalStr = GetCalendarAsString();

string strNew = "&uploadfile=true&file=" + iCalStr;

using (StreamWriter stOut = new StreamWriter(request.GetRequestStream(), System.Text.Encoding.ASCII))
 {
     stOut.Write(strNew);
     stOut.Close();
 }

这看起来很好,但当我在我的日历中添加一些特定的HTML时就出现了问题。

如果我的日历中有一个"&nbsp"(或类似的),那么服务器只会获取到"&"之前的所有数据,所以我认为"&"会让它看起来像是任何在此点之后的内容都属于一个新参数?

我该如何解决这个问题?


发送前对字符串进行编码吗? - santosh singh
3个回答

59

首先安装"Microsoft ASP.NET Web API Client" NuGet包:

  PM > Install-Package Microsoft.AspNet.WebApi.Client

然后使用以下函数来发布您的数据:

public static async Task<TResult> PostFormUrlEncoded<TResult>(string url, IEnumerable<KeyValuePair<string, string>> postData)
{
    using (var httpClient = new HttpClient())
    {
        using (var content = new FormUrlEncodedContent(postData))
        {
            content.Headers.Clear();
            content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

            HttpResponseMessage response = await httpClient.PostAsync(url, content);

            return await response.Content.ReadAsAsync<TResult>();
        }
    }
}

这是如何使用它的方法:

TokenResponse tokenResponse = 
    await PostFormUrlEncoded<TokenResponse>(OAuth2Url, OAuth2PostData);
或者
TokenResponse tokenResponse = 
    (Task.Run(async () 
        => await PostFormUrlEncoded<TokenResponse>(OAuth2Url, OAuth2PostData)))
        .Result

或(不建议)

TokenResponse tokenResponse = 
    PostFormUrlEncoded<TokenResponse>(OAuth2Url, OAuth2PostData).Result;

不确定我是否遗漏了什么,但是这种方式会导致请求挂起。 - deanwilliammills
OAuth2PostData 是什么? - Kiquenet
@Kiquenet - 当您使用Content-Typeapplication/x-www-form-urlencoded的请求时,通常需要一些数据。我从编写OAuth2身份验证的代码中复制了示例代码,因此变量名为OAuth2PostData。名称并不重要,它只是一个保存数据的变量。它基本上是一个KeyValuePair<string, string>的列表。 - Tohid
抱歉,如何使用 TokenResponse 类?需要添加 using Microsoft.Bot.Schema; 吗? - Pham X. Bach
1
@PhamX.Bach - TokenResponse 是你的模型。定义一个类,与你调用的 Web API 的返回模式匹配。它是一个简单的 POCO。 - Tohid

32

由于您的内容类型为application/x-www-form-urlencoded,如果POST正文中包含像&这样在表单中具有特殊意义的字符,您需要对其进行编码。

尝试将字符串通过HttpUtility.UrlEncode进行编码,然后再写入请求流。

以下是一些参考链接。


第二个链接指向一些日本网站! - Badhon Jain
谢谢!对我来说,我只需要在使用.ContentType = "application/x-www-form-urlencoded"进行发布之前将我的字符串strCallString = System.Web.HttpUtility.UrlEncode(strCallString)进行转换。 - Erik Schroder

10
只要服务器允许ampresand字符被POST(并非所有服务器都允许,因为它可能不安全),您只需要对该字符进行URL编码。对于ampresand,您应该使用%26替换该字符。
.NET提供了一种很好的方式来为您编码整个字符串:
string strNew = "&uploadfile=true&file=" + HttpUtility.UrlEncode(iCalStr);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接