在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
ELMAH(The Error Logging Modules And Handlers)错误日志模块和处理,它提供了一个用于集中记录和通知错误日志的机制。 一、添加程序集引用 打开VS2012新建一个asp.net mvc 4 web应用程序项目。右键项目【管理NuGet程序包】,搜索ELMAH如图: 注意:要选择“Elmah.MVC”然后安装,第一个“ELMAH”只是在传统的webform中用到的。 二、配置web.config 安装完成之后在配置文件中会自动添加一些配置项目: <configSections>节中添加 <sectionGroup name="elmah"> <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" /> <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" /> <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" /> <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" /> </sectionGroup>
<appSettings>节中添加 <add key="elmah.mvc.disableHandler" value="false" /> <add key="elmah.mvc.disableHandleErrorFilter" value="false" /> <add key="elmah.mvc.requiresAuthentication" value="false" /> <add key="elmah.mvc.allowedRoles" value="*" /> <add key="elmah.mvc.route" value="elmah" />
<system.web>节中添加 <httpModules> <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" /> <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" /> <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" /> </httpModules>
<system.webServer>节中添加 <modules runAllManagedModulesForAllRequests="true"> <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" /> <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" /> <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" /> </modules> <handlers> <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" /> <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" /> <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" /> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> </handlers>
<elmah>节,注意,这个地方要修改为日志保存方式为 Sql server 数据库,连接字符串为 DefaultConnection, <elmah> <security allowRemoteAccess="false" /> <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="DefaultConnection" /> </elmah> <connectionStrings>
手动添加以下代码 <location path="elmah.axd" inheritInChildApplications="false"> <system.web> <httpHandlers> <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" /> </httpHandlers> </system.web> <system.webServer> <handlers> <add name="ELMAH" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" /> </handlers> </system.webServer> </location>
Web.config 修改完毕 三、配置数据库表 如果配置为数据库保存日志记录,则需要配置数据库的表和存储过程,代码如下:
View Code
/* 错误管理工具 SQL代码 */ CREATE TABLE dbo.ELMAH_Error ( ErrorId UNIQUEIDENTIFIER NOT NULL, Application NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, Host NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, Type NVARCHAR(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, Source NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, Message NVARCHAR(500) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [User] NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, StatusCode INT NOT NULL, TimeUtc DATETIME NOT NULL, Sequence INT IDENTITY (1, 1) NOT NULL, AllXml NTEXT COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO /*创建主键 */ ALTER TABLE dbo.ELMAH_Error WITH NOCHECK ADD CONSTRAINT PK_ELMAH_Error PRIMARY KEY NONCLUSTERED ( ErrorId ) ON [PRIMARY] GO /*创建默认约束 */ ALTER TABLE dbo.ELMAH_Error ADD CONSTRAINT DF_ELMAH_Error_ErrorId DEFAULT (newid()) FOR [ErrorId] GO /*创建非聚集索引 */ CREATE NONCLUSTERED INDEX IX_ELMAH_Error_App_Time_Seq ON dbo.ELMAH_Error ( [Application] ASC, [TimeUtc] DESC, [Sequence] DESC ) ON [PRIMARY] GO SET QUOTED_IDENTIFIER ON GO SET ANSI_NULLS ON GO /*创建存储过程,得到单个错误xml */ CREATE PROCEDURE dbo.ELMAH_GetErrorXml ( @Application NVARCHAR(60), @ErrorId UNIQUEIDENTIFIER ) AS SET NOCOUNT ON SELECT AllXml FROM ELMAH_Error WHERE ErrorId = @ErrorId AND Application = @Application GO SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO /*创建存储过程,得到错误总记录*/ SET QUOTED_IDENTIFIER ON GO SET ANSI_NULLS ON GO CREATE PROCEDURE dbo.ELMAH_GetErrorsXml ( @Application NVARCHAR(60), @PageIndex INT = 0, @PageSize INT = 15, @TotalCount INT OUTPUT ) AS SET NOCOUNT ON DECLARE @FirstTimeUTC DateTime DECLARE @FirstSequence int DECLARE @StartRow int DECLARE @StartRowIndex int -- Get the ID of the first error for the requested page SET @StartRowIndex = @PageIndex * @PageSize + 1 SET ROWCOUNT @StartRowIndex SELECT @FirstTimeUTC = TimeUTC, @FirstSequence = Sequence FROM ELMAH_Error WHERE Application = @Application ORDER BY TimeUTC DESC, Sequence DESC -- Now set the row count to the requested page size and get -- all records below it for the pertaining application. SET ROWCOUNT @PageSize SELECT @TotalCount = COUNT(1) FROM ELMAH_Error WHERE Application = @Application SELECT errorId, application, host, type, source, message, [user], statusCode, CONVERT(VARCHAR(50), TimeUtc, 126) + 'Z' time FROM ELMAH_Error error WHERE Application = @Application AND TimeUTC <= @FirstTimeUTC AND Sequence <= @FirstSequence ORDER BY TimeUTC DESC, Sequence DESC FOR XML AUTO GO SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO /*存储过程:插入数据 */ SET QUOTED_IDENTIFIER ON GO SET ANSI_NULLS ON GO CREATE PROCEDURE dbo.ELMAH_LogError ( @ErrorId UNIQUEIDENTIFIER, @Application NVARCHAR(60), @Host NVARCHAR(30), @Type NVARCHAR(100), @Source NVARCHAR(60), @Message NVARCHAR(500), @User NVARCHAR(50), @AllXml NTEXT, @StatusCode INT, @TimeUtc DATETIME ) AS SET NOCOUNT ON INSERT INTO ELMAH_Error ( ErrorId, Application, Host, Type, Source, Message, [User], AllXml, StatusCode, TimeUtc ) VALUES ( @ErrorId, @Application, @Host, @Type, @Source, @Message, @User, @AllXml, @StatusCode, @TimeUtc ) GO SET QUOTED_IDENTIFIER OFF GO SET ANSI_NULLS ON GO
在DefaultConnection配置的数据库中执行代码。 四、测试 1. 运行新建的asp.net mvc4 应用程序项目,正常运行显示页面“ 修改此模板中的代码以快速开始您的 ASP.NET Web API 开发。” 2.写一段错误的代码,在Controllers里面HomeController.cs 文件中加一段代码 public ActionResult Index() 然后执行,肯定会报错,你会看到 “/”应用程序中的服务器错误。输入字符串的格式不正确。 说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
3. 在地址栏输入 http://localhost:1702/elmah.axd 端口号自己改,会看到以下页面 OK,成功了! 4. 还没完,还没有在WebApi中测试呢,打开默认的ValuesController.cs 这是一个ApiController,通常情况下我们是用jquery 异步方式调用ApiController的。 在ValuesController.cs修改Get()方法,让他发出错误: // GET api/values/5 public string Get(int id) { int k = 0; int i = 2/k; return "value"; }
然后用javascript 调用这个方法,在View/homn/index.cshtml文件最后加上js代码: <div><input type="button" value="测试" onclick="test()" /> </div>
然后编译运行,要去掉之前测试HomeController.cs 中的错误代码,要不然运行不了。 点击“测试”按钮无反应,用firebug查看有错误信息,再在浏览器中 http://localhost:1702/elmah.axd 查看,但是发现没有记录到错误信息,为什么? 这就是开头说的要添加ELMAH.MVC而不是ELMAH,在WebApi中还要做另外的工作。 在App_Start文件夹中添加 ElmahErrorAttribute.cs类,代码: public class ElmahErrorAttribute :System.Web.Http.Filters.ExceptionFilterAttribute { public override void OnException(System.Web.Http.Filters.HttpActionExecutedContext actionExecutedContext) { if (actionExecutedContext.Exception != null) { Elmah.ErrorSignal.FromCurrentContext().Raise(actionExecutedContext.Exception); } base.OnException(actionExecutedContext); } }
然后在 Global.asax 文件Application_Start方法中添加一句:GlobalConfiguration.Configuration.Filters.Add(new ElmahErrorAttribute()); protected void Application_Start() { AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); BundleConfig.RegisterBundles(BundleTable.Bundles); GlobalConfiguration.Configuration.Filters.Add(new ElmahErrorAttribute()); }
然后再编译,运行点击“测试”,打开http://localhost:1702/elmah.axd,发现已经记录了错误信息。 五、注意事项和待解决问题 1.如果异常通过catch被捕获了就无法记录了,除非捕获后又throw。也就是在异常链上,最终的异常必须抛给了ASP.NET运行时,才可以被捕获。 2.ELMAH配置的数据库连接字符串无法加密,或者无法指定为加密了的connectionstring; 3.日志内容是增长的,但ELMAH没有提供清空日志的功能; 4.http://localhost:1702/elmah.axd 访问权限问题,在后续文章中阐述。
|
请发表评论