简短版本:在
AJAX启用的WCF服务中抛出异常(除了打开门并发回所有异常详细信息之外),是否有/有什么建议的方式将错误详细信息返回给客户端?
长版本:
我有一个相对简单的启用AJAX的WCF服务,我使用默认服务代理从客户端调用.我在下面提供了代码片段,但我不相信代码本身有什么问题.
我的问题是,如果我在服务中抛出异常,返回给客户端的错误对象总是通用的:
{
"ExceptionDetail":null,"ExceptionType":null,"Message":"The server was unable to process the request..."
"StackTrace":null
}
理想情况下,我想在客户端上显示不同的错误消息,具体取决于出错.
一个选择是允许在WCF故障中的异常,这将为我提供完整的堆栈跟踪和一切,但我感谢安全性的关注,这实际上比我需要更多的信息.我可以做的只是能够发回一个描述问题或某事的字符串,但我没有看到一种方法来做到这一点.
我的服务代码:
[ServiceContract(Namespace = "MyNamespace")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MyService
{
[OperationContract]
public void DoStuff(string param1,string etc)
{
//Do some stuff that maybe causes an exception
}
}
在客户端上
MyNamespace.MyService.DoStuff(
param1,etc,function() { alert("success"); },HandleError);
其中“HandleError”只是一个通用错误处理方法,将显示有关错误的详细信息.
解决方法
编辑:用适当的自定义json错误处理程序更新了该帖子
快速但非优先的方式.
<serviceDebug includeExceptionDetailInFaults="true"/>
在您的服务行为将给您所需的所有细节.
好的方式
应用程序的所有异常都将转换为JsonError并使用DataContractJsonSerializer进行序列化. Exception.Message直接使用. FaultExceptions提供了FaultCode,其他异常处理为未知的faultcode -1.
使用HTTP状态代码400发送FaultException,其他异常是HTTP代码500 – 内部服务器错误.这不是必需的,因为faultcode可以用来决定是否和未知的错误.这在我的应用程序是方便的
错误处理程序
internal class CustomErrorHandler : IErrorHandler
{
public bool HandleError(Exception error)
{
//Tell the system that we handle all errors here.
return true;
}
public void ProvideFault(Exception error,System.ServiceModel.Channels.MessageVersion version,ref System.ServiceModel.Channels.Message fault)
{
if (error is FaultException<int>)
{
FaultException<int> fe = (FaultException<int>)error;
//Detail for the returned value
int faultCode = fe.Detail;
string cause = fe.Message;
//The json serializable object
JsonError msErrObject = new JsonError { Message = cause,FaultCode = faultCode };
//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();
// return custom error code,400.
rmp.StatusCode = System.Net.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);
}
else
{
//Arbitraty error
JsonError msErrObject = new JsonError { Message = error.Message,FaultCode = -1};
// create a fault message containing our FaultContract object
fault = Message.CreateMessage(version,new DataContractJsonSerializer(msErrObject.GetType()));
// tell WCF to use JSON encoding rather than default XML
var wbf = new WebBodyFormatMessageProperty(WebContentFormat.Json);
fault.Properties.Add(WebBodyFormatMessageProperty.Name,wbf);
//Modify response
var rmp = new HttpResponseMessageProperty();
rmp.Headers[HttpResponseHeader.ContentType] = "application/json";
rmp.Headers["jsonerror"] = "true";
//Internal server error with exception mesasage as status.
rmp.StatusCode = System.Net.HttpStatusCode.InternalServerError;
rmp.StatusDescription = error.Message;
fault.Properties.Add(HttpResponseMessageProperty.Name,rmp);
}
}
#endregion
}
Webbehaviour用于安装上述错误处理程序
internal class AddErrorHandlerBehavior : WebHttpBehavior
{
protected override void AddServerErrorHandlers(ServiceEndpoint endpoint,EndpointDispatcher endpointDispatcher)
{
base.AddServerErrorHandlers(endpoint,endpointDispatcher);
//Remove all other error handlers
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Clear();
//Add our own
endpointDispatcher.ChannelDispatcher.ErrorHandlers.Add(new CustomErrorHandler());
}
}
json错误数据合同
指定json错误格式.
在此添加属性以更改错误格式.
[DataContractFormat]
public class JsonError
{
[DataMember]
public string Message { get; set; }
[DataMember]
public int FaultCode { get; set; }
}
使用错误处理程序
自托管
ServiceHost wsHost = new ServiceHost(new Webservice1(),new Uri("http://localhost/json"));
ServiceEndpoint wsEndpoint = wsHost.AddServiceEndpoint(typeof(IWebservice1),new WebHttpBinding(),string.Empty);
wsEndpoint.Behaviors.Add(new AddErrorHandlerBehavior());
App.config中
<extensions>
<behaviorExtensions>
<add name="errorHandler"
type="WcfServiceLibrary1.ErrorHandlerElement,WcfServiceLibrary1" />
</behaviorExtensions>
</extensions>
