首页 > 解决方案 > 使用 WebFaultException 的 WCF 错误管理 - 错误的 HttpStatusCode

问题描述

我已经实现了一个简单的 Web 服务,我想根据被调用的方法中发生的错误返回适当的 Http 状态错误代码。

我目前正在使用 .NET framework 4.7.2 和 Visual Studio 2019 以及 Visual Studio 中内置的 IIS Express 10 进行测试。我正在使用 Chrome 的 Boomerang 扩展程序来调用该服务。

我已经实现了一个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

这是我得到的回应。就像我说的,细节是正确的......但 Http 状态错误代码是 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>

编辑: 我找到了解决问题的方法,但这只是让我意识到我需要找到更好的解决方案。

该解决方案涉及实现一种方法,该方法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 的测试应用程序中测试调用该方法时,我没有看到服务错误详细信息。我收到通用 404 错误,并带有通用错误消息,指出“无法到达端点”而不是“找不到此人”。这会让任何通过使用 .NET 实现的消费应用程序调用服务的人感到困惑

我不确定这是我未来服务中错误管理的最佳解决方案。

我愿意接受有关 .NET Web 服务中错误管理最佳实践的任何建议。

谢谢

标签: wcfsoaperror-handling

解决方案


我找到了原始问题的解决方案:将 设置为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

这在使用 Boomerang 从浏览器调用方法时效果很好;但是,当我在使用 vb.net 的测试应用程序中测试调用该方法时,我没有看到服务错误详细信息。我收到通用 404 错误,并带有通用错误消息,指出“无法到达端点”而不是“找不到此人”。对于通过使用 .NET 实现的消费应用程序调用服务的任何人来说,这都会让人感到困惑。

因此,虽然这是我最初的问题/问题的答案,但对于整个项目来说似乎是不够的。祝其他面临同样事情的人好运。


推荐阅读