Click here to Skip to main content
15,867,568 members
Articles / Web Development / ASP.NET
Article

Creating Audit Functionality Using ASP.NET 2.0

Rate me:
Please Sign up or sign in to vote.
3.86/5 (5 votes)
8 Jun 20072 min read 89.2K   1.1K   66   12
How to use ASP.NET to audit user data changes
Sample image

Introduction

This updated article describes how to create an audit tool that tracks and records the changes of any fields with their old and new values using an ASP.NET web page. To see the project in action, you can download the code. However, you must change your connection properties for the database interaction.

Background

When posed with this issue, I found various solutions that range from SQL Server Triggers to more custom solutions that require additional knowledge of web controls. However, my solution has the following benefits:

  • Records and tracks only the changes made to the field or fields that are changed. One solution, for example, used a trigger that would populate the audit changes, but this included ALL fields that were in the UPDATE SQL statement. What this means it that it would populate the Audit table with fields that were also not changed, which filled my audit table exponentially.
  • Plays on events already part of the .NET Framework. In this example, I use key event objects that allow us to record and compare data changes consistently, whether using GridView or DetailsView.
  • Uses existing properties that allow audit tracking to work. There are event properties already nicely built into the .NET Framework that is part of the GridView and DetialsView control. This allows us to see the new values and old values via a returned collection object.

Using the Code

The pattern implementations are the same for both the GridView and DetailsView. It is just a matter of simply passing in the appropriate event object as a parameter. Here is an example of the overload methods for the GridView and DetailsView:

C#
// GridView Method overload
public static void updateFieldAudits(GridViewUpdatedEventArgs e)
{
    foreach (DictionaryEntry newValues in e.NewValues)
    {
        int i = 0;

        string newKeyCol = newValues.Key.ToString();
        foreach (DictionaryEntry oldVals in e.OldValues)
        {
            string oldKeyCol = oldVals.Key.ToString();

            if (oldKeyCol == newKeyCol)
            {
                break;
            }
            i++;
        }
        string oldVal = (string)e.OldValues[i];

        if (newValues.Value != null)
        {
            string newVal = newValues.Value.ToString();

            if (oldVal != newVal)
            {
                MyDBDAL.insertAuditChanges(newKeyCol, oldVal, newVal);
            }
        }
        else
        {
            if (!String.IsNullOrEmpty(oldVal))
            {
                MyDBDAL.insertAuditChanges(newKeyCol, oldVal, "");
            }
        }
    }
}
// DetailsView Method overload
public static void updateFieldAudits(DetailsViewUpdatedEventArgs e)
{
    foreach (DictionaryEntry newValues in e.NewValues)
    {
        int i = 0;

        string newKeyCol = newValues.Key.ToString();
        foreach (DictionaryEntry oldVals in e.OldValues)
        {
            string oldKeyCol = oldVals.Key.ToString();
            if (oldKeyCol == newKeyCol)
            {
                break;
            }
                i++;
            }
            string oldVal = (string)e.OldValues[i];

            if (newValues.Value != null)
            {
                string newVal = newValues.Value.ToString();

                if (oldVal != newVal)
                {
                MyDBDAL.insertAuditChanges(newKeyCol, oldVal, newVal);
            }
        }
        else
        {
            if (!String.IsNullOrEmpty(oldVal))
            {
                MyDBDAL.insertAuditChanges(newKeyCol, oldVal, "");
            }
        }
    }
}

In order to record the changes, the event of interest on the GridView is the RowUpdated method. The example below traps this event and allows you to pass in the GridViewUpdatedEventArgs event object parameter to the updateFieldAudits method.

C#
protected void GridView1_RowUpdated(object sender, 
    GridViewUpdatedEventArgs e)
{
    AuditFields.updateFieldAudits(e);
}

For the DetailsView code-behind, we capture the ItemUpdated event method:

C#
protected void DetailsView1_ItemUpdated(object sender, 
    DetailsViewUpdatedEventArgs e)
{ 
    AuditFields.updateFieldAudits(e);
}

Finally, we have to wire up the web control events for the GridView and DetailsView with the following:

C#
OnRowUpdated="GridView1_RowUpdated" 
OnItemUpdating="DetailsView1_ItemUpdating"

That's it! It is portable for web controls and you can add your own database update functions to record your audit data changes, or create a custom business object.

History

  • 8 January, 2007 -- Original version posted
  • 8 June, 2007 -- Article updated

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior) PNC Bank
United States United States
Harry is a .NET Developer for a major financial institution building web and stand alone applications and class libraries. He also has experience teaching courses on ASP.NET and Microsoft databases. He holds a Master's degree in Information Science.

Comments and Discussions

 
GeneralSQL server changes auditing Pin
Denial Parl16-Feb-15 20:21
Denial Parl16-Feb-15 20:21 
GeneralNewEditIndex Definition with DetailsView Pin
jaymdouglas20-Jun-08 5:16
jaymdouglas20-Jun-08 5:16 
I am trying to edit this great concept to use with a DetailsView so that any changes are tracked automatically.

But, I noticed the "DetailsViewUpdateEventArgs" does not contain a definition for "NewEditIndex" so the following line throws an error:

protected void dtvCellPhoneEdit_RowEditing(object sender, DetailsViewUpdatedEventArgs e)
{
string strId = dtvCellPhoneEdit.Rows[e.NewEditIndex].Cells[4].Text; <-- ERROR-->
CurrentFields currFlds = new CurrentFields();
currFieldList = currFlds.GetCurrentFields(strId);
Session["CurrData"] = currFieldList;
}

Anyone have any idea how to correct this?
GeneralRe: NewEditIndex Definition with DetailsView Pin
harryteck8-Jul-08 9:20
harryteck8-Jul-08 9:20 
Generalchange code for msaccess Pin
jonathanm55-Nov-07 2:04
jonathanm55-Nov-07 2:04 
GeneralRe: change code for msaccess Pin
harryteck5-Feb-08 10:06
harryteck5-Feb-08 10:06 
GeneralWeb Auditing on all Controls Pin
But_Im_a_Lady25-Jul-07 23:07
But_Im_a_Lady25-Jul-07 23:07 
GeneralRe: Web Auditing on all Controls Pin
harryteck18-Aug-07 11:12
harryteck18-Aug-07 11:12 
GeneralRe: Web Auditing on all Controls Pin
harryteck18-Aug-07 11:40
harryteck18-Aug-07 11:40 
QuestionMultiple Tables Pin
mrsLeigh22-Mar-07 5:30
mrsLeigh22-Mar-07 5:30 
AnswerRe: Multiple Tables Pin
harryteck11-Jun-07 4:21
harryteck11-Jun-07 4:21 
GeneralSQL Auditing Pin
RyanHilton10-Jan-07 7:04
RyanHilton10-Jan-07 7:04 
GeneralRe: SQL Auditing Pin
harryteck12-Jan-07 3:30
harryteck12-Jan-07 3:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.