Как я могу выдать одно индивидуальное сообщение об ошибке для неправильного ответа API? - PullRequest
0 голосов
/ 10 июля 2019

Я пытаюсь вызвать единственное исключение HttpRequestException из C #, когда пользователь получает код состояния, отличный от 2xx, из API.Это отдельный метод, вызываемый из командлета PowerShell, поэтому в идеале я просто хочу, чтобы пользователь увидел ошибку, с сообщением, которое я создаю на основе кода состояния.

Вот класс, который я написал для проверкикод ответа:

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

Это потому, что я выкидываю ошибку из отдельного класса, и командлет тоже не завершается должным образом, или я делаю что-то еще неправильно?Я ценю вашу помощь в этом.

ОБНОВЛЕНИЕ:

Я попытался осмотреть некоторые примеры того, как сгладить или справиться с внутренними исключениями 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();
}

Я борюсь, потому что нет ошибки, если я не выкину одну.Я хочу, чтобы командлет завершился и сообщил код состояния вызова API.

1 Ответ

0 голосов
/ 10 июля 2019

Хорошо, поэтому вместо того, чтобы пытаться выдать HttpRequestException самостоятельно из базового класса для вызовов API, я возвратил строку с ошибкой, которая у меня уже была.Затем из командлета сопоставьте ответ с регулярным выражением, которое создаст ErrorRecord, и используйте ThrowTerminatingError () из класса Cmdlet, чтобы сообщить об ошибке.

Вызов 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();
    }
}

Внутри командлета

// 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

Как всегда, интересно узнатькак я мог бы справиться с этим лучше, потому что я уверен, что я, вероятно, не использовал лучшие или наиболее эффективные методы.Спасибо.

...