我正在运行一个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);
主机设置 - scrummy yum
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();
这是电话 - 腹部疼痛
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;
}
}
text var包含正确的错误,但序列化为Xml 我在这做错了什么?
答案 0 :(得分:3)
答案 1 :(得分:2)
我很乐意提出解决方案。 我有完全相同的问题,在我用我的端点行为配置搞砸了一点后,我发现了所需的配置元素。 解决方案是强制wcf使用所选格式(json):
<behavior name="ExtendedJSONBehavior">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="false"/>
</behavior>
如您所见,关键是“automaticFormatSelectionEnabled”属性。
再次与wcf玩得很开心
答案 2 :(得分:0)
这可能不会给你“为什么”部分。 看看this question。它允许您在故障作为响应出来之前抓取并重新格式化故障。至少Json-ize你的回答足以让你前进。 this背后也有类似的想法。
答案 3 :(得分:0)
根据MSDN documentation for DataContractJsonSerializer:
“如果在服务器上序列化传出回复期间发生错误,或者由于某些其他原因而回复操作引发异常,则可能不会将其作为错误返回给客户端。”
此外,这仅仅是猜测,但它几乎看起来像这个序列化程序序列化为XML,然后将其转换为JSON。那么当你的故障发生时,它会在进程中被中断吗?然后我又完全错了。
祝你好运。答案 4 :(得分: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
}
答案 5 :(得分: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);
}