Entity Framework Core Audit Trail With Audit.Net
Tags: dotnetcore, efcore, dotnet, backend
Published: 2024-03-19 10:50:11


### What is Audit Trail?

Audit trail is a record of all user activities within an application. It captures details like who accessed the application, what changes were made, and when they occurred. By maintaining an audit trail, developers can track data modifications, identify unauthorized access, and ensure compliance with industry regulations.

### Audit.Net

[Audit.NET](https://github.com/thepirat000/Audit.NET) is Nuget package that can use to implement Audit Trail in dotnet applications. Instead of implement an audit trial manually, we can use this to easily add audit trial to our application.
For Entity Framework Core, they have provided a package called [Audit.EntityFramework.Core](https://www.nuget.org/packages/Audit.EntityFramework.Core). In this blog post, let's see how to use this package to implement audit trial in ASP.Net Core application with Entity Framework Core.

---

### Let's Start

First clone this github repository and open project in Visual Studio. I will implement audit trial to this blazor project. In this article I use Blazor Server App using dotnet 6.0.

```
git clone git@github.com:HRS0986/AuditTrialDemo.git
```


After opened, you can see folder structure like this

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8wrags3zuzy9hfgriurd.png)

Now let's install Audit.EntityFramework.Core package


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g3fwcnn4m08ampjc0rj4.png)

They have provided more than one ways to implement audit trial with this package. I will do this in the most easiest way. After installing, go to ApplicationDbContext.

```C#
// Data.ApplicationDbContext.cs - Before
 public class ApplicationDbContext : DbContext
 {
     public virtual DbSet<Book> Books { get; set; }

     public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }

     protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { }

     protected override void OnModelCreating(ModelBuilder modelBuilder)
     {
         modelBuilder.Entity<Book>(entity =>
         {
             entity.Property(e => e.Id).IsRequired().UseIdentityColumn();
             entity.Property(e => e.Title).IsRequired();
             entity.Property(e => e.Description).IsRequired();
             entity.Property(e => e.Author).IsRequired();
         });
     }
 }
```

We have to inerit our ApplicationDbContext class from the AuditDbContext instead of DbContext.

```C#
// Data.ApplicationDbContext.cs - After
 public class ApplicationDbContext : AuditDbContext
 {
     public virtual DbSet<Book> Books { get; set; }

     public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }

     protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { }

     protected override void OnModelCreating(ModelBuilder modelBuilder)
     {
         modelBuilder.Entity<Book>(entity =>
         {
             entity.Property(e => e.Id).IsRequired().UseIdentityColumn();
             entity.Property(e => e.Title).IsRequired();
             entity.Property(e => e.Description).IsRequired();
             entity.Property(e => e.Author).IsRequired();
         });
     }
 }
```

Then run the project. Do some action. Delete book, Add new book or Update book. You can see a json file in the project root. If you open that file, you can see a json object like this.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9wzfnufckhuxfqefx8ig.png)

Now let's create separete folder for audit logs and add configurations to write audit logs in that folder. Add this configuration to program.cs Replace **_YOUR_FOLDER_PATH_** with your foder path where you want to save your audit logs. If you want to chage the file name of the json. change **{auditEvent.Environment.UserName}_{DateTime.Now.Ticks}.json** to you file name

```C#
// Program.cs
Audit.Core.Configuration.Setup()
    .UseFileLogProvider(config => config
        .DirectoryBuilder(_ => $@"YOUR_FOLDER_PATH\")
        .FilenameBuilder(auditEvent => $"{auditEvent.Environment.UserName}_{DateTime.Now.Ticks}.json"));
```

Now our audit trial is working. But some times when your perform update action, the OriginalValue and the NewValue properties can contain same NewValue. This is not what we want. To fix this simple put [AuditDbContext(ReloadDatabaseValues = true)] attribute on the ApplicationDbContext Class like this.

```C#
[AuditDbContext(ReloadDatabaseValues = true)]
public class ApplicationDbContext : AuditDbContext
{
    public virtual DbSet<Book> Books { get; set; }
...
```

This is the easiest way to use Audit.EntityFramework.Core package. You can customize this as you want. They have provided many options with this. If you read their documentation, you can find more details. That's all for now. Happy Coding !

If this blog is helpful to you, don't forget to give a like

<a href="https://www.buymeacoffee.com/hirushafernando" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/yellow_img.png" alt="Buy Me A Coffee" style="height: 71px !important;width: 204px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

You can reach me on

- [My Portfolio](https://hirushafernando.com/)

- [Github](https://github.com/HRS0986)

- [Medium](https://medium.com/@heshanhfernando)

- [LinkedIn](https://www.linkedin.com/in/hirusha-fernando-webdev/)