首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用ELMAH的WCF服务的异常日志记录

使用ELMAH的WCF服务的异常日志记录
EN

Stack Overflow用户
提问于 2009-05-22 00:11:38
回答 6查看 19.6K关注 0票数 62

我们正在使用优秀的ELMAH来处理ASP.NET 3.5Web应用程序中未处理的异常。除了使用REST功能使用的WCF服务之外,这对所有站点都非常有效。当操作方法中发生应用程序代码未处理的异常时,WCF将根据服务契约和配置设置以各种方式处理它。这意味着异常不会触发ELMAH使用的ASP.NET HttpApplication.Error事件。我知道处理这个问题的两个解决方案是:

try catch(Exception ex) { Elmah.ErrorSignal.FromCurrentContext().Raise(ex);

  • ;}将所有方法调用包装在try{} catch (Exception Ex){ ErrorHandler.

  • ;}中,以在catch块中显式调用Elmah。

第一个选项非常简单,但并不完全是DRY。第二种选择只需要您在实现自定义属性和ErrorHandler之后使用自定义属性来装饰每个服务。我已经基于Will's工作做到了这一点,但我想在发布代码之前验证这是正确的方法

有没有更好的方式让我错过了?

IErrorHandler的MSDN文档指出,HandleError方法是进行日志记录的地方,但是ELMAH访问该方法中的HttpContext.Current.ApplicationInstance,,而该方法中的null为null,即使ELMAH可用。在设置ApplicationInstance时,在ProvideFault方法中调用Elmah是一种变通方法,但这与API文档中描述的意图不匹配。我在这里漏掉了什么吗?文档指出,你不应该依赖于在操作线程上调用的HandleError方法,这可能是ApplicationInstance在这个作用域中为空的原因。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-05-25 12:11:15

我的博客文章中的解决方案(在OP中引用)是基于我们在错误状态期间用来更改HTTP响应代码的现有解决方案。

因此,对于我们来说,将异常传递给ELMAH只需要一行代码。如果有更好的解决方案,我也很想知道。

对于后代/参考,和潜在的改进-这里是来自当前解决方案的代码。

HttpErrorHandler和ServiceErrorBehaviourAttribute类

代码语言:javascript
复制
using System;
using System.ServiceModel;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Collections.ObjectModel;
using System.Net;
using System.Web;
using Elmah;
namespace YourApplication
{
    /// <summary>
    /// Your handler to actually tell ELMAH about the problem.
    /// </summary>
    public class HttpErrorHandler : IErrorHandler
    {
        public bool HandleError(Exception error)
        {
            return false;
        }

        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            if (error != null ) // Notify ELMAH of the exception.
            {
                if (System.Web.HttpContext.Current == null)
                    return;
                Elmah.ErrorSignal.FromCurrentContext().Raise(error);
            }
        }
    }
    /// <summary>
    /// So we can decorate Services with the [ServiceErrorBehaviour(typeof(HttpErrorHandler))]
    /// ...and errors reported to ELMAH
    /// </summary>
    public class ServiceErrorBehaviourAttribute : Attribute, IServiceBehavior
    {
        Type errorHandlerType;

        public ServiceErrorBehaviourAttribute(Type errorHandlerType)
        {
            this.errorHandlerType = errorHandlerType;
        }

        public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
        }

        public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
        {
            IErrorHandler errorHandler;
            errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
            foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers)
            {
                ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher;
                channelDispatcher.ErrorHandlers.Add(errorHandler);
            }
        }
    }
}

使用示例

使用ServiceErrorBehaviour属性装饰您的WCF服务:

代码语言:javascript
复制
[ServiceContract(Namespace = "http://example.com/api/v1.0/")]
[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class MyServiceService
{
  // ...
}
票数 88
EN

Stack Overflow用户

发布于 2011-06-17 21:42:38

在创建配置时,甚至可以使用BehaviorExtensionElement激活行为:

代码语言:javascript
复制
public class ErrorBehaviorExtensionElement : BehaviorExtensionElement
{
    public override Type BehaviorType
    {
        get { return typeof(ServiceErrorBehaviourAttribute); }
    }

    protected override object CreateBehavior()
    {
        return new ServiceErrorBehaviourAttribute(typeof(HttpErrorHandler));
    }
}

配置:

代码语言:javascript
复制
<system.serviceModel>
    <extensions>
      <behaviorExtensions>
        <add name="elmah" type="Namespace.ErrorBehaviorExtensionElement, YourAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
      </behaviorExtensions>
    </extensions>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <elmah />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

通过这种方式,还可以将ELMAH与RIA服务结合使用!

票数 9
EN

Stack Overflow用户

发布于 2013-12-06 00:47:14

这对一些人来说可能是显而易见的,但我只是花了相当长的时间试图弄清楚为什么我的HttpContext.Current是空的,尽管遵循了威尔·休斯的所有优秀答案。令人尴尬的是,我意识到这是因为我的WCF服务是由MSMQ消息激活的。

我最终重写了ProvideFault()方法:

代码语言:javascript
复制
if (HttpContext.Current == null)
{
    ErrorLog.GetDefault(null).Log(new Error(error));
}
else
{
    ErrorSignal.FromCurrentContext().Raise(error);
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/895901

复制
相关文章

相似问题

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