Saturday, May 19, 2007

Microsoft Application Blocks

Microsoft Application Blocks

Application Blocks are C# and VB.NET classes distributed as Visual Studio projects that can be downloaded from Microsoft's Web site and used in any .NET application, including ASP.NET Web applications. They are useful and powerful tools that can make applications more maintainable, scaleable and efficient. In 2002, Microsoft released two Application Blocks that encapsulate two of the most common programming tasks: data access and exception management. These two Application Blocks contain classes, static methods and interfaces that greatly simplify SQL Server data access and application exception management.

Introducing the Data Access and Exception Management Application Blocks
The Data Access Block provides static methods located in the SqlHelper class that encapsulates the most common data access tasks performed with Microsoft SQL server. If the term "static method" is new to you, it means that the class methods can be called without instantiating an instance of the class. For example, the method ExecuteReader () within the SqlHelper class can be called by simply using the statement SqlHelper.ExecuteReader () -- no object instantiation of the SqlHelper class is required.

These static methods can be used to return SqlDataReader, DataSet and XmlReader objects containing database information. You can call stored procedures and SQL commands and specify stored procedure parameter details. The SqlHelper class also supports transactions.

The second Application Block encapsulates exception management. The Exception Management block provides a framework enabling you to log exception information, isolate exception code from your business logic and manage exceptions efficiently and consistently. The Exception block also provides excellent base classes and interfaces that can be used to create your own exception management framework or extend the Application Block to meet the needs of your particular system.

Application Blocks were designed by reviewing successful and efficient .NET applications and combining the optimum implementations into classes for our use. As a result, Application Blocks incorporate the current best practices endorsed by Microsoft. However, the greatest facet of Application Blocks is that they are surprisingly well documented. Each Application Block is distributed with complete documentation and source code examples. Even the source code is commented.

Application Blocks are Microsoft's implementation of two common patterns, efficient database interaction and consistent application exception management.

The Benefits of Using Application Blocks
Arguably, the biggest benefits to using Application Blocks are faster and more modular development. Because much of the "nuts and bolts" of data access and exception handling is wrapped in the Application Blocks, you don't have to worry about the tedious details required to return a DataReader or write an exception to the System Log. This allows us to concentrate on the business logic in our applications. Application blocks cut down on redundant code and provide a buffer between you and the .NET framework. Additionally, because Application Blocks are distributed as Visual Studio projects, you are free to browse the source code and make changes and/or additions to suit the needs of your own application. Finally, Application Blocks come with very good documentation and quick start samples to get you up and running quickly.

Getting Started With Application Blocks
In order to begin using either of the Application Blocks you must first download and install them. As mentioned previously, the application blocks can be downloaded from the following locations:
The Data Access Application Block - http://download.microsoft.com/download/VisualStudioNET/daabref/RTM/NT5/EN-US/DataAccessApplicationBlock.msi
The Exception Management Block - http://download.microsoft.com/download/VisualStudioNET/emabref/RTM/NT5/EN-US/ExceptionManagementApplicationBlock.msi
The installer package will create an entry in your Start Menu -> Program Files called "Microsoft Application Blocks for .NET". There you will find the source code (C# and VB), documentation, and Quick Start examples. To begin, select either C# or VB from the "Microsoft Application Blocks for .NET" menu The selected Project will open in Visual Studio. After the project loads, take some time to browse the source code, then build the assembly (from the Build menu select Build Solution). Once the assembly has built, you can start using the Application Block(s) in your Visual Studio .NET projects by adding a reference the created assembly. For example, to use the Data Access Application Block, you would add a reference to the assembly Microsoft.ApplicationBlocks.Data.dll. Finally, you will need to add the appropriate using (C#) or Imports (VB) statements to reference the Microsoft.ApplicationBlocks.Data, System.Data, and System.Data.SqlClient namespaces.
Let’s have a closer look at the Data Access Application Block
Here we will examine code samples that illustrate the advantages of using the Data Access Application Block. Add a reference to Microsoft.ApplicationBlocks.Data.dll to your project and add using (C#) or Imports (VB) statements for the Microsoft.ApplicationBlocks.Data, System.Data, and System.Data.SqlClient namespaces.

Now you are ready to begin using the Data Access Application Block.

Using the Data Access Application Block to Execute SQL Statements
Once you have the references set and the correct using or Imports statements in your class files, you will have access to the Data Access Application Blocks SqlHelper class. The SqlHelper class contains static methods that facilitate the execution of common data access tasks, including:
· Calling stored procedures or SQL text commands,
· Specifying parameter details, and
· Returning SqlDataReader, DataSet, XmlReader objects, or single values.
In order to illustrate the advantage of using the Data Access Block, let's take a look at sample code that creates a SqlDataReader object and binds it to a DataGrid without using the Data Access Block. In general, returning a DataReader involves establishing a connection, creating a SqlCommand, and executing the command against the database. The resulting SqlDataReader object can then be bound to a DataGrid:



//create the connection string and sql to be executed
string strConnTxt = "Server=(local);Database=Northwind; Integrated
Security=True;";
string strSql = "select * from products where categoryid =
1";
//create and open the connection object
SqlConnection objConn = new
SqlConnection (strConnTxt);
objConn.Open ();
//Create the command
object
SqlCommand objCmd = new SqlCommand (strSql,
objConn);
objCmd.CommandType = CommandType.Text;
//databind the datagrid
by calling the ExecuteReader () method
DataGrid1.DataSource =
objCmd.ExecuteReader ();
DataGrid1.DataBind ();
//close the
connection
objConn.Close ();



Now let’s look at the same task using the SqlHelper class's static ExecuteReader() method:

//create the connection string and sql to be executedstring strSql = "select *
from products where categoryid = 1";
string strConnTxt =
"Server=(local);Database=Northwind; Integrated
Security=True;"; DataGrid4.DataSource
= SqlHelper.ExecuteReader (strConnTxt, CommandType.Text,
strSql);
DataGrid4.DataBind ();




As you can see, there is considerably less code in the second example. To execute an SQL statement and return a SqlDataReader, the ExecuteReader () method requires only the connection string, command type and SQL to be executed. The SqlHelper class contains all of the "plumbing" necessary to establish a connection, create a SqlCommand and execute the command against the database with a single static method call.

The main advantage of the Application Blocks is that they greatly reduce the amount of code you need to write by encapsulating common tasks in a wrapper class. While at first glance this may not seem that profound of a benefit, realize that writing less code means more than just shorter time needed to write the code. It also means fewer bugs and typos, and an overall lower total cost to produce the software.

Using the Data Access Application Block to Execute Stored Procedures

The ExecuteReader() method also has several overloads that enable you to perform stored procedures and transactions. Lets take a quick look at the same method, but this time we'll execute a stored procedure:





DataGrid5.DataSource =
SqlHelper.ExecuteReader(strConnTxt, CommandType.StoredProcedure,
"getProductsByCategory",
new SqlParameter("@CategoryID", 1));



DataGrid5.DataBind();




To execute a stored procedure and return a SqlDataReader, we call the same static ExecuteReader() method but this time the function signature is different. Having a single function name with many different parameter forms to call it is known as method overloading. Overloading enables us to use the same SqlHelper class method but pass different parameters. To call a stored procedure, instead of passing the SQL statement, I send the name of the stored procedure and a SqlParameter object.

It's important to note that there's nothing magical about the ExecuteReader() method (or any other method in the Data Access Application Block). All Microsoft has done is create a wrapper that removes us from the details of creating the objects required to return a SqlDataReader. If you examine the Application Block's code, (which I encourage you to do so), you would see the same familiar objects we have used for database access in the past. Now, we simply don't have to worry about creating and maintaining them.

Lets take a look at a more dramatic example of the benefits of using the Data Access Application Block. For this example, we will retrieve a DataSet containing the results from a stored procedure (getProductsByCategory) that takes a single parameter (CategoryID). Again, to illustrate the amount of code saved by using the Data Access Application Block, let's first look at the necessary code when not using the Data Access Block:



// Open a connection to NorthwindSqlConnection objConn
= new
SqlConnection("Server=(local);Database=Northwind;Integrated
Security=True;");
objConn.Open();
//Create the stored
procedure command objectSqlCommand objCmd = new
SqlCommand("getProductsByCategory", objConn);
objCmd.CommandType =
CommandType.StoredProcedure;
//create the parameter object for the
stored procedure parameterobjCmd.Parameters.Add("@CategoryID", SqlDbType.Int);
objCmd.Parameters["@CategoryID"].Value = 1;

//create our DataAdapter and DataSet objectsSqlDataAdapter objDA = new
SqlDataAdapter(objCmd);DataSet objDS = new
DataSet("Category_Results");
//fill the dataset
objDA.Fill(objDS);
//databind the datagrid
DataGrid1.DataSource =
objDS;
DataGrid1.DataBind();
//close connection
objConn.Close();




Now, we will call the same stored procedure and return a DataSet using the SqlHelper class's ExecuteDataset() method:



string strConn = "Server=(local);Database=Northwind;
Integrated Security=True;";DataSet objDS = SqlHelper.ExecuteDataset(strConn,
CommandType.StoredProcedure,
"getProductsByCategory",
new SqlParameter("@CategoryID", 1)
);
DataGrid2.DataSource = objDS;DataGrid2.DataBind();





Through the usage of the Application Block, we reduced the lines of code from 12 to 4! Once again, the reason for the simplified code is that the ExecuteDataset() method has all the necessary logic to create and manage the required objects to execute the stored procedure and return the DataSet.

Now let’s have a look at another application block The Exception Management Application Block (or EMAB):

The Goal of the Exception Management Application Block
While we all like to think that we write bug free code, even the most skilled developer's code will, at times, contain flaws. These flaws - such as an incorrect connection string, not checking to see if an object is Nothing or null before using it, or attempting to access an array with an invalid index - all result in exceptions. Even if you are the best coder in the world, exceptions can still arise due to conditions out of your control, such as the database server crashing, or someone accidentally deleting a needed file from the Web server. The point is, exceptions happen.
What do you do when an exception happens in one of your ASP.NET Web applications? Is an administrator notified of the exception? Do you record the transaction in a database or in the Web server's Event Log, to maintain a history of exceptions. Imagine you wanted to record all exceptions to a database. To accomplish this you'd need to place code that might cause an exception in a Try ... Catch block, and in the Catch portion you'd record the information to the database. The following code illustrates this:



Try
... code that might cause an exception ...
Catch ex as
Exception
... connect to database ...
... insert a row into
an ExceptionLog table, adding details
about
the exception ...
End Try



The problem with the above code is that it tightly couples the behavior with the code. That is, imagine that you added this code to all of the ASP.NET page's code behind files' methods. Then, right as you finished, your boss said, "On second thought we want to not publish the details in the database, but rather just have the administrator emailed." Arghrhghgh!! Now you have to go back and change each and every ASP.NET code-behind class' methods - what a pain!
A better approach is to encapsulate the exception publishing action in a separate class. Then, if you needed to change the behavior that should occur when publishing an exception, you'd only need to make one change - the class designed to publish information about the exception. Enter the Exception Management Application Block...
The Exception Management Application Block (EMAB) is an application block designed to "publish" exception information. "Publishing" might involve recording the exception's details to a database, paging the system administrator, adding an entry to the Event Log, or some other custom task. The point is, with the EMAB you can write a class yourself to indicate precisely what "publishing" an exception involves.
Using the EMAB in an ASP.NET Web application is fairly straightforward. Now let's look at the code that will be used in an ASP.NET Web page to publish an exception: Try ... code that might cause an exception ...Catch ex as Exception ExceptionManager.Publish(ex)End Try
The EMAB provides a class, ExceptionManager, that has a Publish() method that accepts an Exception instance. It then "publishes" the exception information. (Again, what, precisely, publishing means can be customized.) The nice thing about the EMAB is that if you need to add or change what, exactly, publishing an exception entails, you need to only make a change to the publisher (more on this later), rather than to any code in the ASP.NET Web application.

Downloading and Installing the Exception Management Application Block
You can download the EMAB from Microsoft at http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=8CA8EB6E-6F4A-43DF-ADEB-8F22CA173E02. The download comes as an MSI file. Once you double-click the MSI file, it will prompt you for a directory location and then copy the EMAB Visual Studio .NET project to that directory. The EMAB - as with all of the Microsoft application blocks - provides two Visual Studio .NET projects: one in C# and one in VB.NET.
Once you have downloaded and created the Visual Studio .NET projects, you need to compile the project before you can use the EMAB in an ASP.NET Web application. To do this, open the Visual Studio .NET project in whatever language you prefer (you can do this through the Start menu), go to the Build menu and choose Build Solution. This will compile the project into an assembly (.dll file).

To use the EMAB in an ASP.NET Web application, open up the ASP.NET Web application and then add the EMAB assembly to the Web application's References folder. To accomplish this, right-click on the References folder, click on the Browse button and navigate to the EMAB assembly. Once you have added the assembly you'll still need to specify some configuration settings in the Web application's Web.config file before using the EMAB. We'll get to these settings in a moment, but first let's look at how to define how exceptions are published with the EMAB.
Default and Custom Publishers
The ExceptionManager class, itself, does not publish exception information. Rather, when its Publish() method is invoked, it examines the Web application's Web.config file to determine what publisher to use to publish the exception's details. A publisher is a class that implements the IExceptionPublisher interface. This interface defines a single method - Publish(Exception). The EMAB comes with a default publisher that publishes the exception information to the Web server's Event Log.
The good news, however, is that you can create your own custom publisher. This is accomplished by creating a class that implements IExceptionPublisher and putting the logic in the class's Publish() method. Want your exception information to be logged to a database? Write in the ADO.NET commands to accomplish this in the Publish() method (using the Data Access Application Block, ideally). Want to have the administrator emailed? Put the code here in the Publish() method. Since you are creating the class, you can specify precisely how an exception is "published."
Configuring the Exception Management Application Block
To use the EMAB in an ASP.NET Web application you need to add some settings to the Web.config file to indicate that the EMAB should be used and what, if any, custom publishers should be used. The basic settings in the Web.config look like the following:



The <section> element in the <configsections> section specifies that there is an <exceptionmanagement>section. The <exceptionmanagement>section, then, indicates that the EMAB should perform exception publishing. This configuration uses just the default publisher. You can also indicate that one or more custom publishers should be used through the following syntax:






Here a single, custom publisher is used. Assuming you've created a custom publisher class, you simply specify its assembly and type in the appropriate attributes of the element.
A Real-World Example of the Exception Management Application Block in Action!
I've used the EMAB in several projects I've worked on. Typically I create a custom publisher that adds the exception's details to a database table. The following shows my custom publisher class, my Web.config settings, and an example ASP.NET Web page.
Custom Publisher





Imports
Microsoft.ApplicationBlocks.ExceptionManagement
Imports System.WebImports
System.Data.SqlClient
Imports Microsoft.ApplicationBlocks.Data Public
Class DBExceptionPublisher Implements
IExceptionPublisher Public Sub Publish(ByVal exception
As System.Exception,
_
ByVal additionalInfo As NameValueCollection,
_
ByVal configSettings As NameValueCollection)
_
Implements IExceptionPublisher.Publish
Try
SqlHelper.ExecuteNonQuery(GlobalConnectionString,
CommandType.StoredProcedure,
"sp_AddException",
_
New SqlParameter("@Message",
exception.Message))
Catch ex As
Exception
HttpContext.Current.Response.Write("FATAL ERROR:
" &
_
ex.StackTrace &amp;amp;amp;amp; "

" &
ex.Message)
HttpContext.Current.Response.Flush()
HttpContext.Current.Response.End()
End Try
End SubEnd Class




The above is a very simple custom publisher (a shortened version of the custom publisher I use in practice). Notice that the class implements the IExceptionPublisher interface (which is defined in the Microsoft.ApplicationBlocks.ExceptionManagement namespace). The Publish() method uses the DAAB to run the sp_AddException stored procedure, passing in the Exception's Message property. (In a real scenario, you'd likely be interested in additional Exception properties...) Note that it, itself, uses a Try ... Catch block - this is because there may be an exception in accessing the database! In such a case, an ugly FATAL ERROR message is emitted to the end user's screen. (It would be prudent to email the administrator here, and perhaps redirect the user to a prettier error page.)
Once this class has been created and compiled, the next step is to configure the ASP.NET Web application's Web.config file. Assuming that the DBExceptionPublisher is compiled into an assembly named MyProjectExceptionBlock, with a default namespace of MyProjectExceptionBlock, the configuration syntax would look like:

Web.config file



<configuration>
...
<exceptionManagement mode="on">
<publisher assembly="MyProjectExceptionBlock"
type="MyProjectExceptionBlock.DBExceptionPublisher" />
</exceptionManagement>
...
</configuration>


Finally, let's look at an example ASP.NET Web page's code-behind class. Again, notice that to publish an exception we simply call the ExceptionManagement class's Publish() method. This consults the Web.config file, loads the proper custom publisher, and invokes its Publish() method, thereby publishing the exception details into the database.

An ASP.NET Web page code-behind class





Imports
Microsoft.ApplicationBlocks.ExceptionManagement
Public Class
logon
Inherits System.Web.UI.Page

Private Sub Page_Load(ByVal sender as Object, ByVal e as
EventArgs)

Try
... do something that
might cause an exception ...
Catch ex as
Exception


ExceptionManager.Publish(ex)
End
Try
End Sub
...
End Class


Conclusion
Using the Application Blocks will speed your application development by encapsulating the code required to execute stored procedures or SQL text commands, specify parameters and return SqlDataReader, DataSet, XmlReader objects. Because the Blocks was developed using the latest best practices, you can be confident that your code will be efficient and scalable.
Using the Application Block frees us from the tedious details of data access or exception publishing and allows us to concentrate on the important business logic in our applications. It also reduces the amount of code we must write, which leads not only to quicker development times, but reduced errors, bugs, and typos as well.
Note: Please refer to the original contribution for Data Access and Exception Management Blocks by John Jakovich and Scott Mitchell