如何处理动作过滤器?

时间:2012-08-06 15:49:22

标签: asp.net-mvc-3 dependency-injection castle-windsor asp.net-mvc-4

我有以下全局过滤器,ISiteValidation和ICacheService通过Windsor容器注入并设置为Transient,因此容器不会自动处理依赖项。当站点投入生产时,这将导致资源问题。那么人们正在做什么来正确处理注入过滤器的资源?两个接口都是IDisposable,但是当Action Filter超出范围并且容器将继续保持实现时,Dispose永远不会被调用。

public class SiteValidationAttribute : ActionFilterAttribute
{
    public ISiteValidation SiteValidation { get; set; }
    public ICacheService CacheService { get; set; }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (filterContext.RequestContext.HttpContext.Request.Url != null)
        {
            string host = filterContext.RequestContext.HttpContext.Request.Url.Host;
            try
            {
                string siteId = CacheService.Get("SiteId",
                                                 () =>
                                                 SiteValidation.GetSiteId(
                                                     host));
                var siteIdCookie = new HttpCookie("_site") {Value = siteId};
                filterContext.RequestContext.HttpContext.Response.Cookies.Add(siteIdCookie);
            }
            catch (Exception)
            {
                throw new HttpException(404, String.Format("This site'{0}' was not found", host));
            }
        }

        base.OnActionExecuted(filterContext);
    }
}

1 个答案:

答案 0 :(得分:5)

属性由CLR根据请求创建:

  

如果要构造属性对象,则必须调用其中一个   GetCustomAttributes或GetCustomAttribute。每次都是其中之一   调用方法,它构造指定的新实例   属性类型并设置每个实例的字段和属性   基于代码中指定的值。

这意味着它们不在任何IoC容器的控制之内。系统中唯一可以处理它们的部分是调用GetCustomAttributeGetCustomAttributes的部分。但没有任何明确的做法;因此,属性不应该是Disposable。

幸运的是,还有另一种方式。不要使用过滤器的属性,而是实现IActionFilter并注册IFilterProvider,以便在需要时返回过滤器的新实例(由IoC容器创建)。

看看如何使用Ninject完成它;相同的方法应该可以移植到温莎。

https://github.com/ninject/ninject.web.mvc/tree/master/mvc3/src/Ninject.Web.Mvc/Filter