将FaultException <t>反序列化为FaultException

时间:2016-05-20 15:25:59

标签: c# wcf

我在这个问题上碰到了我的头,并检查了所有其他类似的问题,但无济于事。我有一个简单的FaultException,我正在抛弃WCF服务器并捕获客户端。

这是合同:

[ServiceContract]
public interface MyContract
{
    [OperationContract, FaultContract(typeof(TDetail))]
    void ThrowException();
}

[DataContract]
public class TDetail 
{
    public TDetail(string test) {
        Test = test;
    }
    [DataMember]
    public string Test { get; set; }
}

抛出异常的服务器代码:

throw new FaultException<TDetail>(new TDetail("Test"), "My test fault.");

客户收到的XML(由Fiddler提供):

我对此有点怀疑,因为我的课程被命名为“TDetail”,而非“Sender”。

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <s:Fault>
            <faultcode>s:Client</faultcode>
            <faultstring xml:lang="en-US">My test fault.</faultstring>
            <detail>
                <Sender xmlns:a="http://schemas.datacontract.org/2004/07/Sample.Namespace" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                    <a:Test>MyTest</a:Test>
                </Sender>
            </detail>
        </s:Fault>
    </s:Body>
</s:Envelope>

获取例外的客户端代码:

catch (FaultException<TDetail> ex)
{
    // I expect this
}
catch (FaultException ex)
{
    // But get this D:
}

客户收到的例外:

System.ServiceModel.FaultException was caught
  HResult=-2146233087
  Message=My test fault.
  Source=mscorlib
  StackTrace:
    Server stack trace: 
       at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
       at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
    Exception rethrown at [0]: 
       at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       at Sample.Namespace.ThrowException()
  InnerException: 

对于我的生活,我无法弄清楚为什么TDetail显然被客户抛弃了。我确定客户端和服务器都引用了同一个类(我将DLL复制粘贴到正确的文件夹中),我的实现并不复杂。这甚至在去年工作正常,从那以后我找不到任何实质性的代码更改。

有任何帮助吗? :(

为什么我的问题与潜在的副本不一样: 副本的设置更加复杂。最明显的是,他们实际上是在实现自定义的ErrorHandler并创建自己的错误(问题出在哪里),我不是。他们的答案不适用于我的情况。

最终解决方案: 我最终必须在FaultContract和我抛出FaultException时指定Name / Namespace。

[ServiceContract(Namespace = "MyNamespace")]
public interface MyContract
{
    [OperationContract]
    [FaultContract(typeof(TDetail), Name = "TDetail"]
    void ThrowException();
}

throw new FaultException<TDetail>(new TDetail("Test"), 
    "My test fault.", 
    new FaultCode("TDetail", "MyNamespace));

我还不是100%为什么必须这样,但至少它有效!

1 个答案:

答案 0 :(得分:0)

我自己尝试了,发现了同样的问题。然后我尝试添加名称和命名空间然后它工作。

[ServiceContract(Name = "MyContract", Namespace = "MyNameSpace")]
public interface MyContract
{
    [OperationContract, FaultContract(typeof(TDetail))]
    void ThrowException();
}

[DataContract(Name = "TDetail", Namespace = "MyNameSpace")]
public class TDetail
{
    public TDetail(string test)
    {
        Test = test;
    }
    [DataMember]
    public string Test { get; set; }
}

我认为发生的事情是,当您在不同的程序集上托管相同的代码时,它会占用该程序集的命名空间,因此在客户端连接到服务时不匹配,因此需要指定命名空间至少在数据合同上。

始终记得正确指定孩子的合同; - )