【问题标题】:Elmah logging using IErrorHandler does not work when implemented in non WCF project在非 WCF 项目中实施时,使用 IErrorHandler 进行 Elmah 日志记录不起作用
【发布时间】:2017-10-24 08:29:59
【问题描述】:

我正在尝试使用实现 IErrorHandler 来向 elmah 发出信号以记录未处理的异常。

我的解决方案中有多个项目。我有一个实用程序项目,我在其中实现了 IErrorHandler。

public abstract class BaseWebServiceErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error)
    {
        return false;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        if (error == null) return;

        if (System.Web.HttpContext.Current == null)
        {
            ErrorLog.GetDefault(null).Log(new Error(error));
        }
        else
        {
            ErrorSignal.FromCurrentContext().Raise(error);
        }
    }
}

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)
    {
        var errorHandler = (IErrorHandler)Activator.CreateInstance(errorHandlerType);
        foreach (var channelDispatcherBase in serviceHostBase.ChannelDispatchers)
        {
            var channelDispatcher = channelDispatcherBase as ChannelDispatcher;
            channelDispatcher?.ErrorHandlers.Add(errorHandler);
        }
    }
}

在一个 WCF 项目中,我有一个 BaseWebService 类,我试图在其中使用服务行为属性

[ServiceErrorBehaviour(typeof(WebServiceErrorHandler))]
public abstract class BaseWebService : AbstractWebService
{
    public BaseWebService()
    {
        //Code logic
    }
}

public class WebServiceErrorHandler : BaseWebServiceErrorHandler
{
}

现在使用上面的代码,当发生未处理的异常时,我收到服务行为不匹配的错误。

但是当我在我的 BaseWebService 中定义了 IErrorHandler 时,它自己就可以工作了。

[ServiceErrorBehaviour(typeof(WebServiceErrorHandler))]
public abstract class BaseWebService : AbstractWebService
{
    public BaseWebService()
    {
        //Codelogic
    }
}

//public class WebServiceErrorHandler : BaseWebServiceErrorHandler
//{
//}

public class WebServiceErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error)
    {
        return false;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        if (error == null) return;

        if (System.Web.HttpContext.Current == null)
        {
            ErrorLog.GetDefault(null).Log(new Error(error));
        }
        else
        {
            ErrorSignal.FromCurrentContext().Raise(error);
        }
    }
}

通过上述实现,它运行良好,并且也可以登录 Elmah。

我是否缺少实用程序项目中的一些参考资料? 感谢您的建议。

【问题讨论】:

  • 我写了这个指南:Logging to ELMAH from WCF 这可能会有所帮助。没有将此作为答案发布,因为我从未使用基类对此进行过测试。
  • @ThomasArdal 我做了一个类似的实现,但不知道为什么它不能像你说的那样与基类一起工作。

标签: c# wcf visual-studio-2015 projects-and-solutions elmah


【解决方案1】:

我刚刚使用这篇文章中的代码进行了测试:Logging to ELMAH from WCF

我有两个项目包含以下文件:

  • WcfService2
    • BaseService.cs
    • IService1.cs
    • Service1.svc.cs
  • 实用程序
    • HttpErrorHandler.cs

WcfService2 和 Utils 都引用 System.ServiceModel.dll、System.ServiceModel.Web.dll 和 Elmah.dll

这是HttpErrorHandler中的内容:

using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace Utils
{
    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.
            {
                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 serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints,
            BindingParameterCollection bindingParameters)
        {
        }

        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);
            }
        }
    }
}

BaseService.cs:

using Utils;

namespace WcfService2
{
    [ServiceErrorBehaviour(typeof(HttpErrorHandler))]
    public class BaseService
    {
    }
}

最后是 Service1.svc.cs:

namespace WcfService2
{
    public class Service1 : BaseService, IService1
    {
        public string GetData(int value)
        {
            var d = 100/value;
            return string.Format("You entered: {0}", value);
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-27
    相关资源
    最近更新 更多