在.Net Web服务中抛出SoapException

4

编辑:我已经搜索了很多地方,但没有人似乎遇到类似的问题。在我的看来,抛出SoapException应该按照所需格式进行响应,而不仅仅是异常信息。非常感谢任何帮助。

我正在尝试返回一个类似于以下示例的SoapException

HTTP/1.1 500 Internal Server Error.
Date: Wed, 26 May 2004 05:12:08 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Cache-Control: private
Content-Type: text/xml; charset=utf-8
Content-Length: 488 

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
 <soap:Body>

   <soap:Fault>
     <faultcode>soap:Server</faultcode>
     <faultstring>BlahBlahBlahBlahBlah</faultstring>
     <detail />
   </soap:Fault>

 </soap:Body>
</soap:Envelope> 

为此,我已经实现了类似于以下代码的内容,取自于SoapException的MSDN网站:

Imports System
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports System.Xml.Serialization
Imports System.Xml

<System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class Service1
    Inherits System.Web.Services.WebService

    <WebMethod()>
    Public Sub Process()
        ' Build the detail element of the SOAP fault.
        Dim doc As New System.Xml.XmlDocument()
        Dim node As System.Xml.XmlNode = doc.CreateNode(XmlNodeType.Element, _
            SoapException.DetailElementName.Name, _
            SoapException.DetailElementName.Namespace)

        ' Build specific details for the SoapException.
        ' Add first child of detail XML element.
        Dim details As System.Xml.XmlNode = doc.CreateNode(XmlNodeType.Element, _
            "mySpecialInfo1", "http://tempuri.org/")

        ' Add second child of detail XML element with an attribute.
        Dim details2 As System.Xml.XmlNode = doc.CreateNode(XmlNodeType.Element, _
            "mySpecialInfo2", "http://tempuri.org/")
        Dim attr As XmlAttribute = doc.CreateAttribute("t", "attrName", _
            "http://tempuri.org/")
        attr.Value = "attrValue"
        details2.Attributes.Append(attr)

        ' Append the two child elements to the detail node.
        node.AppendChild(details)
        node.AppendChild(details2)

        'Throw the exception    
        Dim se As New SoapException("Fault occurred", SoapException.ClientFaultCode, _
                                    Context.Request.Url.AbsoluteUri, node)
        Throw se
        Return
    End Sub
End Class

然而,当我运行此代码时,实际发送的响应是:
HTTP/1.1 500 Internal Server Error
Server: ASP.NET Development Server/10.0.0.0
Date: Wed, 03 Jul 2013 13:06:26 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/plain; charset=utf-8
Content-Length: 233
Connection: Close

System.Web.Services.Protocols.SoapException: Fault occurred
   at MyService.Service1.Process() in C:\MyLocation\MyService\Service1.asmx.vb:line 42

我如何获取格式化的响应,类似于:
<soap:Envelope>
    <soap:Body>
        <soap:Fault>
            <faultcode/>
            <faultstring/>
            <detail/>
        </soap:Fault>
    </soap:Body>
</soap:Envelope>
1个回答

3
你的代码应该能够按照MSDN示例提供格式化错误,或者如果你想要类似你发布的响应示例中的结果,则此类服务可以帮助你实现:
Imports System
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports System.ComponentModel
Imports System.Xml.Serialization
Imports System.Xml

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem(False)> _
Public Class Service1
    Inherits WebService

    <WebMethod()>
    Public Sub Process()
        Dim detailsNode As XmlNode = Nothing
        Dim actorString As String = Nothing
        Throw New SoapException("BlahBlahBlahBlahBlah", SoapException.ServerFaultCode, actorString, detailsNode)
    End Sub
End Class

像这样的调用:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <tem:Process/>
   </soapenv:Body>
</soapenv:Envelope>

应该返回这个:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <soap:Body>
      <soap:Fault>
         <faultcode>soap:Server</faultcode>
         <faultstring>BlahBlahBlahBlahBlah</faultstring>
         <detail/>
      </soap:Fault>
   </soap:Body>
</soap:Envelope>

你还需要将以下代码添加到你的 Web.config 文件中,以消除故障字符串中的任何堆栈跟踪信息:
<configuration>
    <system.web>
        <customErrors mode="On" />
        ...
    ...     
...

此外,通常不需要手动构建SoapException,而是抛出更合适的异常并让ASP.NET将其包装在SoapFault中。有关更多详细信息,请参见使用SOAP故障
使用SoapUI调用您的方法,您应该会得到上面的结果。确保在SOAP端点上进行POST,例如http://localhost:8080/Service1.asmx,而不是在单击“Invoke”时的测试页面的URL上,例如http://localhost:8080/Service1.asmx/Process,因为它不返回SOAP格式化的响应。

我正在使用Fiddler(http://www.fiddler2.com)来跟踪请求和响应,它们如问题所示。将`<customErrors mode="On" />`添加到web.config中确实会删除堆栈跟踪,但是响应内容仅为“发生故障”,即仍未用soap标记格式化。我一开始就使用提供的链接作为我的问题基础。 - anothershrubery
@anothershrubery:请查看我的更新答案。您在调用时使用了哪个端点?直接在asmx网址上使用SoapUI,您应该会收到SOAP错误。 - Bogdan
谢谢,我使用了SoapUI并看到了正确的格式。我以为像Fiddler这样的调试代理会返回完全相同的请求/响应?显然不是这样。所以我一直传递正确的东西,只是没有使用正确的工具来查看它。干杯。 - anothershrubery

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接