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

UrlEncode non-string properties for HTTP Post through HttpClient

此代码在 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();   

但我的问题是 posting 内容,因为 post 数据需要同时是 int 和 string.But 我只能使用 [=20 以字符串格式发送数据=] 如何使用正确的参数发送 post 请求。

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

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

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

所以你原来的id参数是字符串"2"还是数字2都没有关系。

它将被编码为相同的:name=mynameValue&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
    });       

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

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

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