ASP.NET MVC 3、操作过滤器和 Autofac 依赖注入

发布于 2024-10-12 06:16:36 字数 2164 浏览 4 评论 0原文

ASP.NET MVC 2 上,我有一个名为 [Transaction]ActionFilterAttribute,它在执行操作之前启动 NHibernate 事务并提交或回滚它之后,取决于是否抛出异常。 ISession 实例是 HttpRequestScoped() 并由 注入Autofac。它看起来像这样并且效果很好:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class TransactionAttribute : ActionFilterAttribute
{
    private ITransaction transaction;

    public TransactionAttribute()
    {
        this.Order = 0;
    }

    public ISession Session
    {
        get;
        set;
    }

    public override void OnActionExecuted(
        ActionExecutedContext filterContext)
    {
        if (this.Session != null && this.transaction != null)
        {
            try
            {
                if (this.transaction.IsActive)
                {
                    if (filterContext.Exception == null)
                    {
                        this.transaction.Commit();
                    }
                    else
                    {
                        this.transaction.Rollback();
                    }
                }
            }
            finally
            {
                this.transaction.Dispose();
                this.transaction = null;
            }
        }
    }

    public override void OnActionExecuting(
        ActionExecutingContext filterContext)
    {
        if (this.Session != null)
        {
            this.transaction = this.Session.BeginTransaction();
        }
    }
}

太棒了。 似乎是一种常见的模式。

ASP.NET MVC 3 注释中,我在“重大更改”下看到了这个小简介(重点是我的):

在以前版本的 ASP.NET MVC 中,除少数情况外,操作过滤器是根据请求创建的。这种行为从来都不是一个有保证的行为,而仅仅是一个实现细节,过滤器的契约是认为它们是无状态的。在 ASP.NET MVC 3 中,过滤器的缓存更加积极。因此,任何不正确存储实例状态的自定义操作过滤器都可能被破坏。

哎呀。

  • 这是否意味着如果我升级到 MVC 3,我就完蛋了?
  • 如果操作过滤器不再按请求实例化,我们将如何将请求范围的依赖项获取到我们的操作过滤器中?

感谢您的任何见解。

On ASP.NET MVC 2 I have an ActionFilterAttribute called [Transaction] that starts an NHibernate transaction before executing the action and commits or rolls it back afterward, depending on whether or not an exception was thrown. The ISession instance is HttpRequestScoped() and injected by Autofac. It looks like this and works great:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class TransactionAttribute : ActionFilterAttribute
{
    private ITransaction transaction;

    public TransactionAttribute()
    {
        this.Order = 0;
    }

    public ISession Session
    {
        get;
        set;
    }

    public override void OnActionExecuted(
        ActionExecutedContext filterContext)
    {
        if (this.Session != null && this.transaction != null)
        {
            try
            {
                if (this.transaction.IsActive)
                {
                    if (filterContext.Exception == null)
                    {
                        this.transaction.Commit();
                    }
                    else
                    {
                        this.transaction.Rollback();
                    }
                }
            }
            finally
            {
                this.transaction.Dispose();
                this.transaction = null;
            }
        }
    }

    public override void OnActionExecuting(
        ActionExecutingContext filterContext)
    {
        if (this.Session != null)
        {
            this.transaction = this.Session.BeginTransaction();
        }
    }
}

Fantastic. Seems to be a common pattern.

In the ASP.NET MVC 3 notes, I see this little blurb under "Breaking Changes" (emphasis mine):

In previous versions of ASP.NET MVC, action filters were created per request except in a few cases. This behavior was never a guaranteed behavior but merely an implementation detail and the contract for filters was to consider them stateless. In ASP.NET MVC 3, filters are cached more aggressively. Therefore, any custom action filters which improperly store instance state might be broken.

Oops.

  • Does this mean I'm hosed if I upgrade to MVC 3?
  • If action filters are no longer instanced per request, how will we get request-scoped dependencies into our action filters?

Thanks for any insight.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ゃ懵逼小萝莉 2024-10-19 06:16:36

我刚刚在谷歌论坛上问了类似的问题。
以下是链接 https://groups.google.com/forum/#!topic /autofac/a0qqp2b3WA8

我得到了答案:

builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();


builder.RegisterControllers(Assembly.GetExecutingAssembly()).InjectActionInvoker();

那么你可以在你的属性中使用属性注入。

I just asked a similar question on google forums.
Here is the link https://groups.google.com/forum/#!topic/autofac/a0qqp2b3WA8

I got the answer:

builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();


builder.RegisterControllers(Assembly.GetExecutingAssembly()).InjectActionInvoker();

Then you can use property injection in your attributes.

醉生梦死 2024-10-19 06:16:36

哦,糟糕......尼古拉斯,您可能需要将 ISession 和 Transaction 存储在 HttpContext.Items 中,您应该能够通过 ActionExecutedContext/ActionExecutingContext 访问它们(也许将其设置在 OnActionExecuting 事件处理程序中),而不是保留它们在实例成员中。或者,您也可以在过滤器内调用 ServiceLocator 来为您抓取它们(也很恶心)。

现在我必须检查我的 MVC 3 代码,看看我自己是否有任何类似的问题!

Oh yuck.... Nicholas, you might need to store your ISession and Transaction in HttpContext.Items, which you should be able to get to via the ActionExecutedContext/ActionExecutingContext (perhaps setting it in the OnActionExecuting event handler), instead of keeping them in instance members. Either that, or you could call a ServiceLocator inside your filter to grab them for you (also yuck).

Now I have to go look through my MVC 3 code and see if I have any similar problems myself!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文