【问题标题】:HttpClient PostAsync does not returnHttpClient PostAsync 不返回
【发布时间】:2018-04-28 09:46:48
【问题描述】:

我已经看到很多关于这个的问题,并且都指向我使用 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);
}

编辑:

为了响应下面的 cmets,代码包含在 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 只是一个对所有人开放的沙盒,所以可以分享 this):

编辑 3:

我认为问题在于我没有 SSL 证书来访问 API。我有一个连接到同一个 API 的 PHP 服务器,我必须将 SSL_VERIFYPEER 设置为 false 才能访问它(别担心,我现在添加了一个 cacert,所以它再次为 true)。这里会发生同样的问题吗?如果是这样,我该怎么做才能为我的 xamarin 表单应用程序创建有效证书

【问题讨论】:

  • 您在哪里以及如何称呼这一切?请告诉我们包含方法和调用它的位置。
  • HttpClient 有一个 Timeout 属性,将其设置为一个较小的值并将您的代码包装在一个 try-catch 块中以查看是否有任何异常。
  • 正如@FedericoDipuma 所说,您的问题(如果它是死锁)将与调用此代码的代码或调用该代码的代码等有关。您在某个地方阻塞了等待的同步上下文。 ConfigureAwait 不是为了避免死锁和it doesn't always save you 而创建的,因此您必须了解它的作用才能正确使用它。
  • @FedericoDipuma 嗨,我已经从最顶层的调用中添加了其他代码。我希望它能阐明可能导致问题的原因
  • 尝试设置 Fiddler 以拦截该请求并通过 C# 再次发送请求。将您在此处捕获的内容与您在 Postman 中看到的有关请求的内容进行比较。如果它们完全相同,您就知道您的问题在于处理响应的 C# 方面。如果它们不同,您可以调整在 C# 中构建请求的方式。如果您根本看不到请求,它甚至不会被发送,您将在 C# 中查看其他内容。

标签: c# .net xamarin.forms async-await dotnet-httpclient


【解决方案1】:

你可以用这个

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

【讨论】:

【解决方案2】:

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

【讨论】:

  • 但我的 OnExecute 方法是一个按钮事件处理程序(根据文档,void 适用于事件处理程序)。将类型更改为任务是否仍然有效?
  • 另外,我在我的天蓝色网站上设置了一个 API,它的响应很好。
【解决方案3】:

这和我通过 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 表单应用程序创建有效证书?
  • 好吧,我已经与 IIS 合作过,我们可以创建自签名证书。我相信这也是 PHP 服务器的一项规定。
【解决方案4】:

所以我认为问题现在已经解决,因为我能够从请求中接收内容,我所做的只是按照这里的文档:https://docs.microsoft.com/en-us/xamarin/cross-platform/app-fundamentals/transport-layer-security?tabs=windows

看起来我的设置在平台级别已经过时了。

更新 HttpClient 实现和 SSL/TLS 实现 启用 TLS 1.2 安全性的选项。

更新 HttpClient 实现选项以启用 TSL 1.2 安全。 (NSUrlSession (iOS 7.0+)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多