2011-01-14 23 views
6

En ASP.NET MVC 2 tengo una llamada ActionFilterAttribute[Transaction] que se inicia una transacción NHibernate antes de ejecutar la acción y confirma o deshace de nuevo después, dependiendo de si o no se lanzó una excepción. La instancia ISession es HttpRequestScoped() e inyectada por Autofac. Se ve así y funciona muy bien:ASP.NET MVC 3, Acción Filtros y Autofac inyección de dependencias

[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(); 
     } 
    } 
} 

Fantástico. Seems to be a common pattern.

En los ASP.NET MVC 3 notas, veo esta pequeña reseña en "Los cambios de última hora" (el énfasis es mío):

En las versiones anteriores de ASP.NET MVC, filtros de acción eran creado por solicitud excepto en algunos casos. Este comportamiento nunca fue un comportamiento garantizado, sino simplemente un detalle de implementación y el contrato de filtros fue considerarlos sin estado. En ASP.NET MVC 3, los filtros son almacenados en caché más agresivamente. Por lo tanto, cualquier filtro de acción personalizado que almacene incorrectamente el estado de la instancia puede estar roto.

Oops.

  • ¿Esto significa que tengo una manguera si actualizo a MVC 3?
  • Si los filtros de acción ya no se instancian por solicitud, ¿cómo obtendremos dependencias con ámbito de solicitud en nuestros filtros de acción?

Gracias por cualquier idea.

Respuesta

6

Acabo de hacer una pregunta similar en los foros de Google. Aquí está el enlace https://groups.google.com/forum/#!topic/autofac/a0qqp2b3WA8

Tengo la respuesta:

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


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

continuación, puede utilizar la inyección de la propiedad en sus atributos.

+0

Sí, parece que el comentario de la nota de lanzamiento se aplica a la configuración predeterminada en MVC, pero los contenedores de IoC anulan esto para proporcionar sus propios comportamientos. –

2

Oh yuck .... Nicholas, puede que necesites almacenar tu ISession y Transaction en HttpContext.Items, que deberías poder acceder a través de ActionExecutedContext/ActionExecutingContext (quizás configurándolo en el controlador de eventos OnActionExecuting), en lugar de mantenerlos en los miembros de la instancia. O eso, o puede llamar a ServiceLocator dentro de su filtro para tomarlos por usted (también asco).

¡Ahora tengo que revisar mi código MVC 3 y ver si tengo algún problema similar yo mismo!

Cuestiones relacionadas