گزارش گیری خطاها با استفاده از Elmah در MVC
سه شنبه 15 دی 1394در این مقاله قصد داریم نحوه استفاده از Elmah را به همراه یک نمونه شرح دهیم . Elmah یک کتابخانه رایگان است که برای ارائه گزارش از خطاهای وب سایتی که نوشته اید به شما کمک می کند .
Elmah خطاهای رخ داده در برنامه شما را گزارش می گیرد.کار با Elmah بسیار ساده است .باید آن را به طریقی به برنامه اضافه کنید .روش های مختلفی برای افزودن آن به برنامه وجود دارد که یکی از این روش ها می تواند افزودن Dll آن از پروژه ای دیگر باشد و یا اینکه از طریق NUGET آن را به برنامه خود اضافه کنید .
به هر حال پس از افزودن آن به پروژه ، فقط کافی است تا تغییرات کمی در Web.config بدهید .پس از راه اندازی Elmah می توانید از طریق آدرس Domain خود و سپس افزودن /Elmah.axd به صفحه ای بروید که خطا ها در آن نمایش داده می شود . Elmah این قابلیت را هم دارد که خطاها را برای شما ایمیل کند .
حال برای شروع کار ابتدا یک پروژه از نوع Asp.net MVC ایجاد می کنیم .
نوع این نمونه از نوع mvc است
بعد از ایجاد نمونه باید از طریق nugget امکان Elmah را اضافه کنیم .
حال در داخل web.config تغییرات زیر را در قسمت <system.web> </system.web> اعمال می کنیم .
<!--add this--> < httpHandlers > < add verb = "POST,GET,HEAD"path = "elmah.axd"type = "Elmah.ErrorLogPageFactory, Elmah" / > < /httpHandlers> <!--add this-->
و همچنین در قسمت <system.webServer></system.webServer> تغییرات زیر را انجام می دهیم
<!--add this--> < handlers > < add name = "Elmah"verb = "POST,GET,HEAD"path = "elmah.axd"type = "Elmah.ErrorLogPageFactory, Elmah" / > < /handlers> <!--add this-->
بعد از افزودن Elmah و اعمال برخی تغییرات در داخل web.congig لازم است که در دیتابیس به ساخت جدولی بپردازیم که خطاها در آن ذخیره شود .
اسکریپت ساخت جدول به صورت زیر است
CREATE TABLE[dbo].[ELMAH_Error] ( [ErrorId][uniqueidentifier] NOT NULL, [Application][nvarchar](60) NOT NULL, [Host][nvarchar](50) NOT NULL, [Type][nvarchar](100) NOT NULL, [Source][nvarchar](60) NOT NULL, [Message][nvarchar](500) NOT NULL, [User][nvarchar](50) NOT NULL, [StatusCode][int] NOT NULL, [TimeUtc][datetime] NOT NULL, [Sequence][int] IDENTITY(1, 1) NOT NULL, [AllXml][ntext] NOT NULL )
برای ذخیره اطلاعات در داخل این جدول روال هایی نوشته شده اند که در زیر می بینید
روال ذخیره شده و یا Stored Procedure مربوط به گرفتن همه خطا ها به صورت زیر است
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 SELECT @TotalCount = COUNT(1) FROM [ELMAH_Error] WHERE [Application] = @Application SET @StartRowIndex = @PageIndex * @PageSize + 1 IF @StartRowIndex <= @TotalCount BEGIN SET ROWCOUNT @StartRowIndex SELECT @FirstTimeUTC = [TimeUtc], @FirstSequence = [Sequence] FROM [ELMAH_Error] WHERE [Application] = @Application ORDER BY [TimeUtc] DESC, [Sequence] DESC END ELSE BEGIN SET @PageSize = 0 END SET ROWCOUNT @PageSize SELECT errorId = [ErrorId], application = [Application], host = [Host], type = [Type], source = [Source], message = [Message], [user] = [User], statusCode = [StatusCode], time = CONVERT(VARCHAR(50), [TimeUtc], 126) + 'Z' FROM [ELMAH_Error] error WHERE [Application] = @Application AND [TimeUtc] <= @FirstTimeUTC AND [Sequence] <= @FirstSequence ORDER BY [TimeUtc] DESC, [Sequence] DESC FOR XML AUTO
روال ذخیره شده برای دریافت یک خطای خاص به صورت زیر است
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
و در نهایت روال ذخیره شده در دیتابیس برای ذخیره خطا به صورت زیر است
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 )
بعد از اجرای اسکریپت های بالا شکل دیتابیس ما به صورت زیر خواهد بود
دوباره به فایل web.config برمی گریم و تغییر زیر را هم اعمال می کنیم .
</configuration> <elmah> <!--. If allowRemoteAccess value is set to 0, then the error log web page can only be viewed locally. If allowRemoteAccess attribute is set to 1 then the error log web page is enabled for both remote and local visitors.--> <!--add this--> <security allowRemoteAccess="0" /> <!-- DefaultConnection is the name of database connection string --> <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="DefaultConnection" /> <!--add this--> </elmah>
در داخل تگ Elmah تنظیمات مختلفی مانند اینکه آیا خطاها توسط کاربران راه دور مشاهده شود یا خیر وجود دارد.اینکه خطاها در کجا ذخیره شوند را هم در این تگ مشخص می کنیم .
شکل نهایی فایل web.config به صورت زیر است
<?xml version="1.0" encoding="utf-8"?> <!-- For more information on how to configure your ASP.NET application, please visit http://go.microsoft.com/fwlink/?LinkId=301880 --> <configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <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></configSections> <connectionStrings> <!--<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-MVCExceptionLog-20160102095730.mdf;Initial Catalog=aspnet-MVCExceptionLog-20160102095730;Integrated Security=True" providerName="System.Data.SqlClient" />--> <add name="DefaultConnection" connectionString="Data Source=.;Initial Catalog=ELMAH_Errore;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings> <appSettings> <add key="webpages:Version" value="3.0.0.0" /> <add key="webpages:Enabled" value="false" /> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> <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.IgnoreDefaultRoute" value="false" /><add key="elmah.mvc.allowedRoles" value="*" /><add key="elmah.mvc.allowedUsers" value="*" /><add key="elmah.mvc.route" value="elmah" /><add key="elmah.mvc.UserAuthCaseSensitive" value="true" /></appSettings> <system.web> <httpHandlers > <add verb = "POST,GET,HEAD" path ="elmah.axd" type ="Elmah.ErrorLogPageFactory, Elmah" /> </httpHandlers> <authentication mode="None" /> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5" /> <httpModules> <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" /> <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" /> <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" /> </httpModules></system.web> <system.webServer> <handlers > <add name = "Elmah" verb ="POST,GET,HEAD" path ="elmah.axd" type ="Elmah.ErrorLogPageFactory, Elmah" /> </handlers> <modules> <remove name="FormsAuthentication" /> <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> <validation validateIntegratedModeConfiguration="false" /></system.webServer> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" /> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework"> <parameters> <parameter value="mssqllocaldb" /> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework> <elmah> <security allowRemoteAccess="0" /> <!-- DefaultConnection is the name of database connection string --> <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="DefaultConnection" /> </elmah> </configuration>
حال به صورت عمد در داخل کنترلر مربوط به Home و در داخل Action به نام contact یک کد اشتباه می نویسیم تا خطا تولید کند .کد کنترلر به صورت زیر است
public ActionResult Index() { return View(); } public ActionResult About() { ViewBag.Message = "Your application description page."; return View(); } public ActionResult Contact() { int a = 0; int b; b = 1 / a; ViewBag.Message = "Your contact page."; return View(); }
اگر برنامه را با آدرس …../Home/contact اجرا کنید صفحه خطای زیر را خواهید دید
به مسیر …/Account/Register رفته و F5 را فشار دهید تا برنامه در این مسیر اجرا شود
برای دیدن خطاهای رخ داده شده به آدرس Domain/Elmah.axd بروید .همان طور که می بینید کلیه خطاهای کاربران در این صفحه گزارش شده است.اما در صفحه register اگر پسورد را اشتباه وارد کنید همانجا Regular Expression به شما پیغام می دهد و دیگر جزو خطاهای exception نیست که به شما پیغام خطا در داخل elmah بدهد در واقع خطاهای سیستمی گزارش گیری می شوند.
در داخل دیتابیس هم خطاها ذخیره شده است
- ASP.net MVC
- 2k بازدید
- 6 تشکر