0

I figured I could use actionfilters in MVC 4 to log when someone create, edits or deletes a row from the database. I can log the controller name, action name, IP and Identity no problem. But I also want to write to the database, the entire row that has been deleted. I also want to write to the database, the changes that have been made to the row. I want this filter to be reusable for multiple controllers.

I wrote some code, but I pretty much got stuck.

public class ActivityLog : ActionFilterAttribute, IActionFilter
    {
        private readonly DbContext1 _db = new DbContext1();

        void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (!filterContext.Controller.ViewData.ModelState.IsValid) return;
            string parameters;
            var formParams = filterContext.HttpContext.Request.Form;

            switch (filterContext.ActionDescriptor.ActionName.ToUpper())
            {
                case "CREATE": //show created object in log parameters
                    parameters = "{" +
                                 String.Join(", ",
                                     formParams.Cast<string>()
                                         .Where(
                                             x =>
                                                 x != "__RequestVerificationToken" &&
                                                 !String.IsNullOrWhiteSpace(formParams[x]))
                                         .Select(x => x + ":" + formParams[x])) + "}";
                    break;
                case "EDIT": //show only changes in object in log parameters
                    parameters = JsonConvert.SerializeObject(/*dunno what to put here*/);
                    break;
                case "DELETE": //show deleted object in log parameters
                    parameters = JsonConvert.SerializeObject(/*dunno what to put here*/);
                    break;
                default:
                    return;
            }

            var log = new Models.ActivityLog()
            {
                DateTime = filterContext.HttpContext.Timestamp,
                Controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
                Action = filterContext.ActionDescriptor.ActionName,
                UserId = filterContext.HttpContext.User.Identity.Name,
                IP = filterContext.HttpContext.Request.UserHostAddress,
                Parameters = parameters
            };
            _db.ActivityLog.Add(log);
            _db.SaveChanges();
            base.OnActionExecuted(filterContext);
        }
    }
  • Instead of using filters, you could use the dbChangeTracker. [http://stackoverflow.com/questions/28627685](http://stackoverflow.com/questions/28627685/entity-framework-6-code-first-entity-versioning-and-auditing/28627926#28627926) – markpsmith Apr 14 '15 at 14:12
  • @markpsmith dbChangeTracker seems like a feasible way to get the job done, although I'm not a big fan of having to put [donotlog] attributes on actions that I don't want to log. – Dannyboyng Apr 14 '15 at 14:47
  • use the decorator pattern on your repository – Ewan Apr 14 '15 at 14:53

0 Answers0