【问题标题】:Re-use of serialized StringContent for http PostAsync为 http PostAsync 重用序列化的 StringContent
【发布时间】:2020-12-06 01:02:52
【问题描述】:

我正在对具有相同内容的不同 URI 进行 2 次 httpclient PostAsync 调用。如果我没有第二次序列化 StringContent,我的异步任务似乎永远不会执行完成。 请忽略我没有在异步调用中使用“等待”运算符的事实 - 除非这会以某种方式影响结果。我的理解是它不应该,但显然如果这是错误的,请帮助我的误解?

private static List<string> validPackageType = new List<string>(new string[] { "A", "B", "C"});
private static shipmentValidationURL = "https://shipment.com.au/v1/shipmentvalidation";
private static shipmentURL = "https://shipment.com.au/v1/shipment";

    public void Controller (){
        PostContent();
        logger.Trace("Sleep");
    }

    private async PostContent(){
        var json = JsonConvert.SerializeObject(validPackageType );
        var data = new StringContent(json, Encoding.UTF8, "application/json");
        var datastring = data.ReadAsStringAsync().Result;
        logger.Trace("data:{data}", datastring);
        logger.Trace("Shipment validation Posting to:{shipmentValidationURL}", shipmentValidationURL);
        var response = client.PostAsync(shipmentValidationURL, data);
        var respcontent = response.Result.Content.ReadAsStringAsync().Result;

        if (response.Result.IsSuccessStatusCode != true)
        {
            logger.Error("Validation Error:{errorxml}", respcontent);
            return;
        }
        else 
        {
            logger.Trace("Validation success");
        }

        logger.Trace("Calling Shipment Creation");
        data = new StringContent(json, Encoding.UTF8, "application/json"); //2nd StringContent()
        logger.Trace("data:{data}", datastring);
        var result = client.PostAsync(shipmentURL, data);
        var resultcontent = result.Result.Content.ReadAsStringAsync().Result;
        logger.Trace("Calling Shipment done");
        
        if (result.Result.IsSuccessStatusCode == true)
        {
            logger.Trace("Shipment success");

        }else{
            logger.Trace("Shipment failed");
        }
    }

输出:

The output WITHOUT the 2nd StringContent() call looks like:
11:01:07.1060 TRACE data:"{ A,B,C....}"
11:01:07.1060 TRACE Shipment validation Posting to:"https://shipment.com.au/v1/shipmentvalidation"
11:01:07.4680 TRACE Validation success
11:01:07.4680 TRACE Shipment update Posting to:"https://shipment.com.au/v1/shipment"
11:01:07.4680 TRACE Calling Shipment Creation
11:01:17.4865 TRACE Sleep

However if the 2nd StringContent call is made, it all executes as expected.
11:01:07.1060 TRACE data:"{ A,B,C....}"
11:01:07.1060 TRACE Shipment validation Posting to:"https://shipment.com.au/v1/shipmentvalidation"
11:01:07.4680 TRACE Validation success
11:01:07.4680 TRACE Shipment update Posting to:"https://shipment.com.au/v1/shipment"
11:01:07.4680 TRACE Calling Shipment Creation
11:01:07.1060 TRACE data:"{ A,B,C....}"
11:01:07.4680 TRACE Calling Shipment done
11:01:07.4680 TRACE Shipment success
11:01:17.4865 TRACE Sleep

【问题讨论】:

  • 除非以某种方式影响结果”您是否尝试等待一切?虽然可能不是你的问题,但不要阻塞异步方法。

标签: c# json asynchronous dotnet-httpclient


【解决方案1】:

显然PostAsync 处理了Content,因此在第一次PostAsync 调用后不再可以使用它。这在多个线程中进行了简要讨论,例如:

我没有深入研究为什么这是最佳行为或最佳实践(除了重新创建内容)。

奇怪的是,Visual Studio 调试器没有在上面提供的示例中发布异常。我摆弄了另一个带有“等待”的版本并强制Task.Wait(),然后那个版本警告我ObjectDisposedException()。我想这是另一个问题...

【讨论】:

    猜你喜欢
    • 2017-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    相关资源
    最近更新 更多