0

مدیریت کاربر پسند خطاها در asp.net

 
amirpetrucci0261
amirpetrucci0261
کاربر طلایی1
تاریخ عضویت : تیر 1388 
تعداد پست ها : 27726
محل سکونت : http://zoomstar.ir/

مدیریت کاربر پسند خطاها در asp.net

این مقاله یک تکنیک عمومی مدیریت استثتاها (exception handling) را برای برنامه های کاربردی و سرویس های وب asp.net ارائه میکند. از این تکنیک میتوانید برای هر برنامه کاربردی خود استفاده کرده و از مزایای آن بهره مند گردید.

نکته: در بسیاری از مواقع عبارات خطا ( Error ) و استثنا ( Exception ) به جای همدیگر به کار برده میشوند. هر چند این دو به یک معنا نسیتند اما دراینجا منظور از استثنا، خطاهای زمان اجرا است.
همانگونه که میدانید از 2 روش میتوانید برای مدیریت و رسیدگی به استثناها در asp.net استفاده کنید. اولین و ساده ترین راه استفده از رخداد Application_Error در فایل global.asax است.این رخداد زمانی اتفاق می افتد که یک مورد استثنا رسیدگی نشده در هرکجای برنامه asp.net رخ دهد.
در این مقاله از کلاسی به نام AspUnhandledException استفاده میکنیم و با امکانات آن بیشتر آشنا خواهیم شد. طبق آنچه گفتیم، میتوانیم در همین متد Application_Error یک نمونه از این کلاس را ایجاد کرده و استفاده کنیم:

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
Dim ueh As New ASPUnhandledException.Handler
ueh.HandleException(Server.GetLastError.GetBaseException())
End Sub

از آنجایی که اکثر توسعه دهندگان asp.net با فایل global.asax آشنایی دارند بنابراین این شیوه برای آنها ملموس تر و قابل توضیح تر است.


روش دوم آنچه که ما در اینجا به آن خواهیم پرداخت و راهکار بسیار مناسب تری است پیاده سازی اینترفیس IHttpModule میباشد.

Public Class UehHttpModule
Implements IHttpModule
Public Sub Init(ByVal Application As System.Web.HttpApplication)
Implements System.Web.IHttpModule.Init
AddHandler Application.Error, AddressOf OnError
End Sub
Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
End Sub
Protected Overridable Sub OnError(ByVal sender As Object,
ByVal args As EventArgs)
Dim app As HttpApplication = CType(sender, HttpApplication)
Dim ueh As New ASPUnhandledException.Handler
ueh.Handle(app.Server.GetLastError)
End Sub
End Class

این روش از لحاظ عملکردی برابر روش قبلی است اما یک تفاوت کلیدی دارد: با استفاده از این روش شما میتوانید بدون آنکه محبور باشید برنامه کاربردی خود را مجددا کامپایل کنید، میتوانید رسیدگی و مدیریت استثناها را پیاده سازی کنید.


این بدان معنی است که شما متیوانید رسیدگی به استثناهای مدیریت نشده را در هر وب سایت طراحی شده توسط asp.net به سادگی و تنها با کپی کردن فایل ASPUnhandledException.dll در فولدر bin و همچنین یک تغییر کوچک در فایل web.config اعمال کنید.

<system.web>
<httpModules>
<add name="UehHttpModule"
type="ASPUnhandledException.UehHttpModule, ASPUnhandledException" />
</httpModules>
</system.web>

به همین سادگی! جالب نیست ؟!

استثناهای رسیدگی نشده در سرویس های وب asp.net

متاسفانه هیچ یک از دو روش فوق برای یک سرویس دهنده وب asp.net کاربرد نخواهد داشت.چرا که متد Application_Error هرگز رخ نخواهد داد و از طرف دیگر با توجه به نحوه عملکرد SOAP pipeline دیگر HTTP pipeline دور زده میشود. برای این که بتوانیم استثناهای سرویس های وب را به طور کامل مدیریت کنیم میبایست اینترفیس SoapExtension را پیاده سازی کنیم.

Public Class UehSoapExtension
Inherits SoapExtension
Private _OldStream As Stream
Private _NewStream As Stream
Public Overloads Overrides Function GetInitializer( _
ByVal serviceType As System.Type) As Object
Return Nothing
End Function
Public Overloads Overrides Function GetInitializer( _
ByVal methodInfo As System.Web.Services.Protocols.LogicalMethodInfo, _
ByVal attribute As System.Web.Services.Protocols.SoapExtensionAttribute)
As Object
Return Nothing
End Function
Public Overrides Sub Initialize(ByVal initializer As Object)
End Sub
Public Overrides Function ChainStream(ByVal stream As Stream) As Stream
_OldStream = stream
_NewStream = New MemoryStream
Return _NewStream
End Function
Private Sub Copy(ByVal fromStream As Stream, ByVal toStream As Stream)
Dim sr As New StreamReader(fromStream)
Dim sw As New StreamWriter(toStream)
sw.Write(sr.ReadToEnd())
sw.Flush()
End Sub
Public Overrides Sub ProcessMessage(ByVal message _
As System.Web.Services.Protocols.SoapMessage)
Select Case message.Stage
Case SoapMessageStage.BeforeDeserialize
Copy(_OldStream, _NewStream)
_NewStream.Position = 0
Case SoapMessageStage.AfterSerialize
If Not message.Exception Is Nothing Then
Dim ueh As New Handler
Dim strDetailNode As String
'-- handle our exception, and get the SOAP <detail> string
strDetailNode = ueh.HandleWebServiceException(message)
'-- read the entire SOAP message stream into a string
_NewStream.Position = 0
Dim tr As TextReader = New StreamReader(_NewStream)
'-- insert our exception details into the string
Dim s As String = tr.ReadToEnd
s = s.Replace("<detail />", strDetailNode)
'-- overwrite the stream with our modified string
_NewStream = New MemoryStream
Dim tw As TextWriter = New StreamWriter(_NewStream)
tw.Write(s)
tw.Flush()
End If
_NewStream.Position = 0
Copy(_NewStream, _OldStream)
End Select
End Sub
End Class

SoapExtension کمی پیچیده تر از HTTPModule میباشد چرا که میباید پیغام ارسالی Soap را ویرایش کرده و جزئیات اطلاعات استثنای رخ داده را در آن درج کنیم. برای استفاده از این کد، بازهم تنها کافی است فایل ASPUnhandledException.dll را در فولدر bin کپی کرده و همچنین یک تغییر کوچک در فایل web.config اعمال کنید.

<webServices>
<soapExtensionTypes>
<add type="ASPUnhandledException.UehSoapExtension, ASPUnhandledException"
priority="1" group="0" />
</soapExtensionTypes>
</webServices>

پیکربندی AspUnhandledException

کلاس AspUnhandledException از طریق یک بخش بخصوص در فایل web.config از پیکربندی به نام <UnhandledException> انجام میگیرد. این کلاس با هر پیکربندی کارخواهد کرد اما تنها چیزی که از تنظیمات پیش فرض آن دریافت خواهید کرد یک فایل گزارش متنی در ریشه وب سایت تان است. ما پیشنهاد میدهیم که از پیکربندی زیر استفاده کنید:

این هم لیست کاملی از تنظیمات پیکربندی :

درست از لحظه ای که شما فایل dll مورد نظر را در فولدر bin کپی کنید و تنظیمات مربوطه را در فایل web.confing انجام دهید، از این به بعد همه چیز به طور اتوماتیک انجام خواهد گرفت، یعنی به محض رخ دادن یک استثنای مدیریت نشده، یک یا چند مورد از اتفاقات زیر رخ خواهند داد:


1- یک صفحه وب کاربر پسند به کاربر نشان داده خواهد شد


2- یک ایمیل شرح وقایع به آدرس یا آدرسهای تعیین شده ارسال خواهد شد


3- یک فایل متنی گزارش خطا در مسیر دلخواه شما ایحاد خواهد شد


4- یک رکورد به قسمت event log اضافه خواهد شد


همه این گزینه ها شامل اطلاعات تشخیص داده شده مفصل درباره استثنا رخ داده هستند که توسط ExceptionString تولید خواهند شد. اجازه بدهید تا هریک را به طور مفصل تر شرح دهیم.


اگر ویژگی LogToUI مثل حالت پیش فرض True باشد، به صورت خودکار یک صفحه وب کاربر پسند در هنگام رخ دادن خطا به کاربر نمایش داده خواهد شد. در غیر این صورت همان صفحه زرد رنگ پیش فرض asp.net نمایش خواهد یافت.


چنانچه ویژگی LogToEmail حالت پیش فرض True داشته باشد خطای مدیریت نشده به طور خودکار با استفاده از امکانات کلاسSMTPMail به آدرس یا آدرسهای مورد نظر شما ارسال خواهد شد. این کلاس نیازمند تنظیمات SMTP در فایل web.config و در بخش <unhandledException> است. لیست کاملی از این تنظیمات را در زیر میبینید:


 

Key
Default
Description
EmailTo
none
لیستی از آدرسهای ایمیل که با سمی کالن از هم جدا شده اند
EmailFrom
server@domain.com
این پارامتر اختیاری است و یک سربازگذاری از نحوه آدرس دهی ایمیل به شمار میرود
IgnoreDebug
True
زمانی که در حال debug برنامه هستید یا در حالتی که هاست شما localhost است، هیچ خطایی را مدیریت نمیکند.
IgnoreRegex
""
اگر الگوی عبارت منظم این پارامتر در هر بخش از رشته خطا یا exception string پیدا شود، خطای رخ داده نادیده گرفته میشود
LogToEventLog
False
خطای مدیرت نشده را در Event Log ثبت میکند
LogToEmail
True
خطای مدیریت نش ده را به آدرس مشخص شده در EmailTo ارسال میکند
LogToFile
True
خطای مدیریت نشده را یک فایل متنی مینویسد
LogToUI
True
به طور خودکار یک صفحه وب برای خطای رخ داده ایجاد کرده و نمایش میدهد
PathLogFile
""
مسیر فایل متنی حاوی خطای رخ داده را تعیین میکند. این آدرس میتواند مطلق و یا نسبی باشد
AppName
none
در صفحه خطای پیش فرض HTML استفاده میشود تا همه نمونه های "(app)" را در رشته ها جایگزین کند
ContactInfo
none
در صفحه خطای پیش فرض HTML استفاده میشود تا همه نمونه های "(contact)" را در رشته ها جایگزین کند
PageTitle
(see screenshot)
عنوان صفحه خطای پیش فرض
PageHeader
(see screenshot)
Header صفحه خطای پیش فرض
WhatHappened
(see screenshot)
متنی که در صفحه خطای پیش فرض زیر قسمت "What happened:" نمایش داده میشود
HowUserAffected
(see screenshot)
متنی که در صفحه خطای پیش فرض زیر قسمت "Wha"How this will affect you:" نمایش داده میشود
WhatUserCanDo
(see screenshot)
متنی که در صفحه خطای پیش فرض زیر قسمت "What you can do about it:" نمایش داده میشود

ایمیل ارسالی حاوی موارد زیر در خصوص خطای رخ داده است:
• شناسه کاربر و کامپیوترش
• اطلاعات برنامه
• خلاصه از خطای رخ داده
• محتوای stack
• محتوای کلکسیونهای Asp.net مانند متغیرهای سمت سرور و ...
 

اگر ویژگی LogToFile حالت پیش فرض True داشته باشد خطاهای رخ داده در یک فایل متنی در ریشه وب سایت شما به نام UnhandledExceptionLog.txt دخیره خواهند شد. اگر به مسیر دیگری نیازمندید از ویژگی PathLogFile استفاده کنید. البته برنامه شما باید مجوز نوشتن را داشته باشد.
چنانچه LogToEvent فعال باشد، جزئیات خطا در بخش ثبت وقایع یا همان Application Event Log ثبت خواهد شد.به یاد داشته باشید که برنامه شما میباشیت مجوز دسترسی به رحیستری را داشته باشد. از آنجایی که معمولا چنین نیست، حالت پیش فرض برای این گزینه False در نظر گرفته شده است.

استفاده از AspUnhandledException در وب سرویس ها

برای وب سرویس ها از بخشی به نام SoapException استفاده میکنیم.البته این بخش تفاوتهایی با آنچه قبلا گفتیم دارد که در زیر میبنیید:


1- استفاده از SoapException به معنای این است که فقط خطاهای مدیریت نشده SOAP در نظر گرفته شوند و شما قادر نخواهدی بود که این خطا ها را توسط اینترفیس مرورگر خود تست کنید


2- از آنجایی که کلاستهای SOAP از یک اینترفیس مرورگر بهره مند نیستند، بنابراین ویژگی LogToUI برای وب سرویس ها در دسترس نبوده و نادیده گرفته خواهد شد.


3- SoapException حاوی المان XML ای به نام <detail> است که جزئیات بخش سمت سرور خطای رخ داده را نگهداری میکند. از آنجایی که این المان حاوی اطلاعات مفصلی نیست، با استفاده از ترفند زیر اطلاعات مورد نظرمان را ثبت میکنیم


شناسایی خطاها با این اطلاعات کم کاری است دشوار و این جاست که از Handler.HandleWebServiceException استفده میشود. ما این متد را از SoapException فراخوانی میکنیم تا اطلاعات بهتری را برایمان فراهم کند.

Public Function HandleWebServiceException(ByVal sm As _
System.Web.Services.Protocols.SoapMessage) As String
_blnLogToUI = False
HandleException(sm.Exception)
Dim doc As New Xml.XmlDocument
Dim DetailNode As Xml.XmlNode = doc.CreateNode(XmlNodeType.Element, _
SoapException.DetailElementName.Name, _
SoapException.DetailElementName.Namespace)
Dim TypeNode As Xml.XmlNode = doc.CreateNode(XmlNodeType.Element, _
"ExceptionType", _
SoapException.DetailElementName.Namespace)
TypeNode.InnerText = _strExceptionType
DetailNode.AppendChild(TypeNode)
Dim MessageNode As Xml.XmlNode = doc.CreateNode(XmlNodeType.Element, _
"ExceptionMessage", _
SoapException.DetailElementName.Namespace)
MessageNode.InnerText = sm.Exception.Message
DetailNode.AppendChild(MessageNode)
Dim InfoNode As Xml.XmlNode = doc.CreateNode(XmlNodeType.Element, _
"ExceptionInfo", _
SoapException.DetailElementName.Namespace)
InfoNode.InnerText = _strException
DetailNode.AppendChild(InfoNode)
Return DetailNode.OuterXml.ToString()
End Function

رشته بازگشت داده شده توسط این متد برای ویرایش پیغام SOAP استفاده میشود تا <detail> بهتری تولید کند:

<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Server was unable to process request. -->

من خطوط <ExceptionInfo> زيادي را امتحان كرده ام اما همه آنها همان اطلاعات ارزشمندي را كه قبلا ملاحظه كرده ايد ارائه ميدهند


منبع : codeproject.com

چهارشنبه 10 آذر 1389  5:36 AM
تشکرات از این پست
دسترسی سریع به انجمن ها