HttpClient的PostAsync方法没有返回结果。

14
我看到了很多关于这个问题的提问,所有的指向都告诉我需要使用ConfigureAwait(false),但即使这样做了,它仍然没有返回任何响应。当我运行调试器时,代码停留在PostAsync处,不继续执行我的代码。这里我做错了什么吗?这和我通过HTTPS调用API有关吗?
这是代码:
public async static Task<PaymentModel> AddAsync(Card card)
{
    HttpClient client = new HttpClient();

    client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:", "hidden"))));

    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

    var cardJson = JsonConvert.SerializeObject(card);
    var postRequest = new StringContent(cardJson, Encoding.UTF8, "application/json");
    var request = await client.PostAsync(new Uri("https://sample-3rd-party-api/api/endpoint/here"), postRequest).ConfigureAwait(false);
    var content = await request.Content.ReadAsStringAsync().ConfigureAwait(false);
}

编辑:

针对下面的评论,该代码是从一个名为AddAsync(Card card)的方法中调用的,该方法在点击带有处理程序的按钮时被调用:

public async void OnExecute(object sender, EventArgs args)
{
    //some code here
    payment = await PaymentModel.AddAsync(card).ConfigureAwait(false);
}

编辑2:我尝试使用ping API,但它返回请求超时,但是当我使用Postman尝试时,它运行良好(该API只是一个开放给所有人的沙盒,所以分享这个):

输入图像描述

输入图像描述

编辑3:

我认为问题出在我没有SSL证书来访问API。我有一个连接到同一个API的PHP服务器,我必须将SSL_VERIFYPEER设置为false才能访问它(不用担心,我现在添加了一个cacert,所以它又变成了true)。这里会发生相同的问题吗?如果是这样,我该如何为我的Xamarin Forms应用程序创建有效证书?


@DannyChen我尝试将它包装在try-catch块中。但结果只是导致了一种“线程已取消”异常。 - Lala
Timeout超时时,HttpClient会抛出TaskCanceledException异常。你确定第三方API正在工作吗? - Cheng Chen
@DannyChen是的,我能够使用Postman访问它。 - Lala
4
尝试使用 Fiddler 拦截该请求,并通过 C# 发送该请求。将你在那里捕获的内容与 Postman 中看到的请求进行比较。如果完全相同,则说明问题出现在处理响应的 C# 代码中。如果不同,您可以调整在 C# 中构建请求的方式。如果您根本看不到该请求,则表示它未被发送,您需要查看 C# 中的其他内容。 - S.C.
这可能是防火墙问题吗? - khargoosh
显示剩余9条评论
5个回答

3
您可以使用这个。
var json = JsonConvert.SerializeObject(card);
using (var client = new HttpClient())
{
    var t = await client.PostAsJsonAsync("https://sample-3rd-party-api/api/endpoint/here", json);

    Response R =JsonConvert.DeserializeObject<Response>((JsonConvert.DeserializeObject(t.Content.ReadAsStringAsync().Result.ToString())).ToString());
}

3
不要丢弃 HttpClient,因为它被设计成可重复使用。这里有更多信息:https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ - Brandon Minnick
HttpClient没有'PostAsJsonAsync'方法。 - Vincent

1
这里最可能发生的情况是您的OnExecute方法返回类型为void而不是Task,这会阻止UI线程等待它。尝试将返回类型更改为Task或创建一个新的UI线程来执行此操作。只要Postman工作正常,就不必担心ping超时。许多公共Web服务器禁用其ping响应。

1
但我的OnExecute方法是一个按钮事件处理程序(根据文档,void适用于事件处理程序)。如果将类型更改为Task,它仍然可以工作吗? - Lala
另外,我在我的 Azure 网站上设置了一个 API,并且它的响应非常良好。 - Lala

1

我曾经遇到过同样的问题,下面的技巧解决了这个问题。

将你的var request = await client.PostAsync(...);更改为以下内容:

var task = client.PostAsync(new Uri("https://sample-3rd-party-api/api/endpoint/here"), postRequest);
var request = task.GetAwaiter().GetResult();

0
这和我通过HTTPS调用API有关吗?
因为您在同一网络中,并从POSTMAN和.NET HTTP客户端调用相同的API并且只有在POSTMAN成功时,所以此问题被取消了。接下来
尝试ping API,但返回请求超时。
这在我的顶部已经回答了。
请尝试在初始化HTTPClient时设置超时选项。
client.Timeout = TimeSpan.FromSeconds(10);

如果问题仍然存在,请设置 Fiddler 并比较从 Postman 和 .NET 客户端发送的请求。


嗨,我认为问题在于我没有SSL证书来访问API。我有一个连接到同一API的PHP服务器,我必须将SSL_VERIFYPEER设置为false,这样我才能访问它(不用担心,我现在添加了cacert,所以它又变成了true)。同样的问题可能也发生在这里吗?如果是,那么我该如何为我的Xamarin Forms应用程序创建有效的证书? - Lala
好的,我曾经使用过IIS,在那里我们有创建自签名证书的范围。我相信PHP服务器也有这样的规定。 - Debashish Saha

0

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