WCF JSON服务在出错时返回XML

WCF JSON服务在出错时返回XML,wcf,json,Wcf,Json,我正在运行一个ServiceHost来测试我的一个服务,在抛出一个FaultException(错误异常)之前,所有的服务都可以正常工作——我得到的是XML而不是JSON 我的服务合同-可爱 /// <summary> /// <para>Get category by id</para> /// </summary> [OperationContract(AsyncPattern = true)] [Fa

我正在运行一个ServiceHost来测试我的一个服务,在抛出一个FaultException(错误异常)之前,所有的服务都可以正常工作——我得到的是XML而不是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);
这是电话-哦,肚子痛

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 request=WebRequest.Create(serviceUrl+“/”+serviceName);
request.Method=“POST”;
request.ContentType=“application/json;charset=utf-8”;
request.ContentLength=0;
尝试
{
//接收响应
使用(var response=request.GetResponse())
{
var responseStream=response.GetResponseStream();
//转换回引用对象以进行验证
var反序列化器=新的DataContractJsonSerializer(typeof(trespona));
return(trea)反序列化程序.ReadObject(responseStream);
}
}
捕获(WebException wex)
{
var响应=wex.响应;
使用(var responseStream=response.GetResponseStream())
{
//归罪
//var deserialiser=newdatacontractjsonserializer(typeof(FaultException));
//var fex=(FaultException)反序列化程序.ReadObject(responseStream);
var text=新的StreamReader(responseStream).ReadToEnd();
var fex=新异常(文本,wex);
记录器错误(fex);
投加fex;
}
}
文本变量包含正确的错误,但已序列化为Xml
我做错了什么?

这可能不会告诉你为什么。 看一看。它允许您在故障作为响应发出之前捕获并重新格式化故障。这至少会使你的回答变得足够生动,让你行动起来。 也有类似的想法

根据:

如果在服务器上对传出应答进行序列化时发生错误,或者应答操作因其他原因引发异常,则可能无法将其作为故障返回到客户端

此外,这只是猜测,但看起来这个序列化程序几乎可以序列化为XML,然后将其转换为JSON。所以当你的错误发生时,它会在过程中被打断?那我也可能完全错了


祝你好运。

我不明白你为什么使用WebRequest呼叫WCF服务。有没有具体的原因?当您处理该
WebException
时,您如何知道它将是一个
FaultException

如果您使用服务代理,并且您的服务抛出
FaultException
,那么最好像这样编写
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
}
试试看
{
//服务电话
} 
捕获(故障异常fe)
{
//未找到句柄类别
}
捕获(故障异常fe)
{
//处理意外异常详细信息
}
catch(FaultException exc)
{
//斯图夫
}
捕获(一般例外){
//所有其他可能爆炸的东西
}

我很乐意提出解决方案。 我遇到了完全相同的问题,在我稍微弄乱了端点行为配置之后,我发现了所需的配置元素。 解决方案是强制wcf使用所选格式(json):


如您所见,关键是“AutomaticFormatSelectEnabled”属性


再次享受wcf的乐趣

答案是实现IErrorHandler和支持行为

我发现了iainjmitchell的这篇优秀文章

//由于调用 提供默认值时,客户端处于阻塞状态,不要在这里进行长时间的操作
public void providefaulture(异常错误,MessageVersion,ref Message msg)
{
//避免敏感信息泄漏,例如:数据库配置, 错误包含的错误信息应该记录到服务器的日志中,不能显示给客户端
//FaultException e=新的FaultException(123,error.Message);
DateTime now=DateTime.now;
time=now.ToString(“yyyymmddhhmmssff”,DateTimeFormatInfo.InvariantInfo);/“+now.Year.ToString()+now.Month.ToString()+now.Day.ToString()+now.Hour.ToString()+now.Minute.ToString()+now.Second.ToString()+now.millis秒.ToString();
字符串errorMsg=”服务内部错误_" + 时间
//FaultException fe=新的FaultException(errorMsg);
//MessageFault mf=fe.CreateMessageFault();
//msg=Message.CreateMessage(版本、mf、fe.Action);
//要返回的错误
msg=Message.CreateMessage(版本,”,errorMsg,新的DataContractJsonSerializer(类型(字符串));
//告诉WCF使用JSON编码而不是默认的XML
WebBodyFormatMessageProperty wbf=新的WebBodyFormatMessageProperty(WebContentFormat.Json);
//将格式化程序添加到错误中
msg.Properties.Add(WebBodyFormatMessageProperty.Name,wbf);
//修改响应
HttpResponseMessageProperty rmp=新的HttpResponseMessageProperty();
//返回自定义错误代码400。
rmp.StatusCode=System.Net.HttpStatusCode.InternalServerError;
rmp.StatusDescription=“错误请求”;
//标记jsonerror和json内容
rmp.Headers[HttpResponseHeader.ContentType]=“应用程序/json”;
rmp.Headers[“jsonerror”]=“true”;
//推诿
msg.Properties.Add(HttpResponseMessageProperty.Name,rmp);
}

谢谢,可能需要做一些类似的事情-但看起来他们正在捕获任何旧的.net异常并将其转换为JSON-我的异常是正确的FaultException,我希望配置能够定义它们的返回方式,在本例中为JSON,但它可能被部署到需要xml的地方-我想我也可以进行编码,但它看到了ms表示,我缺少了一些简单的东西,可以使WCF按我需要的方式运行-再次感谢链接作为错误返回给客户端-只是序列化为Xml。此外,我不确定您提到的推测位是否发生了错误,但是,如果发生了,那么它会返回吗?Ta无论如何,这是为了测试,我将通过预期d在函数中键入。WebRequest的行为类似于JSON客户端。我再次检查了该属性。该属性在.Net 4.0中受支持。是否使用4.0?并尝试抛出“WebFaultException”而不是FaultExc
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
}
 <behavior name="ExtendedJSONBehavior">
     <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="false"/>
 </behavior>
//由于调用 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);
}