使用 Elmah 处理 Web 服务中的异常

34

在常规的ASP.NET Web Service (asmx)中是否有像在ASP.NET网站中使用ELMAH一样全局处理异常的方法?

3个回答

25

ASP.NET Web服务不会触发 Application_Error 事件,也不能像在ASP.NET应用程序中那样全局处理异常。但我们可以使用ELMAH "手动"记录异常:


public int WebServiceMethod() {
  try {
   ...
  }
  catch (Exception ex) {
    Elmah.ErrorLog.GetDefault(
      HttpContext.Current).Log(new Elmah.Error(ex, HttpContext.Current));
  }
}


这正是我所想的,但我正在检查是否有更“简洁”的解决方案。谢谢。 - mberube.Net
是的,对我来说,更干净的解决方案或实践也很有趣。这是个好问题(+1)。 - Tadas Šukys
我最终使用了你的解决方案,我没有找到更好的方法来做这件事。感谢你的提示。 - mberube.Net
3
请使用 Elmah.ErrorSignal.FromCurrentContext().Raise(ex); 触发所有已订阅/配置的日志类型/过滤器。 - Steven Quick
FromCurrentContext()是更好的解决方案,我在2012年2月22日发布了相关答案。不知何故,它在同一天被删除了。如果有任何高声望用户访问,请检查我的答案,并根据需要投票以进行未删除操作。 - Stephen Kennedy

23
您可以使用SoapExtension来实现这个功能:
using System;
using System.Web.Services.Protocols;

namespace MyNamespace
{
    class ELMAHExtension : SoapExtension
    {
        public override object GetInitializer(Type serviceType)
        { return null; }

        public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
        { return null; }

        public override void Initialize(object initializer)
        { }

        public override void ProcessMessage(SoapMessage message)
        {
            if (message.Stage == SoapMessageStage.AfterSerialize &&
                message.Exception != null)
            {
                // Log exception here
            }
        }
    }
}

你可以通过以下代码在web.config文件中注册它:

<system.web>
  <webServices>
    <soapExtensionTypes>
      <add type="MyNamespace.ELMAHExtension, MyDLL" priority="1" group="1" />
    </soapExtensionTypes>
  </webServices>
</system.web>

这将为您提供访问HttpContext和SoapMessage对象的权限,这些对象应该为您提供有关所调用内容的所有细节。我认为您在此阶段检索到的异常始终将是SoapException,并且您感兴趣的部分可能是内部异常。


1
我还没有尝试过这个,但是它“看起来”应该可以工作。在代码中的“log exception here”处,使用Elmah.ErrorLog.GetDefault(HttpContext.Current).Log(new Elmah.Error(ex, HttpContext.Current));可能会解决问题。 - codeulike
@DavidRobbins 没有,但我看不出为什么它不能同样工作。 - avesse
不幸的是,这种方法无法与ScriptService/JSON一起使用(http://stackoverflow.com/a/9585721/198065) - Regin Larsen
“group="1"”是有效的吗?Intellisense建议您需要“Low”或“High”。 - NickG
这确实有效!我通过将以下行添加到ProcessMessage函数中使其工作: Elmah.ErrorSignal.FromCurrentContext().Raise(message.Exception); 但请记住,在使用asmx服务的默认测试接口(带有调用按钮的接口)时,它不起作用。我在某个地方读到过,原因是该接口使用HTTP而不是SOAP,因此当从接口调用方法时,soapExtensions未加载。但我不是很确定。 - emregon
1
也许我错了,但我认为这仅适用于对另一个 Web 服务的调用,而不适用于我的内部未处理错误。 - fabriciorissetto

0

你可以使用这段代码

 try{
// your code in here
}
     catch (Exception ert)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ert);

            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接