简短版本: 在启用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是直接使用。FaultException提供FaultCode,而其他异常则以Faultcode -1威胁为未知。
JsonError
DataContractJsonSerializer
Exception.Message
FaultException是使用HTTP状态代码400发送的,其他异常是HTTP代码500-内部服务器错误。这不是必需的,因为故障代码可用于确定它是否是未知错误。但是在我的应用程序中很方便。
错误处理程序
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, "", msErrObject, 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 }
用于安装上述错误处理程序的Web行为
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>