2011-06-22 184 views
9

返回XML我正在運行的ServiceHost來測試我的服務之一,直到我扔的FaultException一切工作正常 - 砰我得到XML不是JSONWCF JSON服務故障

我的服務合同 - 可愛

/// <summary> 
    /// <para>Get category by id</para> 
    /// </summary> 
    [OperationContract(AsyncPattern = true)] 
    [FaultContract(typeof(CategoryNotFound))] 
    [FaultContract(typeof(UnexpectedExceptionDetail))] 
    IAsyncResult BeginCategoryById(
     CategoryByIdRequest request, 
     AsyncCallback callback, object state); 

    CategoryByIdResponse EndCategoryById(IAsyncResult result); 

主機設置 - scrummy百勝

var host = new ServiceHost(serviceType, new Uri(serviceUrl)); 
host.AddServiceEndpoint(
    serviceContract, 
    new WebHttpBinding(), "") 
     .Behaviors.Add(
      new WebHttpBehavior 
          { 
           DefaultBodyStyle = WebMessageBodyStyle.Bare, 
           DefaultOutgoingResponseFormat = WebMessageFormat.Json, 
           FaultExceptionEnabled = true 
          }); 

host.Open(); 

這裏的呼喚 - OO肚子疼

var request = WebRequest.Create(serviceUrl + "/" + serviceName); 
request.Method = "POST"; 
request.ContentType = "application/json; charset=utf-8"; 
request.ContentLength = 0; 

try 
{ 
    // receive response 
    using (var response = request.GetResponse()) 
    { 
     var responseStream = response.GetResponseStream(); 

     // convert back into referenced object for verification 
     var deserialiser = new DataContractJsonSerializer(typeof (TResponseData)); 
     return (TResponseData) deserialiser.ReadObject(responseStream); 
    } 
} 
catch (WebException wex) 
{ 
    var response = wex.Response; 

    using (var responseStream = response.GetResponseStream()) 
    { 
     // convert back into fault 
     //var deserialiser = new DataContractJsonSerializer(typeof(FaultException<CategoryNotFound>)); 
     //var fex = (FaultException<CategoryNotFound>)deserialiser.ReadObject(responseStream); 

     var text = new StreamReader(responseStream).ReadToEnd(); 
     var fex = new Exception(text, wex);  

     Logger.Error(fex); 
     throw fex; 
    } 
} 

文本var包含正確的錯誤,但序列化爲Xml 我在這裏做了什麼錯誤?

回答

3

答案是實現一個IErrorHandler和支持行爲

我發現這個極好的職位由iainjmitchell

http://iainjmitchell.com/blog/?p=142

+2

The難點在於如何爲SOAP客戶端拋出FaultException,併爲REST客戶端拋出WebHttpException ......我還沒有想到這一點。 – Junto

+0

@Junto,你有沒有想過這個?它是否爲每個客戶提供了一個單獨的終端,併爲每個終端配置了必要的行爲配置? –

+0

@MrMoose我在這裏有一個開放的問題:http://stackoverflow.com/questions/7188519/wcf-ierrorhandler-to-return-faultexception-to-soap-and-webhttpexception-to-pox-a。你有沒有嘗試拋出一個新的WebHttpException (){...};並查看SOAP客戶端中會發生什麼? – Junto

0

這可能不會給你「爲什麼」的一部分。 看一看this question。它可以讓你在出現故障之前抓取並重新格式化故障。這至少會使你的反應足夠讓你走。 this也有一個類似的想法背後。

+0

感謝的是,可必須做類似的事情 - 但看起來他們正在抓住任何舊事物。淨異常,並使其JSON - 我的例外是正確的FaultExceptions,我希望Config來定義它們如何返回,在這種情況下,JSON,但它可能會部署到希望XML的地方 - 我想我也可以編碼,但它似乎我錯過了一些簡單的事情,這將使WCF的行爲,因爲我需要 - 再次感謝鏈接 –

0

根據MSDN documentation for DataContractJsonSerializer

「如果服務器或reply操作上的傳出答覆的序列化過程中發生錯誤拋出一些其他原因的例外,它可能不會返回到客戶端的故障「。另外,這僅僅是推測,但它幾乎看起來像這個序列化器序列化爲XML,然後將其轉換爲JSON。所以當你的故障發生時,它會在進程中斷?然後我又可能完全錯了。

祝你好運。

+0

它被返回到客戶端作爲故障 - 只是序列化爲Xml。另外,我不確定你提到的推測性位是否發生了錯誤,但是,如果確實存在,那麼它會不會返回? Ta反正 –

0

我不明白你爲什麼使用WebRequest來調用WCF服務。這是否有特定的原因?你如何知道當你處理那WebException它將是一個FaultException<CategoryNotFound>
如果你使用一個服務代理,你的服務引發FaultException<T>,它可能會更好寫你try-catch這樣的:

try 
{ 
    //Do service call 
} 
catch (FaultException<CategoryNotFound> fe) 
{ 
    //handle CategoryNotFound 
} 
catch (FaultException<UnexpectedExceptionDetail> fe) 
{ 
    //handle UnexpectedExceptionDetail 
} 
catch (FaultException exc) 
{ 
    //stuf 
} 
catch(Exception general){ 
    //all other stuff that might blow up 
} 
+0

這是爲了測試,我會將預期的類型傳遞給函數。 WebRequest的行爲像一個JSON客戶端 –

2

我可以高興地提出解決方案。 我有完全相同的問題,在我弄糟了一點我的端點行爲配置後,我發現了需要的配置元素。 解決的辦法是強制WCF使用選定的格式(JSON):

<behavior name="ExtendedJSONBehavior"> 
    <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="false"/> 
</behavior> 

正如你所看到的,關鍵是「automaticFormatSelectionEnabled」屬性。

有樂趣WCF再次

+2

不適合我,仍然得到XML回來,而不是JSON –

+0

我再次檢查屬性。該屬性在.NET 4.0中受支持。你用4.0嗎?並嘗試拋出「WebFaultException」而不是FaultException。我使用.Net的FaulException到.NET和WebFaultException從.Net到瀏覽器。 – Firzen

+0

我有同樣的問題,但我使用.net 3.5,我知道這些屬性只存在於.net 4.0。我可以做什麼來實現.net 3.5中的這個(請參閱我的問題http://stackoverflow.com/questions/12095621/consume-json-wcf-service-with-net-3-5-client) –

0
//由於調用 ProvideFault 時,客戶端處於阻塞狀態,不要在這裏進行長時間的操作 
public void ProvideFault(Exception error, MessageVersion version, ref Message msg) 
{ 
    //避免敏感信息泄漏,例如:數據庫配置, error包含的錯誤信息應該記錄到服務器的日誌中,不能顯示給客戶端 
    // FaultException<int> e = new FaultException<int>(123, error.Message); 
    DateTime now = DateTime.Now; 
    time = now.ToString("yyyyMMddHHmmssfff", DateTimeFormatInfo.InvariantInfo);// "" + now.Year.ToString() + now.Month.ToString() + now.Day.ToString() + now.Hour.ToString() + now.Minute.ToString() + now.Second.ToString() + now.Millisecond.ToString(); 
    string errorMsg = "服務內部錯誤_" + time; 
    // FaultException fe = new FaultException(errorMsg); 
    // MessageFault mf = fe.CreateMessageFault(); 
    // msg = Message.CreateMessage(version, mf, fe.Action); 

    //The fault to be returned 
    msg = Message.CreateMessage(version, "", errorMsg, new DataContractJsonSerializer(typeof(string))); 

    // tell WCF to use JSON encoding rather than default XML 
    WebBodyFormatMessageProperty wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json); 

    // Add the formatter to the fault 
    msg.Properties.Add(WebBodyFormatMessageProperty.Name, wbf); 

    //Modify response 
    HttpResponseMessageProperty rmp = new HttpResponseMessageProperty(); 

    // return custom error code, 400. 
    rmp.StatusCode = System.Net.HttpStatusCode.InternalServerError; 
    rmp.StatusDescription = "Bad request"; 

    //Mark the jsonerror and json content 
    rmp.Headers[HttpResponseHeader.ContentType] = "application/json"; 
    rmp.Headers["jsonerror"] = "true"; 

    //Add to fault 
    msg.Properties.Add(HttpResponseMessageProperty.Name, rmp); 
} 
+1

只有代碼的答案不是o.k.,請在此處再次輸入(英文)文本。 – peterh