WCF IErrorHandler 将 FaultException 返回给 SOAP,将 WebHttpException 返回给 POX 和 Json 端点
Posted
技术标签:
【中文标题】WCF IErrorHandler 将 FaultException 返回给 SOAP,将 WebHttpException 返回给 POX 和 Json 端点【英文标题】:WCF IErrorHandler to return FaultException to SOAP and WebHttpException to POX and Json endpoints 【发布时间】:2011-11-03 13:10:55 【问题描述】:我有一组使用 IErrorHandler 包装异常的 SOAP Web 服务,具体来说:
public sealed class ErrorHandler : IErrorHandler
public bool HandleError(Exception error)
return true;
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
// don't wrap existing fault exceptions
if ((error is FaultException)) return;
// our basic service fault
var businessFault = new BusinessFault FaultMessage = error.Message, FaultReference = "Internal" ;
// Resource based faultReason
var faultReason = new FaultReason(Properties.Resources.BusinessFaultReason);
var faultcode = FaultCodeFactory.CreateVersionAwareSenderFaultCode(InternalFaultCodes.BusinessFailure.ToString(), Service.Namespace);
var faultException = new FaultException<BusinessFault>(
businessFault,
faultReason,
faultcode);
// Create message fault
var messageFault = faultException.CreateMessageFault();
// Create message using Message Factory method
fault = Message.CreateMessage(version, messageFault, faultException.Action);
我现在为 Json 和 Pox 添加了额外的端点,它们可以正常工作,除非发生异常。对于 Json 端点,FaultException 以 XML 形式返回。
我从其他 SO 帖子中了解到,对于 REST,我最好抛出 WebHttpException:
throw new WebFaultException<BusinessFault>(detail, HttpStatusCode.BadRequest);
或者覆盖 ProvideFault 中的响应消息属性,因此:
var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
var rmp = new HttpResponseMessageProperty
StatusCode = System.Net.HttpStatusCode.BadRequest,
StatusDescription = "See fault object for more information."
;
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
不过,MSDN 对WebHttpException 有一些有趣的评论,即:
当使用 WCF REST 端点(WebHttpBinding 和 WebHttpBehavior 或 WebScriptEnablingBehavior) 响应上的 HTTP 状态码已设置 因此。但是,WebFaultException 可以与非 REST 一起使用 端点和行为类似于常规的 FaultException。
当使用 WCF REST 端点时,序列化的响应格式 故障的确定方式与非故障响应相同。更多 有关 WCF REST 格式的信息,请参阅 WCF REST 格式。
因此建议我需要转换当前的 ProvideFault 方法以提供新的 WebHttpException(包装任何现有的异常或故障异常),然后 SOAP 仍然可以正常工作。
有没有人想试一试那会是什么样子(.Net4.0 btw)?我想要一个错误处理程序来统治它们!
【问题讨论】:
我不明白你的问题。您想为 JSON/POX/SOAP 端点单独实现 IErrorHandler 吗? @Cybermaxs 正确。 WCF 允许您向不同类型的客户端公开多个端点。这一切都很好,直到你需要提出错误。如果我(通常)提出 SOAP 错误,那么 HTTP 客户端将不会更明智。如果我提出 HTTP 错误,那么 SOAP 客户端就会被蒙在鼓里。 【参考方案1】:我的印象是,使用 webHttpBinding
是一种获得 JSON/POX/SOAP 的“一体化”功能的方法,而不是为每个使用单独的绑定(即 wsHttpBinding
、basicHttpBinding
等等。)。那么,您难道不能直接抛出 WebHttpException
,然后让它为您提供所需的所有错误详细信息,而不管技术如何?
【讨论】:
【参考方案2】:在我正在处理的 REST 应用程序中,我创建了一个派生自 WebFaultException<T>
的新类,该类将一些附加数据附加到捕获的服务异常。在派生类的实例上调用CreatingMessageFault()
方法让我从错误处理程序的ProvideFault()
方法返回我选择的异常数据作为SOAP 错误,让WCF 确定正确的消息格式。
我正在使用webHttpBinding
绑定除部分第三方服务之外的所有服务。
编辑:添加代码示例
public class ErrorHandler : IErrorHandler, IServiceBehavior
public virtual void ProvideFault( Exception error, MessageVersion version, ref Message fault )
// Include next level of detail in message, if any.
MyFaultException myFaultException =
((error is MyFaultException) &&
((MyFaultException)error).Detail != null)
? new MyFaultException(error.Message + " - " +
((MyFaultException)error).Detail.Message, error)
: new MyFaultException( error.Message, error );
MessageFault messageFault = myFaultException.CreateMessageFault();
fault = Message.CreateMessage( version, messageFault, myFaultException.Action );
和
/// <summary>
/// Class used to return exception data from my WCF services.
/// </summary>
/// <remarks>
/// This class is used by a web service to pass exception data back and a
/// data object to the client. This class inherits WebFaultException, which
/// is handled specially by the WCF WebServiceHost2 service class and
/// generates a WebException on the client.
/// </remarks>
public class MyFaultException : WebFaultException<BusinessFault>
public class MyFaultException : WebFaultException<BusinessFault>
public MyFaultException(string message)
: this(HttpStatusCode.BadRequest, message)
public MyFaultException(HttpStatusCode statusCode, string message)
: base(new BusinessFault(message), statusCode)
然后在您的服务中,您可以抛出异常以将故障数据传递给您的客户端:
try
// Successful operation proceeds normally.
catch (ApplicationException e)
// Failure generates MyFaultException.
throw new MyFaultException("Operation failed with " + e.Message);
【讨论】:
如果您想添加代码示例,我可以尝试您所描述的内容。 我会试着找点时间试试看。那么,我会很高兴地为您提供答案。不过可能需要一段时间,因为我已经有一段时间没有从事这个项目了!以上是关于WCF IErrorHandler 将 FaultException 返回给 SOAP,将 WebHttpException 返回给 POX 和 Json 端点的主要内容,如果未能解决你的问题,请参考以下文章
使用 HandleError 或 ProvideFault 中的 IErrorHandler 在 WCF 中记录异常?