我们使用优秀的ELMAH来处理ASP中未处理的异常.NET3.5Web应用程序.除了使用REST功能使用的WCF服务外,这对所有网站都非常有效.当操作方法中出现应用程序代码无法处理的异常时,WCF会根据服务契约和配置设置以各种方式处理该异常.这意味着异常最终不会触发ASP.NET HttpApplication.ELMAH使用的错误事件.我所知道的两种解决方案是:

The first option is extremely simple but is not exactly DRY. The second option only requires you to decorate each service with the custom attribute after implementing the attribute and the ErrorHandler. I have done this based on Will's work but I want to verify that this is the correct approach before posting the code.

Is there a better way that I have missed?

MSDN documenation for IErrorHandler表示HandleError方法是进行日志(log)记录的地方,但ELMAH访问HttpContext.现在的ApplicationInstance,即使在HttpContext中也是空的.有电流可用.在providDefault方法中调用Elmah是一种变通方法,因为设置了ApplicationInstance,但这与API文档中描述的意图不符.Am I missing something here?文档确实指出,您不应该依赖操作线程上调用的HandleError方法,这可能是ApplicationInstance在此范围内为null的原因.

推荐答案

我博客文章中的解决方案(在OP中引用)基于一个现有的解决方案,我们曾/正在使用该解决方案在错误状态下更改HTTP响应代码.

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

供后人/参考,以及潜在的改进——以下是当前解决方案的代码.

HttpErrorHandler和ServiceErrorBehaviourAttribute类

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

用法示例

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

[ServiceContract(Namespace = "http://example.com/api/v1.0/")]
[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class MyServiceService
{
  // ...
}

Asp.net相关问答推荐

从组件属性调用异步方法的正确方法

Web 部署工具 2.1 和 Web 部署 3.5 有什么区别?从 VS 2010 部署需要哪一个?

逐步 ASP.NET 自动构建/部署

如何在 IIS 上配置 Web Deploy 发布功能,以便开发人员可以发布?

如何在没有 Select 按钮的情况下在 GridView 中实现全行 Select ?

将 NUnit 添加到 ASP.NET MVC 测试框架的选项中

AppendHeader 是否与 AddHeader 完全相同?

即使使用正确的 Accepts 标头,WebAPI 也不会返回 XML

异步编程与线程有什么不同?

我可以在 Visual Studio 2010 中将任务列表项添加到 csHTML 吗?

如何将 global.asax 文件添加到 ASP.NET MVC4 项目?

为什么aspx文件会返回404(找不到页面)

以编程方式从后面的代码中关闭 aspx 页面

使用 Asp.Net MVC 和 Web Api 配置 Ninject

使用 Ninject OWIN 中间件在 OWIN 启动中注入 UserStore

应该如何使用 RedirectToRoute?

ASP.NET MVC 2.0 JsonRequestBehavior 全局设置

在 ASP.NET 中使用 MasterPages 时使用 JQuery 的正确方法?

GridView 按代码隐藏列

无法使用 ip:port 访问 WEB API,但可以在 VS 调试模式下使用 localhost:port