在ASP.NET MVC中的面向方面编程

8
我目前正在开发一个ASP.NET的MVC应用程序,我试图分离关注点以便获得更清洁和更易维护的代码。
因此,作为起点,我考虑了一个记录日志的方面。我的想法是最初记录每个控制器中每个方法的调用和返回情况。我会把这个逻辑放在一个专门用于记录日志的单独类中,这样我就不会在代码中到处乱加记录语句。
我还需要访问Http请求,以便获取客户端信息。
是否有集成的方式来做到这一点?ASP.NET MVC可以像Java中的AspectJ一样使用方面文件吗?
另外,它后来可以被配置为记录满足特定条件的方法吗?(例如签名、返回值、异常抛出等)
非常感谢!
1个回答

12
你可以使用属性以面向方面的方式实现特性。然后,你想要用你的功能包围的动作方法只需要用你的属性进行装饰:
[CustomLogger]
public ActionResult Index()
{
    // Doing something here ...
    return View();
}

你可以在一个操作方法、整个控制器,甚至通过 ASP.NET MVC 的 GlobalFilterCollection 全局应用属性。

以下是声明属性的方式:

public class CustomLoggerAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        // Here goes your logic
    }

    // ...
}

ActionFilterAttribute 类允许您重写一些方法,以便您可以钩入 ASP.NET MVC 的操作执行管道:

  • OnActionExecuting
  • OnActionExecuted
  • OnResultExecuting
  • OnResultExecuted

您可以通过传递给上述方法的参数(如 ActionExecutedContext)访问请求变量。


这很有趣,它可以在控制器级别使用吗?我的意思是,注释类,以便自动应用于该控制器的所有操作。 即使是这种情况,我也不喜欢注释我的控制器的想法,我正在考虑一种更透明的方式,以便控制器和日志记录方面完全独立。控制器不应该知道它是否正在被记录。 - Matias Cicero
2
@MatiCicero 现在你比我快了。;-) 是的,你可以将属性范围限定为单个操作方法、整个控制器或 ASP.NET MVC 应用程序中的每个控制器。这样,不需要任何一个控制器知道该属性 - 只使用 GlobalFilterCollection.Filters 即可;此外,您不会忘记将属性应用于某个控制器,这对于身份验证/授权目的非常有用。 - Marius Schulz
好的,现在我们开始谈论@Marius Schulz!! 我喜欢这个想法,它可以用来不记录所有操作,而只记录满足某些标记的特定操作吗? 我正在考虑使用反射,但如果有自动化的方法做到这一点,我全听着! - Matias Cicero
@MatiCicero 是的,这是可能的。提供的 filterContext 变量包含一个类型为 ActionDescriptor 的属性,该属性提供有关签名、参数等信息。 - Marius Schulz
我想这种方法涵盖了我需要的一切,我将尝试并回来告诉你消息,我会将其标记为已接受的答案!谢谢! - Matias Cicero
1
@Mati Cicero,你最终对使用这种方法感觉如何?你尝试过任何AOP库吗?你是否坚持使用这种方法还是已经改变了想法? - puddinman13

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接