gpt4 book ai didi

c# - ASP.NET MVC3 Controller AOP 代理不拦截所有方法,只有 IController.Execute

转载 作者:太空狗 更新时间:2023-10-30 00:55:57 25 4
gpt4 key购买 nike

我有一个包含多个层的项目 - 其中包括 Web 前端 (ASP.NET MVC3) 和服务后端(主要是业务逻辑)。该项目已有几个月的历史,因此一切都按预期进行。现在,我正在尝试使用自定义 [Log] 属性向某些 MVC3 Controller 方法添加日志记录方面。

我正在使用 Castle Windsor用于依赖注入(inject)。为了获得日志记录方面,我利用 Castle DynamicProxy通过SNAP .正在使用 WindsorControllerFactory 解析 Controller 来自 Krzysztof Koźmic 的有用教程 - 但我对其进行了修改以查找 Controller 的默认界面(见下文)。

在我的服务层:

[Log(LoggingLevel.Info)]
public void Save(MyBusinessDto dto)
{
// business logic and other checks

this.repository.Save(mbo);
}

在我的网络前端的 IWindsorInstaller对于 Controller :

private static BasedOnDescriptor FindControllers()
{
return AllTypes
.FromThisAssembly()
.BasedOn<IController>()
.WithService.DefaultInterface();
}

在我的(稍微自定义的)WindsorControllerFactory 中,它寻找 Controller 的默认接口(interface):

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
throw new HttpException(404, string.Format(Error404, requestContext.HttpContext.Request.Path));
}

string controllerName = controllerType.Name;
string defaultInterfaceName = 'I' + controllerName;
Type defaultInterface = controllerType.GetInterface(defaultInterfaceName);

object controller = this.kernel.Resolve(defaultInterface);

return (IController)controller;
}

在我的 Controller 中:

public class MyBusinessController : MyBusinessControllerBase, IMyBusinessController
{
[Log(LoggingLevel.Debug)]
public ActionResult CreateOrUpdate(MyBusinessFormModel fm)
{
// Convert form model to data transfer object,
// perform validation and other checks

this.service.Save(dto);

return View(fm);
}
}

这在服务项目中一切正常,但在 Controller 中,方法没有被拦截。

  • 我已确认 WindsorControllerFactory 返回代理 Controller 。
  • 我已确认 Controller 已注册拦截器。
  • 我已经确认 SNAP 中的 MasterProxy 拦截了 Controller - 但它只拦截了 IController.Execute(RequestContext requestContext)

我如何拦截所有具有我的[Log] 属性的 Controller 方法?

更新 1:我考虑过直接使用 DynamicProxy 而不是 SNAP,但这是次要的,因为它也适用于 Controller 。

更新 2+4:似乎 SNAP 从 github 中丢失 back on github .

更新 3:这是我在插入 WindsorControllerFactory 时在 Visual Studio 调试器中看到的(见上文)。检查的 controller 变量是返回给 MVC 的,它确实被代理了。

  • Controller {CaSTLe.Proxies.IMyBusinessControllerProxy}
    • __interceptors {CaSTLe.DynamicProxy.IInterceptor[1]}
      • [0] {Snap.MasterProxy}
    • __target {My.Business.Web.Controllers.MyBusinessController}
      • 服务 {CaSTLe.Proxies.IMyBusinessServiceProxy}
      • (其他构造函数注入(inject))
    • MyInjectedProperty {My.Business.Useful.MyOtherType}

最佳答案

IController GetControllerInstance(...) 中,不提供接口(interface)代理,使用虚拟方法提供类代理。

IController GetControllerInstance(...) 返回的 Controller 中用户实现的方法将不会通过代理的 IMyBusinessController 接口(interface)访问,而是从 转换IController 到 Controller 的实际类;例如 MyBusinessController。请改用类代理,以使 MVC3 的转换返回代理。此外,将方法标记为 virtual,否则拦截代理将无法拦截方法调用并检查自定义属性。

在 Controller 中,将 virtual 添加到具有属性的方法中:

public class MyBusinessController : MyBusinessControllerBase, IMyBusinessController
{
[Log(LoggingLevel.Debug)]
public virtual ActionResult CreateOrUpdate(MyBusinessFormModel fm)
{
// Convert form model to data transfer object,
// perform validation and other checks

this.service.Save(dto);

return View(fm);
}
}

为什么只有 Execute(...) 被拦截? IController 接口(interface)只包含 Execute(...)。在返回的controller interface proxy上调用了execute,这样就可以拦截了。但是一旦 MVC3 的内部 ControllerBase.Execute(...) 得到调用,它就会执行转换到它期望来自 ControllerFactory 的类。

问题类似于this leaking ,因为两者都绕过了接口(interface)代理。我想它可以通过多种方式解决;也许通过创建自定义类型转换器、从工厂中的接口(interface)代理目标创建类代理、巧妙的 Windsor 配置等。

Krzysztof Koźmic 的 IController installerWindsorControllerFactory应该开箱即用。接口(interface)代理可能会在更大的画面中被推荐(并且在 Controller 中使用拦截器之前它们工作良好)但在这种情况下可能有理由不走那么远,以避免进一步的副作用。

感谢 Marius 为我指明了正确的方向!

关于c# - ASP.NET MVC3 Controller AOP 代理不拦截所有方法,只有 IController.Execute,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8938715/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com