Управление ошибками WCF с помощью WebFaultException - неправильный HttpStatusCode - PullRequest
0 голосов
/ 18 февраля 2020

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

Я использую. NET framework 4.7.2 с Visual Studio 2019 и IIS Express 10 встроены в Visual Studio для тестирования на данный момент. Я использую расширение Бумеранг для Chrome для вызова службы.

Я реализовал метод FindPerson, который принимает имя. Если человек не найден или найдено более одного человека, я хочу вернуть ответ «Не найдено» (404).

Я реализовал простой класс ServiceError, который я использую для броска WebFaultException вместе с кодом ошибки Not Found. Когда я выбрасываю WebFaultException, соответствующая реакция на ошибку отправляется потребителю (я вижу подробности проблемы) , но статус http 500 (внутренняя ошибка службы) вместо ошибки 404, которую я использовал ( и ожидается получение)

Вот мой простой FindPerson метод:

Private Function FindPerson(ByVal name As String) As Person Implements MyService.FindPerson

    Dim foundPerson As Person = Nothing
    Dim people = GetPeople(name)
    Select Case people.Count
        Case Is > 1
            Throw New WebFaultException(Of ServiceError)(New ServiceError("More than 1 person found with the name provided.", ""), HttpStatusCode.NotFound)
        Case Is = 0
            Throw New WebFaultException(Of ServiceError)(New ServiceError("No Person with the name provided was found.", ""), HttpStatusCode.NotFound)
        Case Else
            foundPerson = people(0)
    End Select

    Return foundPerson
End Function

Вот мой класс ServiceError:

<DataContract>
Public Class ServiceError
    <DataMember>
    Public Property ErrorInfo As String
    <DataMember>
    Public Property ErrorDetails As String
    Public Sub New(ByVal info As String, ByVal details As String)
        Me.ErrorInfo = info
        Me.ErrorDetails = details
    End Sub
    Public Sub New()

    End Sub

End Class

Это ответ I получить. Как я уже сказал, детали верны ... но Http Status Error Code - это 500 вместо 404:

<s:Envelope
    xmlns:s="http://www.w3.org/2003/05/soap-envelope"
    xmlns:a="http://www.w3.org/2005/08/addressing">
    <s:Header>
        <a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action>
    </s:Header>
    <s:Body>
        <s:Fault>
            <s:Code>
                <s:Value>s:Sender</s:Value>
                <s:Subcode>
                    <s:Value
                        xmlns:a="http://schemas.microsoft.com/2009/WebFault">a:NotFound
                    </s:Value>
                </s:Subcode>
            </s:Code>
            <s:Reason>
                <s:Text xml:lang="en-US">Not Found</s:Text>
            </s:Reason>
            <s:Detail>
                <ServiceError
                    xmlns="http://schemas.datacontract.org/2004/07/My_Web_Service"
                    xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                    <ErrorDetails/>
                    <ErrorInfo>No Person with the name provided was found.</ErrorInfo>
                </ServiceError>
            </s:Detail>
        </s:Fault>
    </s:Body>
</s:Envelope>

Edit: Я нашел решение своей проблемы, но оно имеет только заставил меня осознать, что мне нужно найти лучшее решение.

Решение заключалось в реализации метода под названием RaiseWebException, который устанавливает код состояния исходящего ответа в состояние, также установленное в исключении WebFaultException:

Private Sub RaiseWebException(ByVal status As HttpStatusCode, ByVal info As String, ByVal details As String)
        WebOperationContext.Current.OutgoingResponse.StatusCode = status
        Throw New WebFaultException(Of ServiceError)(New ServiceError(info, details), HttpStatusCode.NotFound)
End Sub

Я вызвал метод, когда не смог найти свою личность:

Private Function FindPerson(ByVal name As String) As Person Implements MyService.FindPerson

  Dim foundPerson As Person = Nothing
  Dim people = GetPeople(name)
  Select Case people.Count
    Case Is > 1
        RaiseWebException(HttpStatusCode.NotFound, "More than 1 person found with the name provided.", "")
    Case Is = 0
        RaiseWebException(HttpStatusCode.NotFound, "Person with the name provided was found.", "")
    Case Else
        foundPerson = people(0)
  End Select

  Return foundPerson
End Function

Это хорошо работает при вызове метода из браузера с помощью Boomerang; однако, когда я тестирую вызов метода в тестируемом приложении, использующем vb. net, я не вижу сведений об ошибке службы. Я получаю сообщение об ошибке c 404 с сообщением об ошибке c, в котором говорится, что «конечная точка не может быть достигнута» вместо «человек не найден». Это может сбить с толку любого, кто вызывает службу через приложение-потребитель, реализованное с помощью. NET

Я не уверен, что это лучшее решение для управления ошибками в моем сервисе в будущем.

Я открыт для любых предложений по передовым методам управления ошибками в. NET веб-сервисах.

Спасибо

1 Ответ

0 голосов
/ 19 февраля 2020

Я нашел решение моего первоначального вопроса: установите для OutGoingResponse.StatusCode тот же код состояния, который я использовал для WebFaultException

. Решение заключалось в реализации метода с именем RaiseWebException, который устанавливает исходящий ответ. код состояния к статусу, который также был установлен в WebFaultException:

Private Sub RaiseWebException(ByVal status As HttpStatusCode, ByVal info As String, ByVal details As String)
        WebOperationContext.Current.OutgoingResponse.StatusCode = status
        Throw New WebFaultException(Of ServiceError)(New ServiceError(info, details), status)
End Sub

Я вызываю метод, когда мне не удается найти свою личность:

Private Function FindPerson(ByVal name As String) As Person Implements MyService.FindPerson

  Dim foundPerson As Person = Nothing
  Dim people = GetPeople(name)
  Select Case people.Count
    Case Is > 1
        RaiseWebException(HttpStatusCode.NotFound, "More than 1 person found with the name provided.", "")
    Case Is = 0
        RaiseWebException(HttpStatusCode.NotFound, "Person with the name provided was found.", "")
    Case Else
        foundPerson = people(0)
  End Select

  Return foundPerson
End Function

Это хорошо работает при вызове метода из браузера с помощью бумеранга; однако, когда я тестирую вызов метода в тестируемом приложении, использующем vb. net, я не вижу сведений об ошибке службы. Я получаю сообщение об ошибке c 404 с сообщением об ошибке c, в котором говорится, что «конечная точка не может быть достигнута» вместо «человек не найден». Это может сбить с толку любого, кто звонит в службу через приложение-потребитель, реализованное с помощью. NET.

Так что, хотя это и является ответом на мой первоначальный вопрос / проблему, оно кажется недостаточным для всего проекта. Удачи всем, кто сталкивается с тем же.

...