【问题标题】:Catching an exception from a method从方法中捕获异常
【发布时间】:2021-12-23 05:28:23
【问题描述】:

我使用的库在 ApiKey 不起作用时会引发异常。假设库有一个名为 GetAppels() 的方法。如果 ApiKey 无效,则返回消息异常,在本例中为“禁止”。

注意 GetAppels() 正在抛出异常。

现在我想知道 ApiKey 何时无效,以便告诉用户使用了错误的密钥。

所以我这样做了。

try{
   apiTest api = new apiTest(Key.Text);
   api.GetAppels();
} catch (Exception) { MessageBox.Show("Wrong key!"); }

但这不起作用,由于某种原因,它继续在此之前抛出另一个异常。这是有道理的,因为 GetAppels 内部的尝试比我自己的尝试/捕获要先进行。我怎么能解决这个问题?当 GetAppels 方法(不是方法本身,而是其中的另一个方法)抛出异常时,我怎么能捕捉到?

编辑:

GetAppels() 方法只是一个例子,这就是该方法实际抛出异常的方式。

protected void HandleRequestFailure(HttpResponseMessage response)
{
    try
    {
        if (response.StatusCode == (HttpStatusCode)429)
        {
            var retryAfter = TimeSpan.Zero;
            if (response.Headers.TryGetValues("Retry-After", out var retryAfterHeaderValues))
            {
                if (int.TryParse(retryAfterHeaderValues.FirstOrDefault(), out var seconds))
                {
                    retryAfter = TimeSpan.FromSeconds(seconds);
                }
            }

            string rateLimitType = null;
            if (response.Headers.TryGetValues("X-Rate-Limit-Type", out var rateLimitTypeHeaderValues))
            {
                rateLimitType = rateLimitTypeHeaderValues.FirstOrDefault();
            }
            throw new RiotSharpRateLimitException("429, Rate Limit Exceeded", response.StatusCode, retryAfter, rateLimitType);
        }
        else if (RiotHttpStatusCodeResponse.Contains(response.StatusCode))
        {
            string message;
            try // try get error message from response
            {
                var json = response.Content.ReadAsStringAsync().Result;
                var obj = JObject.Parse(json);
                message = obj["status"]["message"].ToObject<string>();
            }
            catch {
                message = response.StatusCode.ToString();
            }
            throw new RiotSharpException(message, response.StatusCode);
        }
        else
            throw new RiotSharpException("Unexpeced failure", response.StatusCode);
    }
    finally
    {
        response.Dispose(); //Dispose Response On Error
    }
}

这就是我捕捉异常的方式,也许我做错了什么。

private bool CheckAPIKEY(string key)
{
    try
    {
        riotApi = RiotApi.GetDevelopmentInstance(key);
        riotApi.Summoner.GetSummonerByNameAsync(
            region: RiotSharp.Misc.Region.Euw, 
            summonerName: summonerName
        );

        return true;
    }
    catch (RiotSharpException) { return false; }
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (gameIsRunning)
        MessageBox.Show("Program is already running!");
    else if (summonerName != null) 
    {
        KEY = Key.Text;

        if(!CheckAPIKEY(KEY))
            MessageBox.Show("Your Riot API Key isn't valid.");          
    }
    else
        MessageBox.Show("Couldn't recive information about your SummonerName, is your League of legends game opened?");
}

【问题讨论】:

  • 它是怎么扔的?它是抛出方法还是在不重新抛出的情况下捕获它,实际上不抛出异常?你能展示GetAppels的实现吗?
  • @ef-dknittl-frank 我已经用代码编辑了帖子!
  • @HappyMoose RiotSharp.RiotSharpException: 'Forbidden'
  • 您的内部方法不会捕获(或吞下)异常,它只是将其抛出。所以你肯定可以用catch(Exception)catch(RiotSharpException) 来捕捉它
  • 看起来问题是您在同步方法中调用异步方法,因此您的代码在抛出异常之前完成执行。您应该将您的方法更改为异步并等待它(首选)或更改您的代码以使用 .GetAwaiter().GetResult()

标签: c# exception try-catch


【解决方案1】:

您正在调用异步方法,而不是以任何方式等待结果。您可以执行以下任一操作,尽管我认识的大多数 .NET 开发人员都喜欢第一个。

private async Task<bool> CheckAPIKEY(string key)
{
    try
    {
        riotApi = RiotApi.GetDevelopmentInstance(key);
        await riotApi.Summoner.GetSummonerByNameAsync(
            region: RiotSharp.Misc.Region.Euw, 
            summonerName: summonerName
        );

        return true;
    }
    catch (RiotSharpException) { return false; }
}

或者这个

private bool CheckAPIKEY(string key)
{
    try
    {
        riotApi = RiotApi.GetDevelopmentInstance(key);
        riotApi.Summoner.GetSummonerByNameAsync(
            region: RiotSharp.Misc.Region.Euw, 
            summonerName: summonerName
        )
        .GetAwaiter()
        .GetResult();


        return true;
    }
    catch (RiotSharpException) { return false; }
}

【讨论】:

    【解决方案2】:

    这样试试

    private bool API(string a)
    {
        try
        {
            Api = WebApi.GetDevelopmentInstance(a);
            Api.Summoner.GetSummonerByNameAsync(
                region: WebApi.Misc.Region.Euw, 
                summonerName: summonerName
            )
            .GetAwaiter()
            .GetResult();
    
    
            return true;
        }
        catch (WebApiException) { return false; }
    }
    

    【讨论】: