gpt4 book ai didi

asp.net - 使用格式错误的 Json 调用 ASP.NET WebMethod 时捕获错误

转载 作者:行者123 更新时间:2023-12-03 14:46:39 28 4
gpt4 key购买 nike

我们有一个较旧的 ASP.NET WebForms 应用程序,它使用 jQuery $.ajax() 执行 AJAX 请求在客户端调用,调用页面代码隐藏中的静态方法,用 [WebMethod] 装饰属性。

如果 WebMethod 中发生未处理的异常,它不会触发 Application_Error事件,因此不会被我们的错误记录器(ELMAH)拾取。这是众所周知的,不是问题——我们将所有 WebMethod 代码包装在 try-catch block 中,异常情况被手动记录到 ELMAH。

但是,有一个案例让我难过。如果将格式错误的 Json 发布到 WebMethod URL,它会在输入我们的代码之前引发异常,我找不到任何方法来捕获它。

例如这个 WebMethod 签名

[WebMethod]
public static string LeWebMethod(string stringParam, int intParam)

通常使用 Json 有效负载调用,例如:
{"stringParam":"oh hai","intParam":37}

我尝试使用 Fiddler 将有效负载编辑为格式错误的 Json 进行测试:
{"stringParam":"oh hai","intPara

并得到以下 ArgumentException来自 JavaScriptObjectDeserializer 的错误响应发送到客户端(这是在本地运行的简单测试应用程序中,没有自定义错误):
{"Message":"Unterminated string passed in. (32): {\"stringParam\":\"oh hai\",\"intPara","StackTrace":"   at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeString()\r\n at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeMemberName()\r\n at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeDictionary(Int32 depth)\r\n at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at
System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize(String input, Int32 depthLimit, JavaScriptSerializer serializer)\r\n at
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n at
System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n at
System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer)\r\n at
System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext context)\r\n at
System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.ArgumentException"}

它仍然没有触发 Application_Error事件,它永远不会进入我们的代码,所以我们不能自己记录错误。

我发现了一个类似的问题,它得到了指向博客文章“ How to create a global exception handler for a Web Service”的指针,但这似乎只对 SOAP Web 服务有效,而不是 AJAX GET/POST。

在我的情况下是否有一些类似的方法可以附加自定义处理程序?

最佳答案

根据引用资料,内部 RestHandler.ExecuteWebServiceCall 方法捕获 GetRawParams 抛出的所有异常并简单地将它们写入响应流,这就是 Application_Error 的原因不被调用:

internal static void ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData) {
try {
...
IDictionary<string, object> rawParams = GetRawParams(methodData, context);
InvokeMethod(context, methodData, rawParams);
}
catch (Exception ex) {
WriteExceptionJsonString(context, ex);
}
}

我能想到的唯一解决方法是创建一个拦截并记录输出的输出过滤器:
public class PageMethodExceptionLogger : Stream
{
private readonly HttpResponse _response;
private readonly Stream _baseStream;
private readonly MemoryStream _capturedStream = new MemoryStream();

public PageMethodExceptionLogger(HttpResponse response)
{
_response = response;
_baseStream = response.Filter;
}

public override void Close()
{
if (_response.StatusCode == 500 && _response.Headers["jsonerror"] == "true")
{
_capturedStream.Position = 0;
string responseJson = new StreamReader(_capturedStream).ReadToEnd();
// TODO: Do the actual logging.
}

_baseStream.Close();
base.Close();
}

public override void Flush()
{
_baseStream.Flush();
}

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

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

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

public override void Write(byte[] buffer, int offset, int count)
{
_baseStream.Write(buffer, offset, count);
_capturedStream.Write(buffer, offset, count);
}

public override bool CanRead { get { return _baseStream.CanRead; } }
public override bool CanSeek { get { return _baseStream.CanSeek; } }
public override bool CanWrite { get { return _baseStream.CanWrite; } }
public override long Length { get { return _baseStream.Length; } }

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

在 Global.asax.cs(或 HTTP 模块)中,在 Application_PostMapRequestHandler 中安装过滤器:
protected void Application_PostMapRequestHandler(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
if (context.Handler is Page && !string.IsNullOrEmpty(context.Request.PathInfo))
{
string contentType = context.Request.ContentType.Split(';')[0];
if (contentType.Equals("application/json", StringComparison.OrdinalIgnoreCase))
{
context.Response.Filter = new PageMethodExceptionLogger(context.Response);
}
}
}

关于asp.net - 使用格式错误的 Json 调用 ASP.NET WebMethod 时捕获错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24054573/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com