从启用 AJAX 的 WCF 服务返回错误详细信息 [英] Returning Error Details from AJAX-Enabled WCF Service

查看:19
本文介绍了从启用 AJAX 的 WCF 服务返回错误详细信息的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简短版本:当在启用 AJAX 的 WCF 服务中抛出异常时,是否有/什么建议的方法可以将错误详细信息返回给客户端(除了只是打开门和发回所有异常详细信息)?

Short Version: Is there a/what is the suggested way to return error details to the client when an exception is thrown in an AJAX-Enabled WCF Service (aside from just throwing the gates open and sending back all of the exception details)?

长版:

我有一个相对简单的支持 AJAX 的 WCF 服务,我使用默认服务代理从客户端调用它.我在下面提供了代码片段,但我认为代码本身没有任何问题.

I've got a relatively simple AJAX-enabled WCF service that I'm calling from the client using the default service proxy. I've provided code snippets below, but I do not believe there is anything wrong with the code per se.

我的问题是,如果我在服务中抛出异常,返回给客户端的错误对象总是泛型的:

My problem is that if I throw an exception in the service, the error object returned to the client is always generic:

{
    "ExceptionDetail":null,
    "ExceptionType":null,
    "Message":"The server was unable to process the request..."
    "StackTrace":null
}

理想情况下,我希望根据出错的原因在客户端上显示不同的错误消息.

Ideally I would like to display different error messages on the client depending on what went wrong.

一个选项是允许 WCF 错误中的异常,这将为我提供完整的堆栈跟踪和所有内容,但我很欣赏这方面的安全问题,实际上这比我需要的信息多得多.我可以通过发回描述问题的字符串或其他东西来凑合,但我看不出有什么方法可以做到这一点.

One option is to allow exceptions in WCF faults, which would provide me with the full stack trace and everything, but I appreciate the security concerns with this, and that's actually a lot more information than I need. I could make do with just being able to send back a string describing the problem or something, but I don't see a way to do this.

我的服务代码:

[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"只是一个通用的错误处理方法,将显示有关错误的详细信息.

where "HandleError" is just a generic error handling method that would display details about the error.

推荐答案

使用适当的自定义 json 错误处理程序更新了帖子

Updated the post with a proper custom json error handler

<serviceDebug includeExceptionDetailInFaults="true"/>

在您的服务行为中,您将获得所需的所有详细信息.

In Your service behavior will give you all the details you need.

来自应用程序的所有异常都转换为 JsonError 并使用 DataContractJsonSerializer 进行序列化.Exception.Message 直接使用.FaultExceptions 提供 FaultCode,其他异常以错误代码 -1 威胁为未知.

All exceptions from the application are converted to an JsonError and serialized using a DataContractJsonSerializer. The Exception.Message is used directly. FaultExceptions provide the FaultCode and other exception are threated as unknown with faultcode -1.

FaultException 以 HTTP 状态代码 400 发送,其他异常为 HTTP 代码 500 - 内部服务器错误.这不是必需的,因为故障代码可用于确定它是否是未知错误.但是在我的应用程序中很方便.

FaultException are sent with HTTP status code 400 and other exceptions are HTTP code 500 - internal server error. This not nescessary as the faultcode can be used to decide if it is and unknown error. It was however convenient in my app.

错误处理程序

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
}

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错误格式.在此处添加属性以更改错误格式.

Specifies the json error format. Add properties here to change the error format.

[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> 

这篇关于从启用 AJAX 的 WCF 服务返回错误详细信息的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆