【问题标题】:Get response from PostAsJsonAsync从 PostAsJsonAsync 获取响应
【发布时间】:2013-03-04 15:45:27
【问题描述】:

我有这行代码

var response = new HttpClient().PostAsJsonAsync(posturi, model).Result;

被调用的 WebAPI 控制器返回一个 bool 以确保对象已保存,但我如何返回该 bool 响应?

【问题讨论】:

  • 使用调试器探索响应对象。还可以让 Fiddler 查看发布和接收的内容。如果您想以异步方式使用它,也可以使用 await - 而不是 .Response。
  • 访问者:PostAsJsonAsync 不在较新的 .net 的主库中,但您可以找到它。我的研究指向自己生成 Json 并调用 PostAsync。

标签: c# asp.net-mvc-4 asp.net-web-api


【解决方案1】:

继续从内容中获取:

var httpClient = new HttpClient();
var response = httpClient.PostAsJsonAsync(posturi, model).Result;
bool returnValue = response.Content.ReadAsAsync<bool>().Result;

但是,对于快速获得结果的方法来说,这实在是太天真了。 PostAsJsonAsyncReadAsAsync 不是这样设计的,它们是为了支持 async await 编程而设计的,所以你的代码应该是:

var httpClient = new HttpClient();
var response = await httpClient.PostAsJsonAsync(posturi, model);
bool returnValue = await response.Content.ReadAsAsync<bool>();

另外,您应该使用 HTTP 代码返回200 OK 来确定保存是否成功,而不是使用标志来检查对象是否已保存。

【讨论】:

  • 李,对于这种特殊情况,有一个非常具体的原因,我不在这种情况下
  • 为什么.Result 和阻塞而不是await
【解决方案2】:

接受的答案在技术上是正确的,但在调用 .Result 时会阻塞当前线程。如果您使用的是 .NET 4.5 或更高版本,则几乎在所有情况下都应避免这种情况。相反,请使用等效的异步(非阻塞)版本:

var httpClient = new HttpClient();
var response = await httpClient.PostAsJsonAsync(posturi, model);
bool returnValue = await response.Content.ReadAsAsync<bool>();

注意包含上述代码的方法需要标记async,并且本身应该是awaited。

【讨论】:

    【解决方案3】:

    因为它是一个异步操作,所以不要立即将.Result 视为错误

    相反,您需要这样做异步:

        var httpClient = new HttpClient()
    
        var task = httpClient.PostAsJsonAsync(posturi, model)
                             .ContinueWith( x => x.Result.Content.ReadAsAsync<bool>().Result);
    
        // 1. GETTING RESPONSE - NOT ASYNC WAY
        task.Wait(); //THIS WILL HOLD THE THREAD AND IT WON'T BE ASYNC ANYMORE!
        bool response = task.Result
    
        // 2. GETTING RESPONSE - TASK ASYNC WAY (usually used in < .NET 4.5 
        task.ContinueWith( x => {
                                  bool response = x.Result
                              });
    
        // 3. GETTING RESPONSE - TASK ASYNC WAY (usually used in >= .NET 4.5 
        bool response = await task;
    

    注意:我只是把它们写在这里,所以我没有实际测试它们,但或多或​​少这就是你想要的。

    希望对你有帮助!

    【讨论】:

    【解决方案4】:

    如果您调用通用版本,它应该返回布尔值:

    var response = new HttpClient().PostAsJsonAsync<bool>(posturi, model).Result;
    

    至少根据the docs.

    【讨论】:

    • 我认为 影响请求,而不是响应。
    • 在异步上使用 .Result 时要非常小心。在 ASP 和 UI 应用程序中获得线程死锁的最简单方法。
    【解决方案5】:

    我使用 HttpStatusCode 来检查结果。

        public HttpStatusCode PostStaffPositions(Foo foo)
        {
            string uri = myapiuri;
    
            using (HttpClient httpClient = new HttpClient())
            {
                var response = httpClient.PostAsJsonAsync(uri, foo).Result;
                return response.StatusCode;
            }
        }
    

    然后在 Controller 中像这样检查它:

       HttpStatusCode update = staffrest.PostStaffPositions(foo);
                if (update == HttpStatusCode.OK)
                {
                   //Update Succeed
                }
                else
                {
                    //Update Failed
                }
    

    【讨论】:

      【解决方案6】:

      现在是 2021 年 7 月,我正在使用 .net 5(即 .net core 5)。

      我在 System.Net.Http 中没有看到上述任何通用方法。现在代码看起来像这样(经过测试):

              using (var client = new HttpClient())
              {
                  client.BaseAddress = new Uri("https://localhost:44330/api/Book/Add");
                  var response = client.PostAsJsonAsync(client.BaseAddress,
                      JsonSerializer.Serialize(_teamSummaries));
                  MessageBox.Show(@"Result is " + JsonSerializer.Serialize(response));
                  var returnValue = response.Result.Content.ReadAsStringAsync();
                  MessageBox.Show(@"Return value is " + returnValue.Result);
              }
      

      还有ReadAsStringAsync、ReadAsByteArrayAsync、ReadAsStream、ReadFromJsonAsync、ReadFromJsonAsync(此方法返回Task)。

      但是从文字意思是“ReadFromJsonAsync”,我认为T不是上面提到的bool,而是一个包含bool成员的类。如果您想退回图书之类的东西,请尝试一下。

      另一方面,由于服务器上的代码如下所示(.net 5):

          [HttpPost]
          [Route("Add")]
          public async Task<ActionResult<IEnumerable<Book>>> Add(string value)
          {
              var all = await _dbCollection.FindAsync(Builders<Book>.Filter.Empty);
              return Ok("Everything is ok.");
          }
      

      所以,如果我们想通过 bool 返回 true,我们应该返回 Ok(...)。如果我们想通过 bool 返回 false,我们应该返回别的东西。还有 20 多种其他类型的结果,其中包含的信息要多得多,而不仅仅是“假”。

      【讨论】:

        猜你喜欢
        • 2022-06-28
        • 1970-01-01
        • 2020-08-10
        • 1970-01-01
        • 1970-01-01
        • 2014-10-29
        • 2021-09-12
        • 2019-04-04
        • 2017-06-18
        相关资源
        最近更新 更多