我有一个WCF 4 REST服务配置为使用json。我想要捕获异常并将异常消息的HTTP状态代码400返回为json对象。我在网络上遵循了一些例子来实现我自己的IErrorHandler和IService接口。WCF 4服务与json自定义错误处理程序返回202接受
例如:
http://zamd.net/2008/07/08/error-handling-with-webhttpbinding-for-ajaxjson/
Returning Error Details from AJAX-Enabled WCF Service
http://social.msdn.microsoft.com/Forums/en/wcf/thread/fb906fa1-8ce9-412e-a16a-5d4a2a0c2ac5
然而,正如在这个岗位
jQuery success callback called with empty response when WCF method throws an Exception
当我尝试创建我的错误时,我收到202 Accepted响应,但没有数据导致序列化错误。这是从我的服务记录如下:
2012-01-31 00:37:19,229 [8] DEBUG JsonWebScriptServiceHostFactory: creating service host
2012-01-31 00:37:19,292 [8] DEBUG JsonErrorHandler.ApplyDispatchBehavior: adding error handler
2012-01-31 00:43:06,995 [10] DEBUG ForemanSvc.GetSessionID
2012-01-31 00:43:39,292 [10] DEBUG ForemanSvc.GetProjects
2012-01-31 00:43:39,448 [10] DEBUG JsonErrorHandler.ProvideFault: creating fault
2012-01-31 00:43:39,635 [10] ERROR ForemanSvc exeption
Type: System.ServiceModel.CommunicationException
Message: Server returned an invalid SOAP Fault. Please see InnerException for more details.
Source: System.ServiceModel
StackTrace:
at System.ServiceModel.Channels.MessageFault.CreateFault(Message message, Int32 maxBufferSize)
at System.ServiceModel.Description.WebScriptEnablingBehavior.JsonErrorHandler.ProvideFault(Exception error, MessageVersion version, Message& fault)
at System.ServiceModel.Dispatcher.ErrorBehavior.ProvideFault(Exception e, FaultConverter faultConverter, ErrorHandlerFaultInfo& faultInfo)
at System.ServiceModel.Dispatcher.ErrorBehavior.ProvideMessageFaultCore(MessageRpc& rpc)
at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage8(MessageRpc& rpc)
Type: System.Xml.XmlException
Message: Start element 'Fault' from namespace 'http://schemas.microsoft.com/ws/2005/05/envelope/none' expected. Found element 'root' from namespace ''.
Source: System.Runtime.Serialization
StackTrace:
at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
at System.Xml.XmlExceptionHelper.ThrowStartElementExpected(XmlDictionaryReader reader, String localName, String ns)
at System.Xml.XmlDictionaryReader.ReadStartElement(XmlDictionaryString localName, XmlDictionaryString namespaceUri)
at System.ServiceModel.Channels.ReceivedFault.CreateFault12Driver(XmlDictionaryReader reader, Int32 maxBufferSize, EnvelopeVersion version)
at System.ServiceModel.Channels.MessageFault.CreateFault(Message message, Int32 maxBufferSize)
从该帖子不清楚如何解决它。我尝试了各种各样的方法 - 使用属性,使用端点行为,尝试使用没有json格式或返回额外信息的简单CreateMessage - 没有任何效果。谁能帮忙?
下面是一些代码片段 - 错误处理程序
public class JsonErrorHandler : IServiceBehavior, IErrorHandler
{
private static readonly ILog log =
LogManager.GetLogger(System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType);
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
//Dont do anything
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
//dont do anything
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
log.IfDebug("JsonErrorHandler.ApplyDispatchBehavior: adding error handler");
foreach (ChannelDispatcherBase dispatcherBase in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher channelDispatcher = dispatcherBase as ChannelDispatcher;
if (channelDispatcher != null)
{
channelDispatcher.ErrorHandlers.Add(this);
}
}
}
public bool HandleError(Exception error)
{
log.IfError("ForemanSvc exeption", error);
//Tell the system that we handle all errors here.
return true;
}
public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
{
log.IfDebug("JsonErrorHandler.ProvideFault: creating fault");
JsonError msErrObject =
new JsonError
{
Message = error.Message,
Source = error.Source,
Detail = error.InnerException != null ? error.InnerException.Message : null
};
//The fault to be returned
fault = Message.CreateMessage(version, "", msErrObject, new DataContractJsonSerializer(msErrObject.GetType()));
// tell WCF to use JSON encoding rather than default XML
WebBodyFormatMessageProperty wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
// Add the formatter to the fault
fault.Properties.Add(WebBodyFormatMessageProperty.Name, wbf);
//Modify response
HttpResponseMessageProperty rmp = new HttpResponseMessageProperty();
if (error is SecurityException &&
(error.Message == "Session expired" || error.Message == "Authentication ticket expired"))
{
rmp.StatusCode = HttpStatusCode.Unauthorized;
rmp.StatusDescription = "Unauthorized";
}
else
{
// return custom error code, 400.
rmp.StatusCode = HttpStatusCode.BadRequest;
rmp.StatusDescription = "Bad request";
}
//Mark the jsonerror and json content
rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
rmp.Headers["jsonerror"] = "true";
//Add to fault
fault.Properties.Add(HttpResponseMessageProperty.Name, rmp);
}
}
,并在那里我添加自定义错误处理程序服务
public class JsonWebScriptServiceHostFactory : WebScriptServiceHostFactory
{
private static readonly ILog log =
LogManager.GetLogger(System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType);
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
log.IfDebug("JsonWebScriptServiceHostFactory: creating service host");
ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses);
host.Description.Behaviors.Add(new JsonErrorHandler());
return host;
}
}
和自定义错误
[DataContract(Namespace = "VSS.Nighthawk.Foreman", Name = "JsonError")]
public class JsonError
{
[DataMember]
public string Message { get; set; }
[DataMember]
public string Source { get; set; }
[DataMember]
public string Detail { get; set; }
}
您是否找到解决方案? – Asher 2013-08-13 06:59:31