Recently, I was tasked with building an audit trail log for a legacy WinForms VB.NET project that uses Entity Framework v6.4 on .NET 4.5. Rather than reinventing the wheel, I opted for an open-source library like Audit.NET v20.2.4.
The default settings are quite nice, as they list all changes by column name and map the original value to the updated value. However, what if you want to use human friendly model property name as column names in the changes list in the audit log? For example, my models already use <Display>
attributes like so:
<Display(Name:="Witness")>
Public Property Personnel2 As String
<Display(Name:="Another Personnel")>
Public Property Personnel1Lv As String
<Display(Name:="Another Witness")>
Public Property Personnel2Lv As String
After making updates to the model, your default audit event will look like this:

As you can see, the columnNames
were not affected by this attribute. So, what needs to be done in the list of changes to support custom property names in this location?
Note, that Audit.NET uses two JSON serializers:
System.Text.Json
for .NET5 and aboveJson.NET
for lower frameworks
So, in my case, I am using Json.NET
. The good news is that Json.NET
already provides the <JsonProperty>
attribute specifically for this purpose. Therefore, I adjust my model accordingly:
<Display(Name:="Witness")>
<JsonProperty("Witness")>
Public Property Personnel2 As String
<Display(Name:="Another Personnel")>
<JsonProperty("Another Personnel")>
Public Property Personnel1Lv As String
<Display(Name:="Another Witness")>
<JsonProperty("Another Witnes")>
Public Property Personnel2Lv As String
As a result, if you enable IncludeEntityObjects()
in Audit.EntityFramework.Configuration
, the property names are affected in the Entity
field but not in the Changes
field. Could this be changed?

Apparently, the library does not provide a setting to automatically use human-friendly column names. However, it does offer some post-processing hooks that you can use to achieve this behavior:
Public MustInherit Class AuditDbContext
...
Public Overridable Sub OnScopeSaved(auditScope As IAuditScope)
Public Overridable Sub OnScopeSaving(auditScope As IAuditScope)
Public Overridable Sub OnScopeCreated(auditScope As IAuditScope)
...
End Class
You can use these hooks in whatever way best suits your needs. In my case, I used the following method, which does exactly what you’d expect: it reads the DisplayAttribute
or JsonPropertyAttribute
and uses their properties to dynamically change column names.
Public Overrides Sub OnScopeCreated(scope As IAuditScope)
MyBase.OnScopeCreated(scope)
Dim [event] = scope.GetEntityFrameworkEvent()
If [event] Is Nothing OrElse [event].Entries Is Nothing Then Return
For Each item In [event].Entries
If item.Entity Is Nothing Then Continue For
Dim entityType = item.Entity.GetType()
If item.Changes Is Nothing Then Continue For
For Each change In item.Changes
Dim propInfo = entityType.GetProperty(change.ColumnName)
If propInfo Is Nothing Then Continue For
Dim displayAttrs = propInfo.GetCustomAttributes(GetType(DisplayAttribute), True)
If displayAttrs IsNot Nothing AndAlso displayAttrs.Length > 0 Then
Dim displayAttr = TryCast(displayAttrs(0), DisplayAttribute)
If displayAttr IsNot Nothing AndAlso Not String.IsNullOrWhiteSpace(displayAttr.Name) Then
change.ColumnName = displayAttr.Name
Continue For
End If
End If
Dim jsonAttrs = propInfo.GetCustomAttributes(GetType(JsonPropertyAttribute), True)
If jsonAttrs IsNot Nothing AndAlso jsonAttrs.Length > 0 Then
Dim jsonAttr = TryCast(jsonAttrs(0), JsonPropertyAttribute)
If jsonAttr IsNot Nothing AndAlso Not String.IsNullOrWhiteSpace(jsonAttr.PropertyName) Then
change.ColumnName = jsonAttr.PropertyName
End If
End If
Next
Next
End Sub