2012-02-03 79 views
3

我有一个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; } 
} 
+1

您是否找到解决方案? – Asher 2013-08-13 06:59:31

回答

0

什么约束力和编码器是否在使用,以及您已经配置了哪些设置?另外,你插入了什么行为?如果你已经插入了WebScriptEnablingBehavior(因为WebScriptServiceHostFactory自动插入它),你的问题可能是WSEB插入了它自己的错误处理程序,这与你尝试做的很多事情相同。

我还会做的是使用Reflector并查看嵌入在WebScriptEnablingBehavior中的错误处理程序,并查看您做了什么不同,以及您是否可以执行其他任何您尚未执行的操作。这是一个非常非常棘手和多毛的区域,有许多微妙之处,所以你可能没有第一次得到错误处理程序。

您可能还必须停止使用WebScriptEnablingBehavior(如果您正在使用它) - 所以请确保您不是。您可能不得不从头开始重新实现WebScriptEnablingBehavior,而是从服务主机工厂从头开始插入它,而不是只插入一个JSON错误处理程序。

希望这会有所帮助!

相关问题