在MVC .NET中执行日志记录操作

时间:2009-09-01 16:54:32

标签: asp.net asp.net-mvc inversion-of-control

我正在尝试找出在我正在开发的应用程序中执行日志记录的最佳方法。

现在,我有一个Log表,用于存储用户名,时间戳,操作,控制器和消息。当控制器被实例化时,它通过Castle Windsor获得IoC信息。

例如,我的“Sites”控制器创建如下:

    private ISitesRepository siteRepository;
    private ILogWriter logWriter;

    public SiteController(ISitesRepository siteRepository, ILogWriter logWriter)
    {
        this.siteRepository = siteRepository;
        this.logWriter = logWriter;
    }

并且日志编写器具有创建和插入日志条目(WriteToLog)的功能。在Sites控制器的Edit和Create操作中,它调用WriteToLog函数。

这正在发挥作用,但我的问题是 - 我真的需要以这种方式设置每个控制器,通过ILogWriter接口/存储库吗?让我感到震惊的是,我可以设置一个LogController,并且只需要对我的日志进行“繁重的工作”。

这样,我不必在每个其他控制器中弄乱IoC的东西。是否可以在另一个控制器上执行操作(例如,LogController-> WriteLog)?我不确定如果不进行重定向会怎么做......

2 个答案:

答案 0 :(得分:1)

你可以通过一个抽象类吗?这个抽象类有一个引用你日志编写器的静态属性吗?

类似这样的事情

public abstract class BaseController
{
    public static ILogWriter Logwriter{get;set;}
    public static BaseController
    {
        Logwriter = YourFactory.GetLogwriter();
    }
}

public class YourController:BaseController
{
    public YourController(ISitesRepository siteRepository)
    {
    }
}

答案 1 :(得分:1)

好的,经过多次头疼,我认为我找到了一个可以接受的解决方案。

我将自己的日志记录操作实现为自定义操作过滤器,如下所示:

public class LogAction : ActionFilterAttribute, IActionFilter
{
    public LogLevel loglevel;
    public string message;


    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ILogWriter logWriter = AppServiceFactory.Instance.Create<ILogWriter>();

        logWriter.WriteToLog(
          filterContext.ActionDescriptor.ControllerDescriptor.ControllerName, 
          filterContext.ActionDescriptor.ActionName,
          loglevel,
          filterContext.HttpContext.Timestamp,
          filterContext.HttpContext.User.Identity.Name.ToString(),
          message + "(id=" + filterContext.RouteData.Values["id"] + ")");
    }

}

但我试图让IoC在自定义属性过滤器中工作。搜索stackoverflow和谷歌搜索,我发现这很难做,谈论使用不同的包装器,动作调用器等,这似乎比我真正愿意处理的更复杂。

试图了解有关IoC的更多信息(我还是很新),我发现this article, 这真的帮助我指明了正确的方向。我用我的WindsorControllerFactory添加了他密封的AppServiceFactory类,它就像一个魅力。

正如我所说,我对MVC和这个IoC的新东西很新,所以我不确定这是处理事物的理想方式 - 但它看起来很简单,它到目前为止都有效。我欢迎任何通过这种方法处理它的评论或批评。

<强>更新 想出了一种不同的方法 - 在我的WebUI项目中创建了一个函数:

public static class Loggers
{
    public static void WriteLog(ControllerContext controllerContext, LogLevel logLevel, string message)
    {
        ILogWriter logWriter = AppServiceFactory.Instance.Create<ILogWriter>();
        logWriter.WriteToLog(
            controllerContext.RouteData.Values["controller"].ToString(),
            controllerContext.RouteData.Values["action"].ToString(),
            logLevel,
            controllerContext.HttpContext.Timestamp,
            controllerContext.HttpContext.User.Identity.Name.ToString(),
            message);
    }
}

现在,无论我想记录什么,我都可以打电话

            Loggers.WriteLog(
            this.ControllerContext,
            LogLevel.Membership,
            "Removed role '" + role + "'" + " from user " + _userService.Get(id).UserName );

将记录写入日志。这为我的“消息”内容提供了更大的灵活性,并解决了包含登录global.asax文件的问题,即使不是不可能使用属性过滤器也是如此。我会留下剩下的,因为它可能对其他人有用,但我认为这是我将继续这样做的方式。

像往常一样,MVC中的事情通常比原先认为的更简单:)