Click here to Skip to main content
15,886,012 members
Articles / Web Development / ASP.NET

Pluggable Audit Framework using Unity, Interception and Reflection

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
10 Jun 2016CPOL5 min read 11.1K   160   5  
Pluggable Audit Framework using Unity, Interception and Reflection

Introduction

The problem which I am trying to solve here is to build a reusable audit framework. The intent is that this framework can be plugged into an existing code and audit should start working for many, if not all scenarios. However some updates would be needed in the application code, mainly configuration related changes.The problem which I am trying to solve here is to build a reusable audit framework. The intent is that this framework can be plugged into an existing code and audit should start working for many, if not all scenarios. However, some updated would be needed in the application code, mainly configuration related changes.

Using the Code

This framework is based on primarily these concepts:

  • Unity Framework
  • Interception
  • Custom Attributes
  • Reflection

I will cover shortly as to how these principles are used in my framework. Prior to that, I would like to mention the structure of audit table:

  • Module Name: Name of the functional module which needs to be audited
  • Table Name: Name of the transaction table which needs to be audited
  • Field Name: Name of the field in the table which needs to be audited
  • Primary Key: Primary key of the record in transaction table which needs to be audited
  • Od Value: Old value of the field
  • New Value: New value of the field
  • User: Name of the user updating the values
  • Time Stamp: Time when the transaction was done.

If some other structure suits your need, feel free to customize this framework.

I am using the Unity and Interception framework to intercept the calls to application methods and introduce auditing logic. I am using custom attributes to signify as audit needs to be applied to which all methods in the application. So every method will not be intercepted by this framework. Also, I am using custom attributes and reflection to signify which fields in the business entity need to be audited.

Let’s see how!!

We need to have some settings in the config file to enabling unity and interception.

XML
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
  <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.
   Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.
   Interception.Configuration" />
  <container>
    <extension type="Interception" />
    <register type="AuditTracker.IAuditProcessor, AuditTracker"
              mapTo="AuditTracker.AuditProcessor, AuditTracker" />
    <register type="AuditTracker.IAuditRepository, AuditTracker"
              mapTo="AuditPOC.AuditRepository, AuditPOC" />
    <register type="AuditPOC.IAuditClient, AuditPOC"
              mapTo="AuditPOC.AuditClient, AuditPOC">
      <interceptor type="InterfaceInterceptor"/>
      <interceptionBehavior type="PolicyInjectionBehavior"/>
    </register>
  </container>
</unity

First few lines would enable interception in the application. Audit Processor is one of my key files in this framework. I will cover Audit Repository later. Audit client is the application which needs to consume audit framework. Note that I have added interceptor and interceptor behavior settings as well while registering the Audit Client in Unity framework.

Thereafter, the audit attribute needs to be added in business entity class fields to indicate which field need to be audited. The business entity also needs to implement IAuditableEntity. There is only one method in this interface to define the primary key value in the business entity.

C#
 public class Employee : IAuditableEntity
{
    private string _name =  "Employee1";
    private int _age = 35;
    private int _empNum = 1001;

    [AuditAtttribute(ModuleName = "HR", TableName = "Employee", FieldName = "Name")]
    public string Name
    {
        get
        {
            return this._name;
        }
        set
        {
            this._name = value;
        }
    }

    public string PrimaryKeyIdentifier
    {
        get
        {
            return this._empNum.ToString();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
}

Next is to define the “AuditCalHandler” attributes on the method which needs to be intercepted for auditing.

Following types of methods should be decorated with this attribute:

  • Get methods. This should be decorated else audit framework won’t know the old / db value of the fields which needs to be audited. The old value would be stored in cache for the duration mentioned in config file.
  • Update methods. Method which is updating values from database
  • Delete methods. Method which is deleting records from database

The catch is that AuditCalHandlerAttribute inherits from HandlerAttribute and hence unity interception would decipher that this attribute is being used for interception. Any method which would have this attribute would get intercepted by the class (i.e. AuditCalHandler) as decided by the attribute class.

C#
[AuditCallHandler(false,TransactionType.Read,RequestType.CacheCurrentValue,1) ]
public Employee GetEmployeeDetails()
{
    Employee emp = new Employee();
    return emp;
}

[AuditCallHandler(false, TransactionType.Update, RequestType.SaveAuditDetails, 1)]
public void SaveEmployeeDetails(Employee emp)
{

}

AuditCalHandler would intercept the call and post that specific method action is taken, would execute its own logic to pass the details to AuditProcessor. AuditCalHandler would implement ICallHandler and Invoke method. Invoke method would have access to the input param as well as output value of the method being intercepted which is the main key.

Assumption is that in case of get methods, the entity or list of entity would be the output and in case of save / delete methods, entity to be updated or deleted is the first input to the methods.

Audit processor is a simple class which would cache the db values or process the updated or delete value. This is the class which would use reflection and decipher the custom attribute “Audit” to identify fields which need to be audited.

Audit Processor would finally call a repository class for saving the audit details in database. I have left this control with the application as what needs to be done with the audit entity. The repository class should Implement IAuditRepository and should be registered in the config file as shown above.

In summary, changes needed in the application code where this framework is being plugged in are as follows:

  • Settings in the config file
  • Loading the Unity container from the config if not happening already
  • Decorate the business entity fields with “Audit” attribute which needs to be audited
  • Decorate the methods which need to be intercepted with “AuditCalHandler” attributes
  • Implement a class for saving audit details. The class should implement IAuditRepository

I have not done any performance check of this code, so please use it with due diligence. Also, I am not claiming that this code is written in the best possible way and would handle all scenarios. I have developed this specific to my needs. Others are free to download the code and optimize it or change it.

I have provided the complete code of the audit framework as well as the code the client is using for this framework.

History

  • 11th June, 2016: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --