All coders are quite familiar with error messages. They are quite handy when developing stuff but you dont want them around after the release of your system and the users dont really think they are too funny.
So, how can we get rid of these ugly messages and still get nice information when your functions break down? I have written some code (with some inspiration from other error logging examples) that provide your system with some nice features:
- On error, it redirects the user to a page that in English explains that an error has occurred.
- You can set the object to either send an email or write in the EventLog, or both.
- All the browser information is included in the email for support help.
- It can also present an Alert message to the user.
Code explanation:
// The constructor is overloaded and gets the important variables from either the object creation or web.config
public KillahErrHandler()
{
this.MailServer = ConfigurationSettings.AppSettings["MailServer"];
this.EmailReciever = ConfigurationSettings.AppSettings["MailReciever"];
this.LogName = ConfigurationSettings.AppSettings["LogName"];
}
web.config
<appSettings>
<add key="MailServer" value="mail.yourserver.com" />
<add key="MailReciever" value="[email protected]" />
<add key="LogName" value="MyWeb Log Alert" />
</appSettings>
or..
public KillahErrHandler(string _mailserver, string _mailreciever, string _logname)
{
this.MailServer = _mailserver;
this.EmailReciever = _mailreciever;
this.LogName = _logname;
}
The RaiseError Method executes the proper action depending on the MessageType
public void RaiseError(string _message)
{
this.LastMessage = _message;
switch(this.MT)
{
case MessageType.EventLog:
SaveToEventLog(_message);
break;
case MessageType.SendMail:
SendMail(_message);
break;
case MessageType.MailAndEventLog:
SaveToEventLog(_message);
SendMail(_message);
break;
default:
break;
}
}
Saving to Event Log
This option raises a security issue on the server. By default the ASPNET account cannot write to the event log (This is why I have a try, catch expression here).
To solve this:
Open regedt32 (not the standard, regedit) and navigate to:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\EventLog and click on "Security-->Permissions..." in the menu.
Add the ASPNET account for the local machine and place a check next to "Full Control".
Remember to include all child objects.
private void SaveToEventLog(string _message)
{
try
{
//Create our own log if it not already exists
if(!EventLog.SourceExists(this.EventLogName))
EventLog.CreateEventSource(this.EventLogName,this.EventLogName);
EventLog MyLog = new EventLog();
MyLog.Source = this.EventLogName;
MyLog.WriteEntry(_message, EventLogEntryType.Warning);
}
catch (Exception e)
{
//send us a email and tell that there is a permission problem
SendMail(e.Message);
}
}
Send Email:
Its not much to say about this. It is quite straight forward.
public void SendMail(string _message)
{
MailMessage mail = new MailMessage();
mail.From = this.EmailReciever;
mail.To = this.EmailReciever;
mail.Subject = this.MailSubject;
mail.Body = "Error message:\n"+_message+"\n\n"+GetUserData();
mail.BodyFormat = MailFormat.Text;
SmtpMail.SmtpServer = this.MailServer;
SmtpMail.Send(mail);
}
User details:
When finding out why the user has problems with your web site, it is quite useful to now the configuration.
private string GetUserData()
{
System.Web.HttpBrowserCapabilities browser=HttpContext.Current.Request.Browser;
string s = "Browser Capabilities\n"
+ "IP Address = " + HttpContext.Current.Request.ServerVariables
"REMOTE_ADDR"].ToString()+"\n"
+ "Type = " + browser.Type + "\n"
+ "Name = " + browser.Browser + "\n"
+ "Version = " + browser.Version + "\n"
+ "Major Version = " + browser.MajorVersion + "\n"
+ "Minor Version = " + browser.MinorVersion + "\n"
+ "Platform = " + browser.Platform + "\n"
+ "Is Beta = " + browser.Beta + "\n"
+ "Is Crawler = " + browser.Crawler + "\n"
+ "Is AOL = " + browser.AOL + "\n"
+ "Is Win16 = " + browser.Win16 + "\n"
+ "Is Win32 = " + browser.Win32 + "\n"
+ "Supports Frames = " + browser.Frames + "\n"
+ "Supports Tables = " + browser.Tables + "\n"
+ "Supports Cookies = " + browser.Cookies + "\n"
+ "Supports VBScript = " + browser.VBScript + "\n"
+ "Supports JavaScript = " + browser.JavaScript + "\n"
+ "Supports Java Applets = " + browser.JavaApplets + "\n"
+ "Supports BackgroundSounds = " + browser.BackgroundSounds + "\n"
+ "Supports ActiveX Controls = " + browser.ActiveXControls + "\n"
+ "Browser = "+ browser.Browser+ "\n"
+ "CDF = "+ browser.CDF+ "\n"
+ "CLR Version = "+ browser.ClrVersion+ "\n"
+ "ECMA Script version = "+ browser.EcmaScriptVersion+ "\n"
+ "MSDOM version = "+ browser.MSDomVersion+ "\n"
+ "Supports tables = "+ browser.Tables+ "\n"
+ "W3C DOM version = "+ browser.W3CDomVersion+ "\n";
return s;
}
Examples
This is an example how we try to contact a database and handles the occurring errors:
private void Page_Load(object sender, System.EventArgs e)
{
SqlDataReader objDataReader = null;
SqlConnection myConnection = null;
try
{
string sql = "server=192.168.0.1;uid=username;pwd=mypass;database=mydb";
myConnection = new SqlConnection(sql);
SqlCommand myLogin = new SqlCommand("MyStoredProcedure", myConnection);
myLogin.CommandType = CommandType.StoredProcedure;
SqlParameter myParm1 = myLogin.Parameters.Add("@Id", SqlDbType.Int);
myParm1.Value = 1;
myConnection.Open();
objDataReader = myLogin.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (SqlException sqlex) // Catch SQL error message
{
//Create object
KillahErrHandler KEH = new KillahErrHandler();
//Set MessageType
KEH.MsgType = MessageType.MailAndEventLog;
//Raise the error
KEH.RaiseError(sqlex.Message);
//Send an alert to the user
Response.Write(KEH.ShowAlert("An database error has occured!",true,true));
}
catch (Exception ex) // Catch other exception message
{
//Create object
KillahErrHandler KEH = new KillahErrHandler();
//Set MessageType
KEH.MsgType = MessageType.MailAndEventLog;
//Raise the error
KEH.RaiseError(ex.Message);
//Send an alert to the user
Response.Write(KEH.ShowAlert("An database error has occured!",true,true));
}
finally //Close DB objects
{
if(objDataReader != null) objDataReader.Close();
if(myConnection != null) myConnection.Close();
}
}
Christopher AndrewsPosted Nov 18, 2015, 6:17 AM
The article was extremely helpful, thank you. I found this .net error tracking tool amazingly simple and nice www.redfly.io
Christopher AndrewsPosted Nov 18, 2015, 6:09 AM
The article was extremely helpful, thank you. I found this .net error tracking tool amazingly simple and nice www.redfly.io
Gowtham RajamanickamPosted Apr 18, 2015, 3:50 AM
good one
salman ansariPosted Jun 1, 2012, 5:06 AM
Very Nice man......................
Vikas MishraPosted Dec 13, 2011, 1:43 PM
Hi Robert you have done a great work thanks for sharing.......
DavePosted Mar 16, 2011, 10:05 PM
Hi, we just wanted to make you aware of a new service that is great for .net event logging. We are currently accepting beta testers, and would love a mention on your site. We are a fully hosted, and offer a great, fluent-style .net logging agent. Please check us out.
Sachin RPosted Dec 22, 2009, 2:28 AM
Good one!
Narendra RathodPosted Feb 25, 2009, 11:41 PM
thank you..
DotNetGuts DNGPosted Sep 10, 2008, 6:37 PM
Check out this article to know more on logging error and generating email indication http://dotnetguts.blogspot.com/2007/10/error-handling-in-net-with-example.html