none
How do I create a class to help me log my application user activity? (clean coding and code refactoring question) RRS feed

  • Question

  • Currently when a user performs a CRUD action I log it in the database:

    var user = User.Identity.Name;
    var log = (from l in db.AppLogs where l.UserName == user select l).ToList();
    var logresult = (from lr in log select lr).LastOrDefault();
    var loggedUser = (from lu in db.AMProfiles where lu.UserName == logresult.UserName select lu).SingleOrDefault();
    var logAppName = "My Application";
    var logRequestType = "Create New Movie - " + Movie.Name;
    
    if (ModelState.IsValid)
    {
        AMLog userLog = new AMLog
        {
            CreateDate = DateTime.Now,                 
            UserId = Convert.ToInt32(loggedUser.EmployeeId),
            AppName = logAppName,
            RequestType = logRequestType,
            LogId = logresult.Id
        };
        db.MADMovies.Add(mADMovies);
        db.SaveChanges();
    }

    The problem here is that I know this is not very clean, repetitive and that there should be a better way of doing this.

    What I would like to do instead is use a class that gets called when a CRUD action is performed. How is this done?

    Tuesday, May 28, 2019 5:30 PM

Answers

  • There are quite a few different ways to do this. At the lowest level you can use the DB to handle this. If you have auditing columns on the DB table then they can handle the auditing automatically (irrelevant of where the changes come from). If you set up auditing tables you can use triggers to record what is changing as well. This is most useful for determining what data is in your database and who put it there but not necessarily why.

    At a higher level if you simply want to log that your app was used to make a change then you can do that at the app level. Since it appears you're using EF you could override the save method, examine what is about to be changed and then log the appropriate information after the save is successful. This would allow you to pick and choose what is getting logged.

    If you need an even higher level of logging such that you know that somebody called your XYZ method to make changes then you're going to have to hook into the code at the higher level. This is where a class hierarchy would be useful. For example suppose that you are implementing an `IUserService` interface and you want to log when different overloads are called. Hook the logging in at that point. If you rely on a higher level service then an abstract base class could be responsible for logging the actual event and then calling (before or after) the actual service logic.

    You could get really complex, although in my experience it doesn't gain you anything, by injecting the behavior using a third party library like PostSharp or something. In this way you could have all your method instrumented. But unless you really need this level of functionality it probably isn't worth the effort.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, May 28, 2019 6:11 PM
    Moderator