【问题标题】:asp.net mvc web api 2 custom logger + controller lifecycleasp.net mvc web api 2 自定义记录器 + 控制器生命周期
【发布时间】:2017-04-03 11:14:13
【问题描述】:

故事:我的 asp.net mvc 5 web api 项目中有以下组件(首先使用 ef 代码)

  1. myBaseController : 基础 api 控制器类
  2. myLogger : 我的服装记录器类

    class myBaseController { MyLogger Logger; }

    class MyLogger { public addLog(Log log) { db.logs.add(log); db.saveChanges(); } }

每个 api 控制器使用base.logger.addLog(new log("somethings")) 并且日志立即提交到数据库。

问题:我希望MyLogger 类能够收集内存中的所有日志以及一些将主题一次添加到数据库的位置。 我把它放在了

protected override void Dispose(bool disposing) { logger.AddRange(_logs); }

但它不起作用,似乎对象在此方法中不可用或从内存中抓取

应该如何处理?

【问题讨论】:

  • 在会话中粘贴日志。
  • 您希望如何保留日志条目?按要求?按会话?通过任意时间范围?根据设计,每个控制器都将被框架为每个动作“更新”,这就是你看到这种行为的原因。如果您希望日志在请求中持久存在,则需要将日志持久保存到内存中。
  • 当然日志条目应该在每个请求结束时插入到数据库中(对于每个动作调用)。@PhilCooper

标签: asp.net-mvc asp.net-web-api controller


【解决方案1】:

您不需要单独收集内存中的记录。因为 EF 会为您做到这一点。例如db.logs.add 表示,请将其添加到内存中。但是当您调用SaveChanges 时,它会立即将所有内存中收集的数据提交到数据库。所以你需要实现unit of work pattern (UoW)。通过使用此模式,您将只有one context per request,然后在请求结束时您将调用SaveChanges 方法once。你的代码中不应该有多个SaveChanges,这是你现在的问题。你的addLog方法调用SaveChanges,你的其他方法调用SaveChanges等等。

来自微软的更多信息:Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application

【讨论】:

  • Thnaks Vahid,您的解决方案很酷,那么我应该在哪里添加最后一个 SaveChanges 方法?我应该设置服装过滤器属性吗? @VahidN
  • 每个请求应该只有一个上下文,然后使用依赖注入注入它。更多波斯语信息:dotnettips.info/post/842 和 dotnettips.info/courses/topic/5/…
  • 谢谢,让我试试@VahidN
【解决方案2】:

您需要在请求周期中将条目存储在内存中,并在请求结束时将这些条目保存到数据库中

 protected void Application_EndRequest()
    {
      //get entries from memory/session/cache whatever your source to store entries
      //do stuff to save entries
    }

【讨论】:

    【解决方案3】:

    我通常会创建 ActionFilterAttributes,并将其放置在我想要记录任何活动的操作方法上。

    TraceMvcAttribute

    public class TraceMvcAttribute : ActionFilterAttribute
    {
       // IoC container will inject this dependencies.
       public IWebUserSession WebUserSession { get; set; }
       public IDateTime DateTime { get; set; }
       public ITraceListener TraceListener { get; set; }
    
       public override void OnActionExecuting(ActionExecutingContext filterContext)
       {
          var traceLog = new TraceLog
          {
             Controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName,
             Action = filterContext.ActionDescriptor.ActionName,
             Message = JsonConvert.SerializeObject(filterContext.ActionParameters),
             PerformedOn = this.DateTime.Now,
             PerformedBy = WebUserSession?.UserName
          };
          TraceListener.AddTraceLogAsync(traceLog);
          base.OnActionExecuting(filterContext);
       }
    }
    

    TraceApiAttribute

    Web API 过滤器与 MVC 过滤器有点不同。我在 Git 的 my sample code 中没有它;以防万一你想看看它。

    public class TraceApiAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            // http://autofac.readthedocs.org/en/latest/integration/webapi.html#standard-web-api-filters-are-singletons
            // All filter attributes in Web API are effectively singleton instances that exist 
            // for the entire lifetime of the application. We must use service location, 
            // since we need per-request services in your filters.
            var requestScope = actionContext.Request.GetDependencyScope();
            var datetime = requestScope.GetService(typeof(IDateTime)) as IDateTime;
            var webUserSession = requestScope.GetService(typeof(IWebUserSession)) as IWebUserSession;
            var traceListener = requestScope.GetService(typeof(ITraceListener)) as ITraceListener;
    
            var traceLog = new TraceLog
            {
                Controller = actionContext.ControllerContext.ControllerDescriptor.ControllerName,
                Action = actionContext.ActionDescriptor.ActionName,
                Message = JsonConvert.SerializeObject(actionContext.ActionArguments.Where(x => x.Key != "request").ToList()),
                PerformDateTime = datetime.Now,
                PerformBy = webUserSession?.UserName
            };
            traceListener.AddTraceLogAsync(traceLog);
            base.OnActionExecuting(actionContext);
        }
    }
    

    然后我像this一样查看日志历史记录 -

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-01
      • 2018-02-20
      • 2016-11-21
      相关资源
      最近更新 更多