- What Is the EMAB, Anyway?
- Logging Exceptions with the EMAB
- Creating a Custom Publisher
- Configuring a Custom Publisher
- Summary
The sample application that ships with the EMAB contains a sample application configuration file. You can glean a lot of information about configuration settings for the EMAB by reading this text/XML file. Listing 3 is a configuration file that tells the application block to use our custom exception publisher. A description of the configuration file contents follows in Listing 3.
Listing 3 An App.config file for the custom exception publisher.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="exceptionManagement" type="Microsoft.ApplicationBlocks.ExceptionManagement.ExceptionMan agerSectionHandler,Microsoft.ApplicationBlocks.ExceptionManagement" /> </configSections> <exceptionManagement mode="on"> <publisher assembly="CustomPublisher" type="CustomPublisher.SimplePublisher" /> </exceptionManagement>
</configuration>
Keep in mind that XML elements are case-sensitive. Also, remember that the code in the preceding listing is wrapped due to the limitations of screen and page real estate, but these items are contiguous in an XML file.
NOTE
The easiest way to ensure that an external exception publisher can be loaded by the EMAB is to put the assembly in the GAC or register it using regasm with the /codebase switch. I cheated slightly by adding a reference to the custom exception publisher in the sample application I created.
The <configSections> element associates a future element (*<exceptionManagement>)with an assembly that contains and implements IConfigurationSectionHandler. The EMAB implements an IConfigurationSectionHandler. The purpose of such a handler is the objectification of an arbitrary XML block. In a nutshell, the <section> element says to the CLR when you encounter an element named <exceptionManagement>, create an instance of the ExceptionManagerSectionHandler and proceed to that code for further instructions about how to treat the XML block. The section handler contains code that converts an <exceptionManagement> XML element into an object. As a result, the XML in the <exceptionManagement> block is read and used to initialize an object. This object is the NameValueCollection represented by the configSections argument to the Publish method.
Listing 4 shows an excerpt from the sample application's .config file. It illustrates an example of the kind of information that ends up in the configSettings argument.
Listing 4 An excerpt from the EMAB sample application.
<exceptionManagement mode="on"> <publisher assembly="Microsoft.ApplicationBlocks.ExceptionManagement" type="Microsoft.ApplicationBlocks.ExceptionManagement.DefaultPublisher" logname="Quick Start Log" applicationname="Quick Start Samples" /> </exceptionManagement>
The logname and applicationname attributes if the <exceptionManagement> element are meaningful only to the Microsoft.ApplicationBlocks.ExceptionManagement.DefaultPublisher. When present these attributes are read by the EMAB and are used to create a custom EventLog source and as the application argument for the EventLog.
If we defined a custom publisher that published to a database, we might define an attribute connectionString and initialize it with a connection string to a database. Only a custom publisher defined to look for that attribute (connectionString) would make sense of a connectionString attribute. To use such an attribute, you would index the configSettings NameValueCollection and use the returned value. (Refer to the DefaultPublisher for an example of this code.)
Multicasting to Publishers
Suppose you elected to log exceptions to multiple publishers. If you added a second, third, or more <publisher> element to the <ExceptionManagement> element, every publisher listed would publish each exception. (The multicasting capability of the EMAB is consistent with the behavior of the Trace.TraceListeners collection. Refer to the System.Diagnostics namespace for more on using Trace.)
Notifying Responsible Parties
As an alternative to multicasting to publishers one could implement a publisher that sends information to several sources. For example, our dialog box publisher could be modified to look for an email address and send a message to the address contained in the configuration file. With such a revision, we could ask our customers to run the application again, adding us to the recipients list, and diagnose the problem remotelyor, at least see what they are seeing. Such a revision to the CustomPublisher is shown in Listing 5, and a revision to the .config file is shown in Listing 6.
Listing 5 The modified CustomPublisher, which sends the exception information to an email respondee.
using System; using Microsoft.ApplicationBlocks.ExceptionManagement; using System.Collections.Specialized; using System.Windows.Forms; using System.Web.Mail; namespace CustomPublisher { public class SimplePublisher : IExceptionPublisher { public void Publish(Exception exception, NameValueCollection additionalInfo, NameValueCollection configSettings) { MessageBox.Show(exception.Message); if( configSettings["notify"] != null) { SmtpMail.Send("", configSettings["notify"], "exception", exception.Message); } } } }
Listing 6 A .config file that shows how to configure the CustomPublisher.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="exceptionManagement" type="Microsoft.ApplicationBlocks.ExceptionManagement.ExceptionMan agerSectionHandler,Microsoft.ApplicationBlocks.ExceptionManagement" /> </configSections> <exceptionManagement mode="on"> <publisher assembly="CustomPublisher, type="CustomPublisher.SimplePublisher" notify="pkimmel@softconcepts.com" /> </exceptionmanagement> </configuration>
It is important to note that the attribute values, like type, represent a single contiguous string. These values need to be defined on one line in your .config files. They have to be wrapped here due to limitations in screen and page real estate.
In the revision, we cowboy a message to whatever value is associated with the configSettings["notify"] value. You might elect to wrap the call to SmtpMail.Send in an exception handler in case something about the notify attributes fails, but the shared SmtpMail.Send method seems to be pretty robust.