4

I am trying to add a logging function to save to my SQL server database. I tried to create ActionFilter class and apply on one of my controller but not working. i want to capture userid, IP address, controller and action visit and timestamp. What am i missing?

AuditAttribute Action Filter class

public class AuditAttribute : ActionFilterAttribute
{
    private readonly ApplicationDbContext _db;

    //Inject ApplicationDBContext
    public AuditAttribute(ApplicationDbContext db)
    {
        _db = db;
    }

    IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {

         //Stores the Request in an Accessible object
         var request = filterContext.HttpContext.Request;

        //Generate an audit
        Portal_Logger audit = new Portal_Logger()
        {
            teacherNRIC = filterContext.HttpContext.User.Identity.Name,
            IPAddress = Convert.ToString(ipHostInfo.AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork)),
            ControllerAccess = (string)filterContext.RouteData.Values["controller"],
            Timestamp = DateTime.Now,
        };

         public DbSet<Portal_Logger> Portal_LoggerDBSet { get; set; }
        //Store objects to database
        _db.Portal_LoggerDBSet.Add(audit);
        _db.SaveChanges();

        base.OnActionExecuting(filterContext);
    }

}
}     


Home controller class
[AuditAttribute]
public class HomeController : Controller
{ ..content of controller
}


Portal_logger model class
public class Portal_Logger
{
    [Key]
    public int LoggerId { get; set; }

    [StringLength(10)]
    public string userid{ get; set; }

    [StringLength(50)]
    public string IPAddress { get; set; }

    [StringLength(50)]
    public string ControllerAccess { get; set; }

    public DateTime? Timestamp { get; set; }

}

Please see the error message as attached image Screenshot of error message

I tried and have a new issue. enter image description here

I tried this method also not working. [AuditActionFilter] -> Error message (AuditActionFilter is not an attribute class)

public class HomeController : Controller
{
}

I tried this method but not working still.

[AuditActionFilter] - error message -> "AuditActionFilter" is not an 
public class HomeController : Controller
{
}

I have added services.AddMVC to startup.cs
services.AddMvc(options => options.Filters.Add(typeof(AuditActionFilter)));

This is the AuditActionFilter.cs

public class AuditActionFilter : IActionFilter
{
    private readonly ApplicationDbContext _db;

    public AuditActionFilter(ApplicationDbContext db)
    {
        _db = db;
    }

    IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
    public void OnActionExecuting(ActionExecutingContext filterContext)
    {

        var request = filterContext.HttpContext.Request;

        Portal_Logger audit = new Portal_Logger()
        {
            teacherNRIC = filterContext.HttpContext.User.Identity.Name,
            IPAddress = Convert.ToString(ipHostInfo.AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork)),
            ControllerAccess = (string)filterContext.RouteData.Values["controller"],
            Timestamp = DateTime.Now,
        };

        //Store objects to database
        _db.Portal_LoggerDBSet.Add(audit);
        _db.SaveChanges();
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // do something after the action executes or leave it empty
    }

}
1
  • What's not working? Do you get any errors? Commented Aug 22, 2018 at 11:32

4 Answers 4

3

For using AuditAttribute on the specific method or controller, you could try ServiceFilterAttribute or TypeFilterAttribute.

Here are the available two options:

Option1

Use TypeFilterAttribute.

[TypeFilter(typeof(AuditAttribute))]
public class HomeController : Controller

Option2

Use ServiceFilterAttribute

  1. Register AuditAttribute in Startup.cs

     services.AddScoped<AuditAttribute>();
    
  2. Use AuditAttribute

     [ServiceFilter(typeof(AuditAttribute))]
     public class HomeController : Controller
    
Sign up to request clarification or add additional context in comments.

4 Comments

Can I have more details for Option 1 and 2 ?
@xingtan check this document Dependency injection
Tks Tao Zhou. Will check that out.
Any idea how to set properties of the action filter attribute?
0

The error is occurring because you have a parameter of "DbContext" on your attribute, but you are not supplying it when applying it to the controller?

public AuditAttribute(ApplicationDbContext db)
{
    _db = db;
}

Comments

0

How to use DI in Action filters is described here: https://www.c-sharpcorner.com/blogs/custom-filter-in-mvc-or-logging-using-mvc-filter

The article in short:

Enable for all controllers:

starup.cs:

services.AddMvc(options =>  
{  
   options.Filters.Add(typeof(AuditAttribute));  
});

Enable for only one controller:

starup.cs:

services.AddScoped<AuditAttribute>();

Next you place on the controller or action method:

[ServiceFilter(typeof(AuditAttribute))] 

Comments

0

To use the attribute without having to resort to [TypeFilter(typeof(AuditAttribute))] or [ServiceFilter(typeof(AuditAttribute))] it should be possible to get the ApplicationDbContext by using filterContext.HttpContext.RequestServices.GetService instead of through the constructor.

public class AuditActionFilter : IActionFilter
{

public AuditActionFilter(){}

IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());

public void OnActionExecuting(ActionExecutingContext filterContext)
{
    ApplicationDbContext _db = filterContext.HttpContext.RequestServices.GetService<ApplicationDbContext>();

    var request = filterContext.HttpContext.Request;

    Portal_Logger audit = new Portal_Logger()
    {
        teacherNRIC = filterContext.HttpContext.User.Identity.Name,
        IPAddress = Convert.ToString(ipHostInfo.AddressList.FirstOrDefault(address => address.AddressFamily == AddressFamily.InterNetwork)),
        ControllerAccess = (string)filterContext.RouteData.Values["controller"],
        Timestamp = DateTime.Now,
    };

    //Store objects to database
    _db.Portal_LoggerDBSet.Add(audit);
    _db.SaveChanges();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.