通过 HttpClient 的 HTTP Post 的 UrlEncode 非字符串属性

Posted

技术标签:

【中文标题】通过 HttpClient 的 HTTP Post 的 UrlEncode 非字符串属性【英文标题】:UrlEncode non-string properties for HTTP Post through HttpClient 【发布时间】:2017-01-12 18:18:57 【问题描述】:

这段代码在python中

dataParams = urllib.urlencode(
    "name": "myname",      
    "id": 2,        
    )

    dataReq = urllib2.Request('mylink', dataParams)
    dataRes = urllib2.urlopen(dataReq)

现在我正在尝试将其转换为 C#。直到现在我只能这样做

 var dataParams = new FormUrlEncodedContent(
             new KeyValuePair<string, string>[]
             
                 new KeyValuePair<string, string>("name", myname"),                     
                 new KeyValuePair<string, string>("id", "2"),
             );

  httpResponse = await httpClient.PostAsync(new Uri(dataString),dataParams);
  httpResponseBody = await httpResponse.Content.ReadAsStringAsync();   

但我的问题是发布内容,因为发布数据需要同时是 int 和字符串。但我只能使用 FormUrlEncodedContent 以字符串格式发送数据。那么如何发送带有适当参数的发布请求。

【问题讨论】:

【参考方案1】:

我不确定post data needs to be both int and string 是什么意思,因为application/x-www-form-urlencoded 基本上是一个带有字符串键值对的字符串。

因此,您的原始id 参数是字符串"2" 还是数字2 都没有关系。

它将被编码为相同的:name=mynameValue&amp;id=2

所以您的代码没有任何问题。只需对原始 int 值使用 ToString 方法即可获取其字符串表示形式:

var id = 2;
var dataParams = new FormUrlEncodedContent(
     new KeyValuePair<string, string>[]
     
         new KeyValuePair<string, string>("name", myname"),                     
         new KeyValuePair<string, string>("id", id.ToString()),
     );

你可以用更少的样板来对复杂类型进行 urlencode,它甚至看起来更像原始的 python 代码:

public static class HttpUrlEncode

    public static FormUrlEncodedContent Encode(Object obj)
    
        if (obj == null)
            throw new ArgumentNullException("obj");

        var props = obj
            .GetType()
            .GetProperties(BindingFlags.Instance | BindingFlags.Public)
            .ToDictionary(
                prop => 
                    prop.Name,
                prop => 
                    (prop.GetValue(obj, null) ?? String.Empty).ToString());

        return new FormUrlEncodedContent(props);
    



var dataParams = HttpUrlEncode.Encode(
    new 
    
        name = "myname",
        id = 2
    );       

【讨论】:

第二种方法到底如何不起作用?我已经用简单的[HttpPost] public ActionResult TestPost( String name, Int32 id) 进行了尝试,并且该操作接收到正确的数据。 不,我的意思是说我尝试了第一个并且它有效,所以我没有尝试第二个。 :)【参考方案2】:

如果您不介意小型库依赖项,Flurl [披露:我是作者] 会像您的 Python 示例一样简短明了,也许更是如此:

var dataParams = new 
    name: "myname",
    id: 2
;

var result = await "http://api.com".PostUrlEncodedAsync(dataParams).ReceiveString();

【讨论】:

感谢您的回答,目前它对我有用,下次我一定会尝试您的图书馆。【参考方案3】:

如果您的数据将包含数字和字符串值,您可以使用KeyValuePair&lt;string,object&gt;,它应该接受您的任何数据。所以你的代码可能是:

var contentString = JsonConvert.SerializeObject(
         new KeyValuePair<string, object>[]
         
             new KeyValuePair<string, object>("name", "myname"),                     
             new KeyValuePair<string, object>("id", 2),
         );
var requestMessage = new HttpRequestMessage(HttpMethod.Post, "URI") 
    Content = new StringContent(contentString)
;
httpResponse = await httpClient.SendAsync(requestMessage);

【讨论】:

我在FormUrlEncodedContent 上没有看到任何接受IEnumerable&lt;string, object&gt; 的constructors。并且单个现有构造函数 (msdn.microsoft.com/en-us/library/…) 不会接受这样的参数。 @EugenePodskal 你说得对,我想它必须是JsonConvert.SerializeObject,我会相应地进行编辑。 不,他需要标准的application/x-www-form-urlencoded 编码。 这个答案不正确。 OP 询问是否发布 URL 编码的内容,而不是 JSON 内容。

以上是关于通过 HttpClient 的 HTTP Post 的 UrlEncode 非字符串属性的主要内容,如果未能解决你的问题,请参考以下文章

如何通过python twisted HTTPClient生成POST和GET请求?

如何通过 HttpClient 在 POST 请求中将 JSON 数据作为正文发送

HttpClient通过Post方式发送Json数据

如何通过HttpClient去POST一个multipart/form-data数据

HttpClient使用示列(post请求的)

httpclient post