I need to log certain user actions, such as Login, logout, CRUD, etc. and save to a table called AuditRecords
. I have a DbContext
called AuditContext
:
I have learned that applying an ActionFilter
and decorate a controllermethod with it is the way to go. The AuditContext
is causing a red squiggly asking for the ‘options’, which baffles me. I have tried DI, but got the same results. Any thoughts? I am on DotNet 5.01, but I tried it withg DotNet 6 as well with the same results.
EDIT
I changed the AuditAttribute and Context to make it as straightforward as possible and by using Dependency Injection, as advised. But the problem is still not solved.
public class Audit
{
//Audit Properties
public Guid AuditID { get; set; }
public string UserName { get; set; }
public string IPAddress { get; set; }
public string AreaAccessed { get; set; }
public DateTime Timestamp { get; set; }
//Default Constructor
public Audit() { }
}
public class AuditContext : DbContext
{
public DbSet<Audit> AuditRecords { get; set; }
}
public class HomeController : Controller
{
//red squiggly under [Audit] decoration with error of no formal
//parameter 'context' in AuditAttribute.AuditAttribute(AuditContext)
[Audit]
public IActionResult Privacy()
{
return View();
}
//AuditAttribute class
using Microsoft.AspNetCore.Mvc.Filters;
using System;
namespace LoggingDemoMVC.Filters
{
public class AuditAttribute : ActionFilterAttribute
{
private readonly AuditContext _context;
public AuditAttribute(AuditContext context)
{
_context = context;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//Stores the Request in an Accessible object
var request = filterContext.HttpContext.Request;
//Generate an audit
Audit audit = new Audit()
{
//Your Audit Identifier
AuditID = Guid.NewGuid(),
//Our Username (if available)
UserName = (filterContext.HttpContext.User.Identity.IsAuthenticated) ? filterContext.HttpContext.User.Identity.Name : "Anonymous",
//The IP Address of the Request
IPAddress = request.Path,
//The URL that was accessed
AreaAccessed = request.HttpContext.Request.Path,
//Creates our Timestamp
Timestamp = DateTime.UtcNow
};
//Stores the Audit in the Database
_context.AuditRecords.Add(audit);
_context.SaveChanges();
//Finishes executing the Action as normal
base.OnActionExecuting(filterContext);
}
}
}
2
Answers
WebAppContext
expects aDbContext<WebAppContext>
to be passed into its constructor . However , you are calling the constructor without providing anything :To fix the issue , you can just plug into the Dependency Injection system that you’ve set up
Simple Demo :
model
DataContext
Custom Filter
Startup
controller
when I access
Privacy
method , The database will add a row of dataFirst, add the Nuget package
Microsoft.EntityFrameworkCore.SqlServer
to your project.Then, add the following code to the
ConfigureServices
method of yourStartup
class:That’s the bare minimum and this will enable you to inject the DbContext into the
ActionFilter
.