WCF - 使用自定义错误消息替换Fault SOAP消息的Fault节点

时间:2014-04-15 10:52:27

标签: .net wcf soap xmlserializer

我正在尝试使用IErrorHandler接口在WCF中实现自定义错误处理。我想将未处理的异常转换为自定义错误,这是我在XSD中获得的结构。

我的代码如下所示:

public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
    if (!(error is FaultException))
    {
        var customFault = new MyCustomFault
        {
            FaultString = "Something gone wrong",
            Detail = new DetailType
            {
                GeneralFault = new GeneralFaultType
                {
                    Errors = new[]
                    {
                        new ErrorType
                        {
                                Code = "333"
                        }
                    }
                }
            }
        };

        var faultException = new FaultException<MyCustomFault>(customFault);
        var msgFault = faultException.CreateMessageFault();
        fault = Message.CreateMessage(version, msgFault, faultException.Action);
    }
}

但是这段代码产生输出肥皂消息

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <s:Fault>
         <faultcode>s:Client</faultcode>
         <faultstring xml:lang="cs-CZ">The creator of this fault did not specify a Reason.</faultstring>
         <detail>
... MyCustomFault goes here...
         </detail>
      </s:Fault>
   </s:Body>
</s:Envelope>

我只能影响故障的细节元素。我想实现,而不是来自namespece“http://schemas.xmlsoap.org/soap/envelope/”的Fault元素将是我的自定义故障对象。这甚至可能吗?我正在使用XmlSerializer。

谢谢你, 米甲

2 个答案:

答案 0 :(得分:1)

不,不幸的是,这是不可能的。 WCF服务通过soap fault消息通知客户端错误的唯一方法。因此,WCF服务必须遵循soap规范。

遵循规范,所有故障消息必须具有相同的结构。请参阅规范:SOAP 1.2,查找第5.4.6节“SOAP故障代码”。您可以找到并举例说明(几乎与您提供的相同)以及所有节点的描述。

在SOAP 1.2中引入了Detail节点(请参阅规范:第5.4.5节SOAP详细信息元素)。

提供您的错误合同,您可以在此处以xml形式注入自定义错误(在Detail元素内)。但是其他xml结构是不可更改的。

答案 1 :(得分:0)

如果您需要遵循供应商的规范,您可以选择定义xml序列化,然后生成xmlReader,然后将该读取器传递给消息。我做了类似的事情,所以我可以单独测试一个修复了故障的行为/ messageInspector。

var xtr = new XmlTextReader("CustomSoapFault.xml");

// I'm only allocating 1MB, you could allocate more if needed
var message = Message.CreateMessage(xtr, 1024 * 1024, MessageVersion.Soap11);

CustomSoapFault.xml的内容

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
   <s:Body>
      <s:Fault>
          ... CustomFault goes here...
      </s:Fault>
   </s:Body>
</s:Envelope>

当.NET使用此方法生成消息时,Message.IsFault属性将返回true。

另外,请确保更新soap的命名空间和MessageVersion以使它们匹配。