ASP.Net Sending exceptions as email

If you’re building an ASP.Net web application, the last thing you want to show your users is broken code. I’m going to demonstrate how to easily manage error handling in modern web applications by holding back errors from the presentation layer and sending them via email to yourself when and if a problem occurs.

The first task is related to framework. We need a way of storing some global information such as whether email notifications are enabled, which SMTP server we are going to relay messages through and to which address they will send and receive to.

The first and easiest way of accomplishing this is through the Web.config, let’s take a look.

Web.config Application Settings:

1. Right click on your solution and “Add New Item”
2. Select “Web Configuration File” and accept the default name, click “Add”
3. Double click on the new Web.config file and read through the XML file to get an idea of what information is being stored automatically about your web application.
4. Locate the <appSettings> … </appSettings> section.
5. This section works similar to a hash table of values, you can add new key/value pairs to reference from code.
6. Create a new line inside <appSettings> like the following:

<appSettings>
  <add key="MailServer" value="smtp.myServer.com" />
  <add key="MailServerPort" value="25" />
  <add key="MailUserName" value="smtpUser" />
  <add key="MailPassword" value="smtpPass" />
  <add key="EnableErrorLogEmail" value="true" />
  <add key="ErrorLogEmailAddress" value="error@myWebsite.com" />
  <add key="AdminEmailAddress" value="admin@myWebsite.com" />
</appSettings>

Now that we have some basic information stored in the Web.config we’ll need a structured means for referencing those value pairs from within code. While it is possible to go directly to the Web.config, I don’t recommend it because we can build off this initial example with a special class for configuration settings to have something even better.

Class: AppConfiguration

Inside the App_Code folder create a new class, I’m using C# so I’ve called my new class AppConfiguration.cs. This class is going to be static and used as a utility class for the entire site. It will provide structured access to Web.config files by using properties. Now for some code.

using System;
using System.Configuration;
 
public static class AppConfiguration {
 
  static AppConfiguration()
  {}
 
  public static string MailServer {
    get { return ConfigurationManager.AppSettings["MailServer"].ToString(); }
 
  }
 
  public static int MailServerPort {
    get { return Int32.Parse(ConfigurationManager.AppSettings["MailServerPort"].ToString()); }
  }
 
  public static string MailUserName {
    get { return ConfigurationManager.AppSettings["MailUserName"].ToString(); }
  }
 
  public static string MailPassword {
    get { return ConfigurationManager.AppSettings["MailPassword"].ToString(); }
  }
 
  public static bool EnableErrorLogEmail {
    get { return bool.Parse(ConfigurationManager.AppSettings["EnableErrorLogEmail"].ToString()); }
  }
 
...
 
}

The rest of the properties are left for yourself and will fit one of the previous examples. Feel free to include your own specific application settings in both areas to suit your needs.

Now one of the final things we’ll need is another utility class which can perform system functions, one of which will be sending an email message for us using the application configuration.

Class: Utilities

This class is going to be similar to the last in such that it provides provide member functions for the web application. Any type of system wide functions can be included here such as sending emails, logging errors, parsing date’s to a special format, etc…

Nothing like looking at code to make things clearer.

using System;
using System.Data;
using System.Data.Common;
using System.Text;
using System.Net.Mail;
 
public static class Utilities {
 
  static Utilities() {
  }
 
  public static void LogError(Exception ex) {
    LogError(ex, "");
  }
 
  public static void LogError(Exception ex, string message) {
    string errorMessage = "";
 
    errorMessage += "Exception Date: " + DateTime.Now.ToLongDateString() + "<br>";
    errorMessage += "Exception Time: " + DateTime.Now.ToShortDateString() + "<br>";
    System.Web.HttpContext context = System.Web.HttpContext.Current;
    errorMessage += "Error Page: " + context.Request.RawUrl + "<br>";
    errorMessage += "Error: " + ex.Message + "<br>";
 
    if (AppConfiguration.EnableErrorLogEmail) {
      string from = AppConfiguration.AdminEmailAddress;
      string to = AppConfiguration.ErrorLogEmailAddress;
      string subject = "Error Report";
      string body = errorMessage;
 
      SendEmail(from, to, subject, body);
    }
  }
 
  public static void SendEmail(string from, string to, string subject, string body) {
    MailMessage message = new MailMessage(from, to, subject, body);
    SmtpClient client = new SmtpClient(AppConfiguration.MailServer);
    client.Send(message);
  }
}

Now finally, you’re going to want to use all these fancy new mechanics we’ve written. Consider that for any instance of a try/catch block you have in code, you can now have the exceptions delivered to your inbox. For example

try {
 
  //Some code which may produce an exception
 
} catch (SqlException ex) {
  Utilities.LogError(ex);
} catch (Exception ex) {
  Utilities.LogError(ex);
}

Whew, that was a lot to take in. I hope it is all clear. Leave me a comment with questions if you have any and I’ll get back to you as soon as possible.

C# List SQL databases to populate list

You may come across the requirement to query a system running SQL Server for a list of all possible databases. From there you may drill down to find a specific database and need to perform a query on one of the found database’s tables. For both instances the .net class SqlConnection can be used in conjunction with it’s method GetSchema. Let’s take a look how to write a method which will return a list of databases provided a server name and SQL credentials.

public List<String> GetDatabases
(String ServerName, String UserName, String Password)
{
   // Instantiate returning data structure of database names
   List<String> databases = new List<String>();
   // Build connection string with parameters
   String connectionString =
      "Data Source=" + ServerName +
      ";UID=" + UserName +
      ";Password=" + Password + ";";
 
   try
   {
      // Create SqlConnection object with connection string
      using (SqlConnection sqlConnection = new SqlConnection(connectionString))
      {
         sqlConnection.Open();
         // Query SQL server for databases
         DataTable dt = sqlConnection.GetSchema("Databases");
         // Close connection to SQL
         sqlConnection.Close();
 
         // Iterate the datatable and parse names
         foreach (DataRow dataRow in dt.Rows)
         {
            databases.Add(dataRow["database_name"].ToString());
         }
      }
   }
   // Handle SQL type errors
   catch (SqlException ex)
   { }
   // Catch all error handler
   catch (Exception ex)
   { }
 
   return databases;
 }

Now, it’s likely that that return value will be used to populate a drop down list control to allow the user to select one of the databases the method found. This is a simple process but I will include it for completeness.

// User inputs server name and SQL credentials on form
List<String> databases = GetDatabases(
   txtServerName.Text,
   txtUserName.Text,
   txtPassword.Text);
 
// Clear drop down list to prevent duplicates
ddlDatabases.Items.Clear();
// Iterate through data structure's strings
foreach (String db in databases)
{
   // At new string value to drop down list
   ddlDatabases.Items.Add(db);
}

Finally, we’re going to write a method similar to the database query which will return a list of tables in a specific database. This will use as parameter a string value which is the name of a database. It assumes that the connection string is stored after the first method was executed.

public List<String> GetTables(String database)
{
   // Instantiate returning data structure of table names
   List<String> tables = new List<String>();
 
   try
   {
      // Create SqlConnection object with connection string
      using (SqlConnection sqlConnection = new SqlConnection(ConnectionString))
      {
         // Build SQL query for tables of a paramaterized database
         SqlCommand command = sqlConnection.CreateCommand();
         command.CommandText =
            "USE " + database +
            " SELECT [name] AS Name FROM sysobjects WHERE xtype='U'";
         sqlConnection.Open();
         // Query SQL for table names and close connection when done
         DataTable dt = new DataTable();
         dt.Load(command.ExecuteReader(
            CommandBehavior.CloseConnection));
 
         // Iterate datatable for table names
         foreach (DataRow dataRow in dt.Rows)
         {
            tables.Add(dataRow["Name"].ToString());
         }
      }
   }
   // Handle SQL type errors
   catch (SqlException ex)
   { }
   // Catch all error handling
   catch (Exception ex)
   { }
 
   return tables;
}

That combined approach is a solid method for reliably retrieving initial information from a SQL server to drill down and execute a query on a specific table.

Leave a question in the comments if you have any, happy coding.

More Articles

HTC Dream Review