.NET WCF错误生成不正确的SOAP 1.1错误代码值

.NET WCF错误生成不正确的SOAP 1.1错误代码值

.NET WCF faults generating incorrect SOAP 1.1 faultcode values

我正在尝试使用FaultException和FaultException < T >确定我们应用程序中的最佳用法模式。我们需要支持WCF以及非WCF服务使用者/客户端,包括SOAP 1.1和SOAP 1.2客户端。

仅供参考:将FaultExceptions与wsHttpBinding一起使用会导致SOAP 1.2语义,而将FaultExceptions与basicHttpBinding一起使用会导致SOAP 1.1语义。

我正在使用以下代码抛出FaultException

1
2
3
4
5
  throw new FaultException<FaultDetails>(
      new FaultDetails("Throwing FaultException<FaultDetails>."),
      new FaultReason("Testing fault exceptions."),
      FaultCode.CreateSenderFaultCode(new FaultCode("MySubFaultCode"))
      );

FaultDetails类只是一个简单的测试类,其中包含字符串" Message"属性,如下所示。

使用wsHttpBinding时,响应为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="utf-16"?>
<Fault xmlns="http://www.w3.org/2003/05/soap-envelope">
<wyn>
  <Value>Sender</Value>
  <Subcode>
    <Value>MySubFaultCode</Value>
  </Subcode>
</wyn>
<Reason>
  <Text xml:lang="en-US">Testing fault exceptions.</Text>
</Reason>
<Detail>
  <FaultDetails xmlns="http://schemas.datacontract.org/2004/07/ClassLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Message>Throwing FaultException<FaultDetails>.</Message>
  </FaultDetails>
</Detail>

根据SOAP 1.2规范,这看起来不错。主/根"代码"是"发件人",其"子代码"为" MySubFaultCode"。如果服务使用者/客户端使用WCF,则客户端的FaultException也将模拟相同的结构,faultException.Code.Name为"发件人",faultException.Code.SubCode.Name为" MySubFaultCode"。

使用basicHttpBinding时,响应为:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-16"?>
<s:Fault xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <faultcode>s:MySubFaultCode</faultcode>
  <faultstring xml:lang="en-US">Testing fault exceptions.</faultstring>
  <detail>
    <FaultDetails xmlns="http://schemas.datacontract.org/2004/07/ClassLibrary" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
      <Message>Throwing FaultException<FaultDetails>.</Message>
    </FaultDetails>
  </detail>
</s:Fault>

这看起来不对。看一下SOAP 1.1规范,当我使用FaultCode.CreateSenderFaultCode(new FaultCode(" MySubFaultCode"))时,我期望看到"故障代码"的值为" s:Client.MySubFaultCode"。此外,WCF客户端的结构也不正确。 faultException.Code.Name为" MySubFaultCode",而不是" Sender",faultException.Code.SubCode为null,而不是faultException.Code.SubCode.Name为" MySubFaultCode"。另外,faultException.Code.IsSenderFault为false。

使用FaultCode.CreateReceiverFaultCode(new FaultCode(" MySubFaultCode"))时出现类似问题:

  • 可以正常工作于SOAP 1.2
  • 生成" s:MySubFaultCode"而不是" s:Server.MySubFaultCode",并且对于SOAP 1.1,faultException.Code.IsReceiverFault为false

此项目也在2006年由其他人发布在http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=669420&SiteID=1上,没有人回答。我很难相信没有人遇到过这种情况。

这是其他有类似问题的人:http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3883110&SiteID=1&mode=1

Microsoft Connect错误:https://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=367963

故障如何工作的描述:http://blogs.msdn.com/drnick/archive/2006/12/19/creating-faults-part-3.aspx

我是在做错什么,还是WCF中的错误?


这是我当前的解决方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    /// <summary>
    /// Replacement for the static methods on FaultCode to generate Sender and Receiver fault codes due
    /// to what seems like bugs in the implementation for basicHttpBinding (SOAP 1.1). wsHttpBinding
    /// (SOAP 1.2) seems to work just fine.
    ///
    /// The subCode parameter for FaultCode.CreateReceiverFaultCode and FaultCode.CreateSenderFaultCode
    /// seem to take over the main 'faultcode' value in the SOAP 1.1 response, whereas in SOAP 1.2 the
    /// subCode is correctly put under the 'Code->SubCode->Value' value in the XML response.
    ///
    /// This workaround is to create the FaultCode with Sender/Receiver (SOAP 1.2 terms, but gets
    /// translated by WCF depending on the binding) and an agnostic namespace found by using reflector
    /// on the FaultCode class. When that NS is passed in WCF seems to be able to generate the proper
    /// response with SOAP 1.1 (Client/Server) and SOAP 1.2 (Sender/Receiver) fault codes automatically.
    ///
    /// This means that it is not possible to create a FaultCode that works in both bindings with
    /// subcodes.
    /// </summary>
    /// <remarks>
    /// See http://stackoverflow.com/questions/65008/net-wcf-faults-generating-incorrect-soap-11-faultcode-values
    /// for more details.
    /// </remarks>
    public static class FaultCodeFactory
    {
        private const string _ns ="http://schemas.microsoft.com/ws/2005/05/envelope/none";

        /// <summary>
        /// Creates a sender fault code.
        /// </summary>
        /// <returns>A FaultCode object.</returns>
        /// <remarks>Does not support subcodes due to a WCF bug.</remarks>
        public static FaultCode CreateSenderFaultCode()
        {
            return new FaultCode("Sender", _ns);
        }

        /// <summary>
        /// Creates a receiver fault code.
        /// </summary>
        /// <returns>A FaultCode object.</returns>
        /// <remarks>Does not support subcodes due to a WCF bug.</remarks>
        public static FaultCode CreateReceiverFaultCode()
        {
            return new FaultCode("Receiver", _ns);
        }
    }

可悲的是,我没有一种不破坏SOAP 1.1或1.2客户端的使用子代码的方法。

如果使用Code.SubCode语法,则可以创建与SOAP 1.1兼容的故障代码值,但是它将破坏SOAP 1.2。

如果在.NET中使用适当的子代码支持(通过静态FaultCode方法或通过重载之一),它将破坏SOAP 1.1,但可以在SOAP 1.2中使用。


微软的回应:

如http://msdn.microsoft.com/zh-cn/library/ms789039.aspx中所述,Soap 1.1规范中概述了两种用于自定义故障代码的方法:

(1)使用您描述的"点"符号

(2)定义全新的故障代码

不幸的是,应该避免使用"点"符号,因为在WS-I Basic Profile规范中不鼓励使用它。本质上,这意味着使用Soap 1.1时,Soap 1.2故障子代码没有真正的等效项。

因此,在生成故障时,您必须了解绑定中定义的MessageVersion,并相应地生成故障代码。

由于"发件人"和"接收者"不是Soap 1.1的有效故障代码,并且没有真正等同的故障子代码,因此在为Soap 1.1生成自定义故障代码时,不应使用CreateSenderFaultCode和CreateReceiverFaultCode方法。

相反,您需要使用自己的名称空间和名称来定义自己的故障代码:

FaultCode customFaultCode =新的FaultCode(localName,faultNamespace);


推荐阅读

    linux命令行模式清页?

    linux命令行模式清页?,工作,系统,命令,信息,地址,目录,内容,文件,操作,功能,l

    linux底线模式命令?

    linux底线模式命令?,系统,档案,密码,状态,工作,命令,模式,文件,明文,界面,lin

    linux启用命令模式?

    linux启用命令模式?,系统,密码,数字,首页,电脑,情况,终端,界面,模式,命令,安

    linux命令错误代码?

    linux命令错误代码?,系统,密码,电脑,网络,手机,网址,软件,代码,设备,老板,Lin

    linux命令测试客户端?

    linux命令测试客户端?,地址,系统,网络,工具,工作,分析,环境,命令,下行,资料,l

    linux命令行模式联网?

    linux命令行模式联网?,系统,网络,地址,密码,软件,检测,信息,工具,终端,界面,l

    linux回到命令行模式?

    linux回到命令行模式?,系统,密码,状态,工具,电脑,终端,界面,环境,地方,命令,

    linux命令模式联网?

    linux命令模式联网?,网络,系统,工具,软件,密码,地址,最新,信息,工作,数据,lin

    linux进去命令模式?

    linux进去命令模式?,系统,密码,首页,终端,命令,界面,窗口,选项,桌面,用户,lin

    linux命令模式全屏?

    linux命令模式全屏?,系统,工具,电脑,数据,位置,命令,虚拟机,分辨率,字符串,

    linux中回到命令模式?

    linux中回到命令模式?,系统,密码,情况,状态,终端,环境,信息,首页,界面,命令,

    linux命令行模式6?

    linux命令行模式6?,系统,设计,信息,工作,终端,首页,庞大,服务,地方,环境,linu

    linux怎么用命令模式?

    linux怎么用命令模式?,工作,地址,系统,信息,管理,命令,目录,情况,图形界面,

    linux插入命令模式?

    linux插入命令模式?,工作,系统,地址,管理,信息,时间,命令,目录,平均,项目,Lin

    命令行模式登陆linux?

    命令行模式登陆linux?,密码,系统,工作,信息,终端,环境,状态,地址,工具,服务,l

    linux打开命令模式?

    linux打开命令模式?,系统,密码,管理,情况,终端,命令,工具,信息,地方,电脑,LIN

    linux命令忽略错误?

    linux命令忽略错误?,系统,地址,工作,信息,设备,命令,设计,灵活,观察,标准,lin

    linux纯命令模式切换?

    linux纯命令模式切换?,系统,密码,状态,电脑,网络,信息,模式,命令,情况,地方,L

    linux命令底行模式?

    linux命令底行模式?,系统,地址,工作,命令,管理,时间,信息,模式,控制台,图形

    linux中进入命令模式?

    linux中进入命令模式?,系统,服务,信息,命令,终端,情况,地址,模式,数据库,选