我有一组使用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(包装任何现有的Exceptions或FaultExceptions),然后SOAP仍然可以正常工作。
有人愿意尝试一下(.Net4.0 btw)吗?我想要一个错误处理程序来统治它们!
答案 0 :(得分:0)
我的印象是使用webHttpBinding
是获得JSON / POX / SOAP的“一体化”功能的一种方式,而不是为每个使用单独的绑定(即wsHttpBinding
,basicHttpBinding
等。那么你是不是可以抛出WebHttpException
然后让你得到你需要的所有错误细节而不管技术如何?
答案 1 :(得分:0)
在我正在开发的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);
}