2012-02-03 83 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錯誤處理程序。

希望這會有所幫助!

相關問題