【问题标题】:What is the equivalent to SoapExtension for JSON WebMethods?什么是 JSON WebMethods 的 SoapExtension 等价物?
【发布时间】:2012-03-06 11:44:44
【问题描述】:

我有一些网络方法用于调用一些外部服务,例如 Google 日历 API,显然这些方法非常脆弱。

不幸的是,我现在意识到在这些方法上引发的任何错误都不会导致异常冒泡到 Global.asax,这是在此应用程序中记录错误的地方。

我看到了将方法包装在 try/catch 中的建议,这是一种愚蠢的做法,因为 ASP.Net 仍然会默默吞下各种错误。

在尝试寻找解决方案时,我看到很多对 SoapExtension 的引用,这正是我想要做的,但在我返回 Json 时并没有被解雇。我真正想要的是一种捕捉错误的方法。

感谢任何指点,我仍然无法理解 ASP.Net 团队怎么会认为像这样默默地吞下错误是个好主意。

例如这样的方法:

    [WebMethod]
    [ExceptionHandling] //can I write a handler like this to catch exceptions from JSON webservices?
    static public void DeleteItem(string id)
    {
        var api = new GoogleCalendarAPI(User.InternalUser());
        api.DeleteEvent(id);
        return "success";
    }

【问题讨论】:

  • 您的问题是您使用的是旧版技术,而您应该使用 WCF。 WCF 比 ASMX 更可扩展
  • @JohnSaunders WCF 很糟糕,几年后就会像渡渡鸟一样死去,它本身就是遗产。如果我可以使用任何东西,我会选择 MVC,但可惜你不能在一夜之间重写客户的遗留项目
  • 异常处理程序只能捕获异常。如果异常被隐藏,则没有要处理的异常。
  • MVC 与 WCF 完全不同。 MVC 是关于将数据与表示分离。 WCF 是关于在端点之间发送数据。
  • @JohnSaunders Microsoft 技术的问题在于它们从不向后兼容。如果你必须使用 asmx 来维护一个带有 asmx 的旧项目,你应该迁移到 wcf 来记录错误:这是一场噩梦。

标签: c# asp.net


【解决方案1】:

对于 JSON WebMethods,没有等效于 SoapExtension 的方法,并且在您的生产站点中打开自定义错误将导致向客户端返回一般错误消息,服务器上不会出现任何错误。你无法绕过这一点。

如果您使用 ILSpy 之类的工具检查代码,则无法将方法或类传递给像 SoapExtension 这样的页面 WebMethods。 ASP.Net 在调用 web 方法时会吞下该错误,您将收到的唯一通知是发送给客户端的 HTTP 500 错误,其中包含一个通用错误消息。

在 4.0 中,WebMethods 被这样调用:

// System.Web.Script.Services.RestHandler
internal static void ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)
{
    try
    {
        //snip irrelevant code
        RestHandler.InvokeMethod(context, methodData, rawParams);
    }
    catch (Exception ex)
    {
        RestHandler.WriteExceptionJsonString(context, ex);
    }
}

因此,如果调用您的方法引发错误,它将调用 statusCode 为 500 的以下代码,那里没有重新抛出,也没有其他东西可以传入,所以除非我是盲目的,否则它只会被默默吞下.更糟糕的是,如果您打开了自定义错误,任何理智的人都会这样做,它会完全混淆最初的原因:

// System.Web.Script.Services.RestHandler
internal static void WriteExceptionJsonString(HttpContext context, Exception ex, int statusCode)
{
    //snip code setting up response
    context.Response.TrySkipIisCustomErrors = true;
    using (StreamWriter streamWriter = new StreamWriter(context.Response.OutputStream, new UTF8Encoding(false)))
    {
        if (ex is TargetInvocationException)
        {
            ex = ex.InnerException;
        }
        if (context.IsCustomErrorEnabled)
        {
            streamWriter.Write(JavaScriptSerializer.SerializeInternal(RestHandler.BuildWebServiceError(AtlasWeb.WebService_Error, string.Empty, string.Empty)));
        }
        else
        {
            streamWriter.Write(JavaScriptSerializer.SerializeInternal(RestHandler.BuildWebServiceError(ex.Message, ex.StackTrace, ex.GetType().FullName)));
        }
        streamWriter.Flush();
    }
}

我看不到解决办法,看起来 WebMethod 还没有准备好用于生产代码,太遗憾了。

【讨论】:

    【解决方案2】:

    与其说它们消失了,不如说它们被传递给调用客户端。但是,由于您并不总是希望(或应该)透露您的服务的此类私密细节,因此您可以防止错误从您的服务中冒出来。这给人一种他们正在消失的印象。

    将内部细节包装在 try-catch 中是处理任何错误的最佳方法。在您处理标准错误捕获的方法中。所以我想你会想要这样的东西:

    [WebMethod]
    static public string DeleteItem(string id)
    {
        try
        {
            var api = new GoogleCalendarAPI(User.InternalUser());
            api.DeleteEvent(id);
            return "success";
        }
        catch(Exception ex)
        {
            log.fatal(ex);
            return "error";
        }
    }
    

    如果任何东西在 try-catch 中抛出异常,它将被捕获。 ASP.Net 不会干扰它,除非您调用的方法已被专门编码。

    编辑

    如果 GoogleCalendarAPI 类依次调用方法,例如捕获异常的 ExecuteWebServiceCall,那么您必须解析响应。我希望他们能给你一些其他线索,比如响应代码,以指示错误状态。然后你可以将它包装在一个异常中,抛出它,让它被你的默认错误处理程序捕获。

    【讨论】:

    • 我特别说过我不想这样做。有很多方法无法捕获 WebMethod 上的严重错误。当您的 js 日历控件配置错误导致 DateTime 参数错误时怎么办?还是发生整数溢出?或者用户在响应中传递了一个“asp.net 禁止”字符?这不会抓住任何一个。这是一个糟糕的解决方案。
    • 它们都将被异常处理程序捕获。为什么你认为他们不会被抓住?从您的示例中,DateTime 解析将引发 FormatException,该异常将被捕获。 int 将抛出一个被捕获的溢出异常。如果代码抛出异常,那么它将被捕获。 ASP.net 在这个阶段不能干预它,因为它还不知道异常已经发生。在将异常传递出方法之前,它不会知道发生了异常。
    • 如何干扰?异常会在调用堆栈中冒泡,直到它被处理。 Asp.net 受与框架其余部分相同的异常处理规则的约束。我想我们在这里谈论的是不同的事情。我的回答并不愚蠢,只是不是你想要的,因为你已经证明异常被捕获,所以你需要一个异常处理的替代方法。
    • 我支持 d/v。您不清楚自己要做什么,也没有给我机会解释或澄清,我相信您的回答没有用,因为不清楚这与您的问题有何关系。
    • 在问题中我特别说我不能使用 try...catch 这就是你的建议,你需要什么额外的说明?你的回答很烦人,因为你甚至没有费心去阅读这个问题。说真的,你的“被困”异常听起来很像我的“被默默吞下”的异常,不是吗?下次在 cmets 中要求澄清。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 2020-08-25
    • 2014-05-08
    • 2014-06-12
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    相关资源
    最近更新 更多