【问题标题】:How do I handle a server side exception during an Ajax call from JQuery?如何在 JQuery 的 Ajax 调用期间处理服务器端异常?
【发布时间】:2009-11-02 22:02:29
【问题描述】:

我正在从 JQuery 调用页面方法,如下所述:http://encosia.com/2008/05/29/using-jquery-to-directly-call-aspnet-ajax-page-methods/

这一切都很好。在测试过程中,当我从 Web 方法得到的响应太大时,我遇到了一个错误: 使用 JSON JavaScriptSerializer 进行序列化或反序列化时出错。字符串长度超过 maxJsonLength 属性设置的值。

我能够对 maxJsonLength 属性进行一些研究并将其设置得更高,但是我想尝试在服务器端捕获此异常,然后在 Ajax 调用期间将其发送到客户端。我该怎么做呢?

我在我的方法中设置了一个 try/catch 块但无济于事,它发生在我的方法之外(在 JSON 序列化期间)。

StackTrace 看起来像这样:

在 System.Web.Script.Serialization.JavaScriptSerializer.Serialize(Object obj, StringBuilder output, SerializationFormat serializationFormat)
在 System.Web.Script.Serialization.JavaScriptSerializer.Serialize(对象 obj,SerializationFormat 序列化格式)
在 System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext 上下文,WebServiceMethodData 方法数据,IDictionary`2 rawParams)
在 System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)

更新
全局和页面级别的捕获对我不起作用(但此时可能会得到赏金。为非常特定于一个页面调用的东西维护全局异常似乎是一个糟糕的设计决策。)我想要抓住的重点例外情况是,我可以对文本进行中继,并且仍然对 javascript 调用做出有效响应。

【问题讨论】:

    标签: asp.net jquery ajax


    【解决方案1】:

    这可能是一项巨大的努力,但如果您想要一个设计良好的解决方案,我认为您最好的选择可能是创建一个扩展服务处理程序的类,实现您自己的自定义序列化程序,在哪里检查 maxJsonLength。然后,您可以设置您的 web.config 以让您自己的处理程序处理所有(或部分)asmx 请求。 Spring framework 似乎有助于实现这一点,尽管我还没有仔细研究过该解决方案。

    但请注意,在不破坏语法的情况下手动截断 JSON 字符串本身可能是一项艰巨的任务。

    另一个可能更容易实现并且仍然可以说非常简洁的解决方案是用您自己的函数覆盖(或包装)jQuery 的 $.ajax 函数,该函数将客户端上的 JSON 字符串化(这是无论如何都要完成,首先创建请求,所以它不应该有很多开销),并在那里检查长度。这种方法的好处是您不必费心扩展服务处理程序,而且截断对象的部分会更容易,因为您的 javascript 对象随时可用;你可以迭代它,对它的子集进行字符串化,检查它们的长度,或者使用你喜欢的任何机制来实现智能截断(显然 whatever 截断你想要使用的 JSON 的方法,你必须知道您的数据,以便能够在不破坏请求中的关键功能的情况下决定可以安全删除哪些内容)。

    如果无法截断,您可以选择显示错误消息,甚至无需访问服务器。

    由于 javascript 非常灵活,您可以指定$.ajaxCore = $.ajax,然后用您自己的函数覆盖$.ajax,该函数调用$.ajaxCore

    【讨论】:

    • 问题是太长的文本在服务器上被确定为太长,在我的方法运行之后,但在 ajax 有机会进行自己的截断之前。能够捕获错误的想法是我可以手动查看我正在发送的对象并截断错误的特定字段。
    • 哦,对不起,我把你误认为是传入请求的问题=/所以你的问题基本上是你返回一个对象,并且在你交出返回对象后代码失败了服务器序列化?那么,在这种情况下,如何在 try/catch 块中手动调用System.Web.Script.Services.JavaScriptSerializer.Serialize?我知道您当前的执行发生在您无法尝试/捕获它的地方,但不仅仅是return myObjectreturn getValidatedObject(myObject) 然后getValidatedObject 序列化,捕获异常并截断,并且...
    • ... 返回一个对象,该对象然后返回给服务处理程序,然后服务处理程序将再次序列化代码。这意味着将每个请求序列化两次,而不是一次,但至少它使您能够知道您返回的内容将被验证
    • 另外(对于咆哮感到抱歉),扩展服务处理程序的想法仍然是一个解决方案,只是它会反过来工作。扩展服务处理程序,映射 asmx 请求以处理它,以常规服务处理程序通常的方式调用它,但在您的方法返回一个对象后覆盖序列化部分,包括一个 try/catch 块,并执行必要的截断.我认为我之前的评论应该给你一个快速而肮脏的解决方案,而这个,一个适当但冗长的解决方案。
    【解决方案2】:

    也许How to: Handle Page-Level Errors 会有所帮助。

    【讨论】:

      【解决方案3】:

      您也可以尝试在您的应用中添加global exception handler

      【讨论】:

        【解决方案4】:

        在从方法返回之前自己计算对象大小。你不需要做精确的计算,只是一个估计就可以了。很可能获得可能很大的文本字段的大小就足够了(例如,对某物或 cmets 的描述)。

        如果结果大小大于某个限制,则截断数据。将 MaxJsonLength 设置为限制的两倍。

        【讨论】:

          【解决方案5】:

          如果您无法访问实际上引发异常以修复它的序列化程序的底层代码,也许custom error handlers 是一个选项?

          【讨论】:

            猜你喜欢
            • 2010-10-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-03-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多