如何针对错误的API响应抛出单个自定义错误消息?

时间:2019-07-10 09:42:44

标签: c# error-handling try-catch

当用户从API接收到非2xx状态代码时,我试图从C#引发单个HttpRequestException。这是一个从PowerShell cmdlet调用的单独方法,因此理想情况下,我只希望用户看到错误,并根据状态代码创建消息。

这是我编写的用于检查响应代码的类:

internal class ISSChecks
{
    private static string Message;
    private static bool Success;

    internal static ResponseStatus CheckHttpResponse(int statusCode)
    {
        switch (statusCode)
        {
            case 200:
                Message = "Success";
                Success = true;
                break;
            case 201:
                Message = "New resource created";
                Success = true;
                break;
            case 202:
                Message = "Request accepted - Long running command";
                Success = true;
                break;
            case 204:
                Message = "Delete Success";
                Success = true;
                break;
            case 400:
                Message = "Bad Request";
                Success = false;
                break;
            case 401:
                Message = "Unauthorised";
                Success = false;
                break;
            case 403:
                Message = "Resource not accessible";
                Success = false;
                break;
            case 404:
                Message = "Resource not found";
                Success = false;
                break;
            case 405:
                Message = "Method not supported for this resource";
                Success = false;
                break;
            case 500:
                Message = "Internal server error";
                Success = false;
                break;
            case 503:
                Message = "Service not available";
                Success = false;
                break;
            default:
                Message = "Unknown";
                Success = false;
                break;
        }

        var responseString = statusCode.ToString() + " - " + Message;
        var responseStatus = new ResponseStatus(responseString, Success);
        return responseStatus;
    }

    internal class ResponseStatus
    {
        private string _callStatus;
        private bool _callSuccess;

        internal string CallStatus
        {
            get { return _callStatus; }
            set { _callStatus = value; }
        }

        internal bool CallSuccess
        {
            get { return _callSuccess; }
            set { _callSuccess = value; }
        }

        internal ResponseStatus(string callStatus, bool callSuccess)
        {
            this._callStatus = callStatus;
            this._callSuccess = callSuccess;
        }
    }
}

这是方法:

static private async Task InvokePost(HttpClient httpClient, string url, StringContent content)
{
    var response = await httpClient.PostAsync(url, content);
    var responseHeaders = response.Headers;
    var responseCode = (int)response.StatusCode;

    // Check the error code
    var responseStatus = ISSChecks.CheckHttpResponse(responseCode);

    if (responseStatus.CallSuccess != true)
    {
        throw new HttpRequestException(responseStatus.CallStatus);
    }

    // Collect content from the API call.
    JsonString = await response.Content.ReadAsStringAsync();
}

它在PowerShell中引发了一个错误,但是,看起来在一个错误记录中有多个错误。

this-cmdlet : One or more errors occurred.
AggregateException

这是因为我从单独的类抛出错误,并且cmdlet也没有以正确的方式终止,还是我做错了其他事情?感谢您的协助。

更新:

我试图查看一些有关如何展平或处理AggregateException的内部异常的示例,但是我不确定我是否在我的代码上下文中完全理解了它。

static private async Task InvokePost(HttpClient httpClient, string url, StringContent content)
{
    var response = await httpClient.PostAsync(url, content);
    var responseHeaders = response.Headers;
    var responseCode = (int)response.StatusCode;

    // Check the error code
    var responseStatus = ISSChecks.CheckHttpResponse(responseCode);

    if (responseStatus.CallSuccess != true)
    {
        try
        {
            throw new HttpRequestException(responseStatus.CallStatus).InnerException; // Pretty sure I do not need to throw here, but I also do not why throwing this error in the first place created multiple exceptions in an aggregate.
        }
        catch (AggregateException ex)
        {
            foreach (Exception e in ex.InnerExceptions)
            {
                // My first thought here was to throw e, but that would kill everything on the first instance.
            }
        }
    }

    // Collect content from the API call.
    JsonString = await response.Content.ReadAsStringAsync();
}

我很努力,因为如果我不扔一个就没有错误。我希望cmdlet终止并报告API调用的状态代码。

1 个答案:

答案 0 :(得分:0)

好吧,所以我没有尝试自己从API调用的基础类中抛出HttpRequestException,而是返回了一个字符串,该字符串带有我已经遇到的错误。然后从cmdlet中将响应与正则表达式匹配,这将创建一个ErrorRecord并使用Cmdlet类中的ThrowTerminatingError()来报告错误。

立即调用API:

static private async Task InvokePost(HttpClient httpClient, string url, StringContent content)
{
    var response = await httpClient.PostAsync(url, content);
    var responseHeaders = response.Headers;
    var responseCode = (int)response.StatusCode;

    // Check the error code
    var responseStatus = ISSChecks.CheckHttpResponse(responseCode);

    if (responseStatus.CallSuccess != true)
    {
        JsonString = responseStatus.CallStatus;
    }
    else
    {
        // Collect content from the API call.
        JsonString = await response.Content.ReadAsStringAsync();
    }
}

在cmdlet中

// Check the response for errors
Regex responseCheck = new Regex("^(?!2|{).*");
if (responseCheck.IsMatch(_response))
{
    Exception exception = new HttpRequestException(_response);
    ErrorRecord errorRecord = new ErrorRecord(exception, _response, ErrorCategory.InvalidOperation, null);
    ThrowTerminatingError(errorRecord);
}

如果有一个问题可以使您对发生的事情有所了解,则会导致错误。

Test-Cmdlet : 400 - Bad Request
At line:1 char:32
+ ... Test-Cmdlet -Name Test4 -Description "blah"
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Test-Cmdlet], HttpRequestException
    + FullyQualifiedErrorId : 400 - Bad Request,Test.Cmdlets.Test-Cmdlet

一如既往,我想知道如何更好地处理此问题,因为我确信我可能没有使用最好或最有效的方法。谢谢。