Asp.net Core 2.1 HttpClientFactory: второй вызов API не ожидает возвращенного результата первого вызова API - PullRequest
0 голосов
/ 15 декабря 2018

Я столкнулся с проблемой при использовании HttpClientFactory.Мне нужно вызвать два веб-метода из одного стороннего веб-интерфейса.

  1. getOrderNumber.
  2. getShippingLabelFile.

Вызов # 2 зависит от результата # 1, так как ему нужно передать ему orderNumber, например:

await _client.getAsync("http://xxx/api/getLabel?orderNumber=[returnedOrderNumber]&fileType=1")

Когда я устанавливаю точку остановаи отладить, все работает как положено.Без режима отладки веб-метод # 2 всегда терпел неудачу.Я провел расследование.Если я передаю статический параметр запроса, например:

http://xxx/api/getLabel?orderNumber=123&fileType=1

, он работает нормально.Кажется, # 2 оценивает строку запроса и выполняет вызов API перед тем, как ему присвоит orderNumber.Это очень расстраивает, не могли бы вы пролить свет на эту проблему?

На контроллере:

private readonly ISite1AuthHttpClient _site1HttpClient;

public OrderShippingOrdersController(site1AuthHttpClient)
{
    _site1HttpClient=site1AuthHttpClient
}

[HttpGet("{id}")]
public async Task<IActionResult> GetShippingLabel(int id)
{
    string token=await _site1HttpClient.GetToken(username.ToString(),password);
    string orderNumber=await _site1HttpClient.CreateOrder(Order,token);

    if (orderNumber!=null && orderNumber!="")
    {
        //this API call always failed during runtime. It works on debugging mode.
        var streamFile=(MemoryStream)(await _site1HttpClient.getShippingLabel(orderNumber,token));

    }
}

Класс типа HttpClient:

public interface ISite1HttpClient
{
    Task<string> CreateOrder(AueCreateOrder order,string token);
    Task<Stream> GetShippingLabel(string orderNumber,string token);
}

public class Site1HttpClient:ISite1HttpClient
{
    private readonly HttpClient _client;

    public Site1HttpClient(HttpClient httpClient)
    {
        httpClient.BaseAddress = new Uri("http://abcapi.Site1.com/");
        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));

        _client = httpClient;
    }

    public async Task<string> CreateOrder(AbcCreateOrder order,string token)
    {
        var jsonInString=JsonConvert.SerializeObject(order);
        jsonInString="[ " + jsonInString + " ]";

        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",token);
        HttpResponseMessage response = await _client.PostAsync(
            "api/AgentShipmentOrder/Create", new StringContent(jsonInString, Encoding.UTF8, "application/json"));

        if (response.IsSuccessStatusCode)
        {
            var contents = await response.Content.ReadAsStringAsync();
            AbcOrderCreateResponse abcRes = JsonConvert.DeserializeObject<AbcOrderCreateResponse>(contents);
            return abcRes.Message;
        }
        else
        {
            var errorResponse = await response.Content.ReadAsStringAsync();
            throw new Exception(errorResponse);
        }
    }

    public async Task<Stream> GetShippingLabel(string orderNumber,string token)
    {
        _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer",token);
        HttpResponseMessage response = await _client.GetAsync("api/GetOrderLabel?orderId="+orderNumber+"&fileType=1");

        if (response.IsSuccessStatusCode)
        {
            Stream streamFile= await response.Content.ReadAsStreamAsync();
            return streamFile;
        }
        else
        {
            throw new Exception("failed to get label.");
        }
    }
}

1 Ответ

0 голосов
/ 16 декабря 2018
string token = _site1HttpClient.GetToken(username.ToString(),password);
string orderNumber = await _site1HttpClient.CreateOrder(Order,token);

Я думаю, проблема возникает из-за первого ключевого слова await.Когда вы используете await для первого вызова функции (вызова асинхронной функции), вы объявляете, что вашей программе не нужно удерживать ответ.Таким образом, переменная токена используется во второй функции, когда она не установлена.Как вы можете видеть выше, вы должны хорошо обходиться без первого ожидания для переменной токена.

...