2011-06-22 87 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