我有一个WCF服务,如果出现问题,会抛出一个通用的FaultException。 我不知道为什么,有时客户端会捕获非泛型的FaultException而不是泛型异常。
有人知道,问题是什么?
答案 0 :(得分:18)
您的服务需要处理所有异常并将它们包装成FaultException< T>其中T是您编写的数据合同。因此,第一步是定义包含您的异常信息的自定义数据协定:
[DataContract]
public class CustomFault
{
public string Message { get; set; }
}
然后,您指示您的服务合同,其方法可能会抛出FaultException< CustomFault>。这允许服务在wsdl中公开CustomFault类,以便客户端可以生成代理类:
[ServiceContract]
public interface IMyServiceContract
{
[FaultContract(typeof(CustomFault))]
void MyMethod(string someArgument);
}
下一步是实现此界面:
public class MyService : IMyServiceContract
{
public void MyMethod(string someArgument)
{
// Do something here that could throw exceptions but don't catch yet
}
}
要处理可以实现IErrorHandler的异常,只要您的某个服务方法引发异常,就会使用该异常。此错误处理程序的目的是将异常包装到FaultException< CustomFault>:
中public class MyErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message msg)
{
var customFault = new CustomFault()
{
Message = error.Message,
};
var fe = new FaultException<CustomFault>(customFault);
MessageFault fault = fe.CreateMessageFault();
string ns = "http://somenamespace/whatever";
msg = Message.CreateMessage(version, fault, ns);
}
}
在客户端注册错误处理程序后,您将始终获得FaultException&lt; CustomFault&gt ;.
答案 1 :(得分:5)
如果您的客户端无法访问Exception类型本身(在FaultException&lt; T&gt;上&lt; T&gt;),则抛出FaultException的非泛型版本。我花了好几个小时试图解决这个问题,并在我在msdn论坛上找到this时最终意识到这一点。如果有一些迹象表明异常在将其退出服务之前已经改变了,那就太好了,但是没有。
答案 2 :(得分:2)
当服务抛出一些未捕获的异常时,抛出非泛型FaultException
。您需要找出异常是什么,如果它是一个错误就修复它,或者确定它是您希望向客户公开的东西,然后将其包装在通用FaultException
中并添加{{1}适当的。
答案 3 :(得分:2)
另一种可能性是您的TDetail没有正确序列化。如果例如这可能是这种情况。 TDetail派生自Exception,并且您有一个不可序列化的内部异常。
答案 4 :(得分:1)
如果您未使用FaultContractAttribute声明故障详细信息类型,则会发生这种情况。
以下是您的服务合同的外观:
[ServiceContract]
public interface IMyServiceContract
{
//...
[OperationContract]
[FaultContract(typeof(MyFaultDetail))]
[FaultContract(typeof(OtherFaultDetail))]
GetDetailsResp GetDetails(GetDetailsReq req);
//...
}
答案 5 :(得分:1)
我看到了同样的问题,Drew发布的链接为我提供了答案。
我的解决方案是我的服务接口有一个与我的服务故障不同的命名空间。
即服务合同有:
[ServiceContract(Namespace = "http://dummydomain.com/service/searchservice")]
public interface ISearchService
....
并且服务故障有:
[DataContract(Namespace = "http://dummydomain.com/service/searchservicefault")]
public class MySearchServiceFault
...
显然当命名空间不同时,客户端不知道如何处理它并恢复到非通用的FaultContract ...我认为这在某种程度上取决于客户端,因为我已经看到上面的代码工作并返回通用FaultContract ......
但是,当我将名称空间更改为相同时,似乎使代码在我的测试中始终有效。
答案 6 :(得分:0)
我有一个类似的问题,当我升级某些NuGet软件包,使用共享的.NET标准类等时发生了这种情况(我不知道是什么原因造成的,在两个月内发生了很多更改,但是这些包括在内)。原来是将Action设置为字符串“ FAULT”的问题,并且使用默认的FaultContract属性在客户端运行良好。但是在进行了这些更改(2018年末)之后,字符串“ FAULT”作为操作意味着它不再与故障类匹配,而我得到了常规的FaultException。 解决所有问题的更改(客户端无更改)是在抛出FaultException而不是“ FAULT”时将操作设置为“ null” 。我想如果有人遇到这个问题,我会在这里发布该修复程序作为答案。