如何在Windows Phone 8中使用HttpClient发送Post请求体?

125

我已经编写了下面的代码来发送头信息和Post参数。问题是我使用SendAsync,因为我的请求可以是GET或POST。如何将POST Body添加到此代码片段中,以便如果有任何POST Body数据,则将其添加到我发出的请求中,如果没有Body则按照普通的GET或POST方式发送请求。请更新下面的代码:

HttpClient client = new HttpClient();

// Add a new Request Message
HttpRequestMessage requestMessage = new HttpRequestMessage(RequestHTTPMethod, ToString());

// Add our custom headers
if (RequestHeader != null)
{
    foreach (var item in RequestHeader)
    {

        requestMessage.Headers.Add(item.Key, item.Value);

    }
}

// Add request body


// Send the request to the server
HttpResponseMessage response = await client.SendAsync(requestMessage);

// Get the response
responseString = await response.Content.ReadAsStringAsync();

请查看更新后的答案,它采用了更好的方法。 - Ilya Luzyanin
3个回答

223

更新2:

来自@Craig Brown的消息:

从.NET 5开始,您可以执行以下操作:
requestMessage.Content = JsonContent.Create(new { Name = "John Doe", Age = 33 });

请参阅JsonContent类文档。

更新1:

哦,这甚至可以更好(来自这个答案):

requestMessage.Content = new StringContent("{\"name\":\"John Doe\",\"age\":33}", Encoding.UTF8, "application/json");

这取决于您拥有的内容。您需要使用新的HttpContent初始化您的requestMessage.Content属性。例如:

...
// Add request body
if (isPostRequest)
{
    requestMessage.Content = new ByteArrayContent(content);
}
...

其中content是您的编码内容。您还应该包含正确的Content-type标头。


1
如何使用JsonSerializer将Json写入内容中? - GiriB
27
@GiriB,我使用Newtonsoft.Json包来实现,代码如下:requestMessage.Content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");你也可以使用JsonSerializer将其序列化为字符串,然后将该字符串作为StringContent构造函数的第一个参数传递。 - Matt Shepherd
3
从.NET 5开始,您可以执行以下操作: requestMessage.Content = JsonContent.Create(new {Name = "John Doe", Age = 33}); - Craig Brown

17
我以下面的方式实现了它。我想要一个通用的MakeRequest方法,能够调用我的API并接收请求主体的内容,并将响应反序列化为所需的类型。我创建了一个Dictionary<string, string>对象,用来存储要提交的内容,然后将HttpRequestMessageContent属性设置为它: 调用API的通用方法:
    private static T MakeRequest<T>(string httpMethod, string route, Dictionary<string, string> postParams = null)
    {
        using (var client = new HttpClient())
        {
            HttpRequestMessage requestMessage = new HttpRequestMessage(new HttpMethod(httpMethod), $"{_apiBaseUri}/{route}");

            if (postParams != null)
                requestMessage.Content = new FormUrlEncodedContent(postParams);   // This is where your content gets added to the request body


            HttpResponseMessage response = client.SendAsync(requestMessage).Result;

            string apiResponse = response.Content.ReadAsStringAsync().Result;
            try
            {
                // Attempt to deserialise the reponse to the desired type, otherwise throw an expetion with the response from the api.
                if (apiResponse != "")
                    return JsonConvert.DeserializeObject<T>(apiResponse);
                else
                    throw new Exception();
            }
            catch (Exception ex)
            {
                throw new Exception($"An error ocurred while calling the API. It responded with the following message: {response.StatusCode} {response.ReasonPhrase}");
            }
        }
    }

调用该方法:

    public static CardInformation ValidateCard(string cardNumber, string country = "CAN")
    { 
        // Here you create your parameters to be added to the request content
        var postParams = new Dictionary<string, string> { { "cardNumber", cardNumber }, { "country", country } };
        // make a POST request to the "cards" endpoint and pass in the parameters
        return MakeRequest<CardInformation>("POST", "cards", postParams);
    }

5
这个实现有几个问题。首先,它不是异步的。使用“.Result”会导致这是一个阻塞调用。第二个问题是它不能够扩展!请看我在这里的答案——https://dev59.com/xGEh5IYBdhLWcg3wTB_2#35045301。第三个问题是你正在抛出异常来处理控制流。这不是一个好的做法。请参见 - https://learn.microsoft.com/en-us/visualstudio/profiling/da0007-avoid-using-exceptions-for-control-flow?view=vs-2019. - Dave Black
谢谢您的输入。我会检查那些链接。 - Adam Hey
@AdamHey,这对于同步请求很不错,谢谢! - Syed Rafay
1
另外,你有一个内存泄漏问题。HttpRequestMessage 实现了 IDisposable 接口,因此你需要将其包装在 using 语句中。 - Jeremy Thompson

0

我创建了一个方法:

public static StringContent GetBodyJson(params (string key, string value)[] param)
    {
        if (param.Length == 0)
            return null;

        StringBuilder builder = new StringBuilder();

        builder.Append(" { ");

        foreach((string key, string value) in param)
        {
            builder.Append(" \"" + key + "\" :"); // key
            builder.Append(" \"" + value + "\" ,"); // value
        }

        builder.Append(" } ");

        return new StringContent(builder.ToString(), Encoding.UTF8, "application/json");
    }

注意:在 HttpContent 中使用 StringContent,继承关系为 StringContent -> ByteArrayContent -> HttpContent。

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