首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >全局记录来自ASP.NET [ScriptService]服务的异常

全局记录来自ASP.NET [ScriptService]服务的异常
EN

Stack Overflow用户
提问于 2009-01-24 00:30:30
回答 4查看 7.1K关注 0票数 14

我使用System.Web.Script.Services.ScriptService标签来使用可从客户端javascript调用的web服务。我需要的是一种全局记录这些方法中任何未处理的异常的方法。在客户端,我得到了错误回调,可以从那里继续,但我需要一个服务器端捕获来记录异常。

这个url上的人:http://ayende.com/Blog/archive/2008/01/06/ASP.Net-Ajax-Error-Handling-and-WTF.aspx

表明这是不可能做到的。

这是准确的吗?我真的需要访问整个系统中的每一个webmethod,并尝试/捕获整个方法吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-02-15 20:28:16

您可以使用HTTP模块来捕获由web服务方法抛出的异常消息、堆栈跟踪和异常类型。

首先是一些背景知识。

  • 如果web服务方法抛出异常,则

响应的状态代码为500。

  • 如果自定义错误处于关闭状态,则web服务将以JSON的形式向客户端返回异常消息和堆栈跟踪。例如:

{"Message":"Exception message","StackTrace":" at WebApplication.HelloService.HelloWorld() in C:\Projects\Stackoverflow Examples\WebApplication\WebApplication\HelloService.asmx.cs:line 22","ExceptionType":"System.ApplicationException"}

  • When自定义错误打开后,web服务将向客户端返回默认消息,并删除堆栈跟踪和异常类型:

{"Message":"There was an error processing the request.","StackTrace":"","ExceptionType":""}

因此,我们需要为web服务设置自定义错误,并插入一个HTTP模块,该模块:

如果抛出异常,

  1. 将检查请求是否针对web服务method
  2. Checks -即,如果1)和2)为真,则返回状态代码500
  3. ,然后获取将发送到客户端的原始JSON,并将其替换为默认的JSON

下面的代码是执行此操作的HTTP模块的示例:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Web;

public class ErrorHandlerModule : IHttpModule {

  public void Init(HttpApplication context) {
    context.PostRequestHandlerExecute += OnPostRequestHandlerExecute;
    context.EndRequest += OnEndRequest;
  }

  static void OnPostRequestHandlerExecute(object sender, EventArgs e) {
    HttpApplication context = (HttpApplication) sender;
    // TODO: Update with the correct check for your application
    if (context.Request.Path.StartsWith("/HelloService.asmx") 
        && context.Response.StatusCode == 500) {
      context.Response.Filter = 
        new ErrorHandlerFilter(context.Response.Filter);
      context.EndRequest += OnEndRequest;
    }
  }

  static void OnEndRequest(object sender, EventArgs e) {
    HttpApplication context = (HttpApplication) sender;
    ErrorHandlerFilter errorHandlerFilter = 
      context.Response.Filter as ErrorHandlerFilter;
    if (errorHandlerFilter == null) {
      return;
    }

    string originalContent =
      Encoding.UTF8.GetString(
        errorHandlerFilter.OriginalBytesWritten.ToArray());

    // If customErrors are Off then originalContent will contain JSON with
    // the original exception message, stack trace and exception type.

    // TODO: log the exception
  }

  public void Dispose() { }
}

此模块使用以下过滤器覆盖发送到客户端的内容,并存储原始字节(包含异常消息、堆栈跟踪和异常类型):

代码语言:javascript
复制
public class ErrorHandlerFilter : Stream {

  private readonly Stream _responseFilter;

  public List OriginalBytesWritten { get; private set; }

  private const string Content = 
    "{\"Message\":\"There was an error processing the request.\"" +
    ",\"StackTrace\":\"\",\"ExceptionType\":\"\"}";

  public ErrorHandlerFilter(Stream responseFilter) {
    _responseFilter = responseFilter;
    OriginalBytesWritten = new List();
  }

  public override void Flush() {
    byte[] bytes = Encoding.UTF8.GetBytes(Content);
    _responseFilter.Write(bytes, 0, bytes.Length);
    _responseFilter.Flush();
  }

  public override long Seek(long offset, SeekOrigin origin) {
    return _responseFilter.Seek(offset, origin);
  }

  public override void SetLength(long value) {
    _responseFilter.SetLength(value);
  }

  public override int Read(byte[] buffer, int offset, int count) {
    return _responseFilter.Read(buffer, offset, count);
  }

  public override void Write(byte[] buffer, int offset, int count) {
    for (int i = offset; i < offset + count; i++) {
      OriginalBytesWritten.Add(buffer[i]);
    }
  }

  public override bool CanRead {
    get { return _responseFilter.CanRead; }
  }

  public override bool CanSeek {
    get { return _responseFilter.CanSeek; }
  }

  public override bool CanWrite {
    get { return _responseFilter.CanWrite; }
  }

  public override long Length {
    get { return _responseFilter.Length; }
  }

  public override long Position {
    get { return _responseFilter.Position; }
    set { _responseFilter.Position = value; }
  }
}

此方法要求关闭web服务的自定义错误。您可能希望为应用程序的其余部分保留自定义错误,以便将web服务放在一个子目录中。只能使用覆盖父设置的web.config关闭该目录中的自定义错误。

票数 15
EN

Stack Overflow用户

发布于 2012-12-14 21:24:29

您可以在后端运行存储过程。然后,对于单个变量,它返回一个以上的值。正因为如此,冲突才会发生,并抛出此错误。

票数 3
EN

Stack Overflow用户

发布于 2009-02-19 07:48:25

我知道这不能回答每个人的问题,但我前段时间自己去寻找答案,结果空手而归。最终将每个web服务调用包装在try/catch中,catch调用我们的错误记录器。很糟糕,但很管用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/475189

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档