用于调用 REST API 服务的 HttpClient 不起作用

问题描述 投票:0回答:1

这是过时的函数 - 使用 :

调用该函数
string requestData = RestClient.JiraRequest(buildFilter());

功能:

public static string JiraRequest(string api)
{
    string data = string.Empty;
    
    try
    {
        string requestUrl = @"https://jira.komax.org/rest/api/2/" + api;
        string authType = "Basic";
        string httpMethod = "GET";

        string authHeader = Convert.ToBase64String(Encoding.ASCII.GetBytes(Config.UserName + ":" + Config.UserPassword));
        _ = Encoding.UTF8.GetBytes(authHeader);

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
        request.Method = httpMethod;
        request.Headers.Add("Authorization", authType + " " + authHeader);
        request.ContentType = "application/json";

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();

        if (response.StatusCode != HttpStatusCode.OK)
        {
            throw new ApplicationException("Exeption error: " + response.StatusCode.ToString());
        }

        using (Stream responseStream = response.GetResponseStream())
        {
            if (responseStream != null)
            {
                using (StreamReader reader = new StreamReader(responseStream))
                {
                    data = reader.ReadToEnd();
                }
            }
        }
    }
    catch (Exception ex)
    {
        HandleExeption.Exception(ex);
        return data;
    }

    return data;
}

这是新函数 - 使用 :

调用该函数
string requestData = await RestClient.JiraRequest(buildFilter());

功能:

public static async Task<string> JiraRequest(string api)
{
    string data = string.Empty;

    try
    {
        string requestUrl = @"https://jira.komax.org/rest/api/2/" + api;
        string authType = "Basic";

        using (HttpClient client = new())
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authType, Convert.ToBase64String(Encoding.ASCII.GetBytes(Config.UserName + ":" + Config.UserPassword)));

            HttpResponseMessage responseMessage = await client.GetAsync(requestUrl);

            if (!responseMessage.IsSuccessStatusCode)
            {
                throw new ApplicationException("HttClient exception: " + responseMessage.StatusCode.ToString());
            }

            data = await responseMessage.Content.ReadAsStringAsync();
            return data;
        }
    }
    catch (Exception ex)
    {
        HandleExeption.Exception(ex);
        return data;
    }
}

描述和历史: 使用旧代码,我收到两条消息,表明这种方法已过时,因此我编写了新的

HttpClient

使用过时的功能,它可以完美地工作,但是使用新的功能,它不再工作了..

新函数出错:调用后崩溃

HttpResponseMessage responseMessage = await client.GetAsync(requestUrl);

没有显示任何异常,我也尝试过

Debug.Writeline
,但也没有任何显示。

调用 this 后,程序直接退出(崩溃)....

异常(异常前):

public static void Exception(Exception ex)
        {
            StackTrace stackTrace = new(ex, true);

#nullable enable
            StackFrame? stackFrame = stackTrace.GetFrame(stackTrace.FrameCount - 1);
#nullable disable

            Debug.WriteLine($"Exception message: {ex.Message ?? "No message"}");

            if (stackFrame != null)
            {
                var method = stackFrame.GetMethod();
                Debug.WriteLine($"Exception in method: {method}");

                var lineNumber = stackFrame.GetFileLineNumber();
                Debug.WriteLine($"Exception in line: {lineNumber}");
            }
        }
c# async-await httpclient visual-studio-2022 httpresponsemessage
1个回答
0
投票

我怀疑你的程序在该特定代码行“崩溃”,因为你在那里有异常处理,这会捕获该方法中抛出的任何错误。

新旧版本之间唯一显着的区别是新版本是异步的。在导致调用此特定方法的调用堆栈中的某个位置,您没有正确地

await
异步方法的结果。即你有这样的东西

public static void Main(string[] args) {
  ...
  methodA();
}

void methodA() {
  ...
  methodB();
}


async Task methodB() {
  ...
  await methodC();
}

async Task<...> methodC() {
  try {
    HttpResponseMessage responseMessage = await client.GetAsync(requestUrl);
    ...

    return ...
  } catch (Exception ex) {
    ...
  }
}

因此,当您现在从同步上下文调用

methodA()
时,它会调用
methodB()
而不等待其结果。这是完全有效的(尽管它会在 Visual Studio 中生成警告),但此时您会丢失异步上下文。这意味着
methodA()
将在 methodB()
 之前完成,这会将调用堆栈向上冒泡到 
Main()
 方法,该方法也将在 
methodB()
 完成之前到达结束。

Main

方法结束时,程序终止。无论是否仍有异步操作挂起。

这可能是在您将

JiraRequest(string api)

 从同步重构为异步时发生的。

© www.soinside.com 2019 - 2024. All rights reserved.