C# Flurl和HttpClient,REST API没有响应

7
我遇到了一个问题,我的代码无法从API获取响应,请求没有超时,但是根本没有给我响应。我在自己的API中创建了一个API端点来返回JSON字符串,然后使用“Firefox Poster”手动发布JSON数据,这样就可以正常工作。因此,我认为问题出现在我的代码中。
我正在开发用于与Angular前端一起使用的C# WebAPI(这个是可行的,只是历史原因)。当调用我的API时,我创建了“EnrollmentRequestDto”对象。
public class EnrollmentRequestDto
{
    /// <summary>
    /// Context Information for the request. Contains the Ship-To, language code and timezone.
    /// </summary>
    [JsonProperty("requestContext")]
    public RequestContextDto RequestContext { get; set; }
    /// <summary>
    /// Unique ID provided by DEP to reseller on provisioning DEP access. This would be the reseller's DEP ID if its posted by distributor OBO a reseller, and would be his own depResellerId if a reseller is posting for self.
    /// </summary>
    [JsonProperty("depResellerId")]
    public string DepResellerId { get; set; }
    /// <summary>
    /// Unique transaction ID provided by the reseller
    /// </summary>
    [JsonProperty("transactionId")]
    public string TransactionId { get; set; }
    /// <summary>
    /// List of orders in the transaction (limit 1000 per transaction)
    /// </summary>
    [JsonProperty("orders")]
    public List<OrderDto> Orders { get; set; }
}

创建这个对象后,我将其发送到我的RequestHandler类和BulkEnrollRequest方法中。目前该方法使用HttpClient扩展Flurl编写,可以在此处找到: github。请注意保留HTML标记。
public IResponse BulkEnrollRequest(EnrollmentRequestDto enrollmentRequest)
    {
        try
        {
            var result = _bulkEnrollUrl.PostJsonAsync(enrollmentRequest).ReceiveJson<SuccessResponse>();
            result.Wait();
            return result.Result;
        }
        catch (FlurlHttpTimeoutException)
        {
            throw new AppleTimeOutException();
        }
        catch (FlurlHttpException ex)
        {
            return _errorHandler.DeserializeFlurlException(ex);
        }
    }

我还尝试过这个来确保在Flurl中没有发生任何事情(这只是为了调试到我想要得到响应的那个点):
public async Task<IResponse> BulkEnrollRequest(EnrollmentRequestDto enrollmentRequest)
    {
        var json = JsonConvert.SerializeObject(enrollmentRequest);

        var httpClient = new HttpClient();
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        HttpResponseMessage response = await httpClient.PostAsync(_bulkEnrollUrl, new StringContent(json, Encoding.UTF8, "application/json"));

        return new SuccessResponse();
    }

代码在await处卡住,没有任何反应。我尝试在BulkEnrollRequest之后放置断点,以使其永远不会离开此方法。

现在来说有趣的部分:当我在ErrorHandler上工作时,它确实起作用了,但某个时间点API突然停止响应。Wireshark 显示正在发出请求...所以我陷入了困境。

非常感谢任何帮助。

编辑

现在它可以工作了!我从API Controller一直实现了async,然后等待每个调用完成。供参考:

public async Task<IResponse> BulkEnrollRequest(EnrollmentRequestDto enrollmentRequest)
    {
        try
        {
            var result = await _bulkEnrollUrl.PostJsonAsync(enrollmentRequest).ReceiveJson<SuccessResponse>();
            return result;
        }
        catch (FlurlHttpTimeoutException)
        {
            throw new AppleTimeOutException();
        }
        catch (FlurlHttpException ex)
        {
            return _errorHandler.DeserializeFlurlException(ex);
        }
    }

下载 Fiddler 并将您的 HTTP 请求与“Firefox Poster”发送的请求进行比较。 - Eser
谢谢您的评论,我已经这样做了,但是我在请求中找不到任何奇怪的东西。然而,通过Fiddler,我发现我确实收到了来自API的响应,这正是我在代码中识别的“SuccessResponse”。我还进行了Wireshark跟踪,流量看起来有点奇怪,我认为。没有明显的RST或FIN ACK告诉我交易已经结束... - Miwca
2个回答

5

现在这个问题已经解决了。我认为Wireshark流量看起来很奇怪的原因是由于代码中出现了死锁,而且超时时间在我的一侧,这意味着我永远无法 FIN ACK 信息。为了解决这个问题,我对所有方法都实现了异步,从控制器到我的 RequestHandler 类。供参考:

public async Task<IResponse> BulkEnrollRequest(EnrollmentRequestDto enrollmentRequest)
    {
        try
        {
            var result = await _bulkEnrollUrl.PostJsonAsync(enrollmentRequest).ReceiveJson<SuccessResponse>();
            return result;
        }
        catch (FlurlHttpTimeoutException)
        {
            throw new AppleTimeOutException();
        }
        catch (FlurlHttpException ex)
        {
            return _errorHandler.DeserializeFlurlException(ex);
        }
    }

1
很高兴看到你没有放弃Flurl ;) - Todd Menier
这里对我来说关键是捕获Flurl特定的异常。它们直到代码的其余部分完成后才被冒泡。捕获它们使我能够确定在其余代码执行后调试器中发生了什么。(逐步跟踪内部异常。) - Will Strohl

0

尝试这段代码

Install-Package Microsoft.AspNet.WebApi.Client

 using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri("http://localhost:9000/");
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            HttpResponseMessage response = await client.PostAsJsonAsync("api/products", enrollmentRequest);
            if (response.IsSuccessStatusCode)
            {
                var result = await response.Content.ReadAsAsync<T>();
            }
        }

它仍然在await处冻结。就像我的代码无法获取答案一样 :) - Miwca

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