在Web应用程序中何处以及如何使用拦截器?

Any*_*One 7 .net c# asp.net-mvc inversion-of-control interceptor

我最近对拦截器概念感兴趣.我知道这个概念在许多库中使用,如NHibernate,Entity Framework等.但我对如何在ASP.NET MVC Web应用程序中使用此概念感兴趣.

在Mvc Web应用程序中使用它有用吗?

有没有使用拦截器的开源Asp.Net Mvc项目?

Asp.net Mvc已经支持一种带过滤器的控制器拦截器.最好使用过滤器而不是拦截器?

Dan*_*ing 13

何时/何时使用拦截器

查看您开发的先前应用程序并检查代码.查找在方法和属性的开头或结尾经常重复的代码.这是您可以考虑从所有这些方法转移到拦截器的代码.例如,我注意到我的许多执行输入验证的MVC操作使用相同的几行代码:

if (!ModelState.IsValid)
    return View(model);
Run Code Online (Sandbox Code Playgroud)

这是可能被移动到拦截器的代码(在这种情况下可能是MVC过滤器).编写和应用过滤器的成本是否超过此重复代码的成本?(2行代码乘以使用此代码的控制器操作数).在这种情况下,也许不是.然而,在其他情况下,使用拦截器的好处会更大.

下面是一些情况,我想这类型的代码重复可能发生,即一个列表是场景的气味像他们能从中获益的拦截器:

  • 输入验证(如上图所示).
  • 调试日志. 您可以编写一个拦截器来记录每个方法调用的入口和出口.
  • 线程同步. 您的问题是关于Web应用程序,但如果您正在开发具有MVP样式视图的Windows应用程序,则可以应用拦截器以确保所有方法调用都同步回UI线程.
  • 数据库事务. 我的大多数数据库事务代码如下所示:

 

using (var transaction = Session.BeginTransaction())
{
    // ... do some work that is unique to this method ...
    transaction.Commit();
}
Run Code Online (Sandbox Code Playgroud)
  • PropertyChanged事件实现. 这段代码通常非常重复并且很难编写. Sacha Barber彻底探索了如何使用各种框架自动实现此事件.
  • 安全. 您的应用程序中可能有许多方法仅限于某些用户. AuthorizeAttribute是一个过滤器.
  • Web服务请求限制. 某些API(例如Basecamp的API)要求您将请求限制为每个给定时间范围内的特定数量的请求.如果您编写了Basecamp客户端类,则可以对其应用拦截器,以确保所有方法调用都符合速度限制,并Thread.Sleep在必要时使用.
  • 结果缓存. MVC为此目的预先构建了一些过滤器.您可以编写自己的拦截器来缓存UI层下面的图层的结果.
  • WCF错误处理.Dispose如果它处于Faulted状态, 则不能是WCF客户端,因此创建和销毁客户端实例的每个方法都需要检查状态,然后Abort在必要时调用而不是简单地using在客户端周围包装子句.在这种情况下,拦截器可能不是最合适的.修复Dispose实现或使用某种包装可能更容易.

上述示例是否适合作为拦截器的候选者取决于您的应用程序的独特复杂性.这个列表当然不是详尽无遗的,也不是.拦截器的可能应用与您编写的应用程序一样多种多样.

如何使用拦截器

我可以想到您可能想要应用拦截器的三个主要位置:控制器,服务和域对象.

  • 使用MVC控制器,最有意义的是继续​​使用MVC的过滤器.
  • 对于您将从IoC容器中取出的中间层服务,过滤器不是一个选项(因为它不是控制器),因此您应该使用IoC容器拦截功能.
  • 对于您的域对象,您通常使用构造函数直接实例化(如果它是新实体)或从您选择的ORM中获取(如果它是现有实体),您将需要使用某种对象工厂而不是构造函数并指导您的ORM如何使用工厂.

关于如何完成所有这些的细节具体取决于您使用的工具.


Mar*_*ann 5

拦截可用于许多事情 - 最值得注意的是解决横切问题,如仪表,记录,审计,安全,计量等.

不需要DI容器来应用这个概念,但它有所帮助.

您可以使用ASP.NET MVC过滤器来实现大致相同的效果,但是当您可以应用通常可重用的实现时,为什么要将自己限制在MVC框架中?


the*_*kip 0

我想说你使用更通用的 DI 容器来注入依赖项。这不仅将依赖项注入到您的控制器中,而且还提供这些依赖项的依赖项,从而生成所有依赖对象的完整对象图。

在前端使用 DI 容器也带来了很好的机会,使您的后端更具单元测试性和松散耦合性。