C# Flurl 和 HttpClient,REST 无响应 API

C# Flurl and HttpClient, no response from REST API

我在使用我的代码从 API 获得响应时遇到问题,请求没有超时,它根本没有给我响应。我在自己的 API 中创建了一个 api 端点到 return json 字符串,然后手动 post json 数据 "Firefox Poster" 并且效果很好。有了这个,我相信问题出在我的代码中。

我有一个 C# WebAPI,我正在开发它以与 Angular 前端一起使用(这有效,只是为了历史)。调用我的 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; }
}

创建此对象后,我发送到我的 class RequestHandler 和 BulkEnrollRequest 方法,其中 atm 是用 HttpClient 扩展 Flurl 编写的,可以在这里找到:github

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

并且代码在等待点冻结,什么也没有发生。我试图在 BulkEnrollRequest 之后放置一个断点,所以它永远不会离开这个方法。

有趣的是:当我在处理 ErrorHandler 时它确实起作用了,在某个时候 API 刚刚停止响应。 Wireshark 显示正在发出请求...所以我卡住了。

感谢任何帮助。

编辑

这现在有效了!我实现了 async 从 API Controller 一直到 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);
        }
    }

试试这个代码

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

此问题现已修复。我相信 Wireshark 流量看起来如此奇怪的原因是代码中的死锁,超时在我这边,这意味着我永远无法 FIN ACK 信息。为了解决这个问题,我在所有方法上实现了 async,从 Controller 到我的 RequestHandler class。供参考:

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