CrazyCoderz
CrazyCoderz

Reputation: 1341

How are action filters disposed?

I have the following Global filter, The ISiteValidation and ICacheService are injected via the Windsor container and are setup as Transient so the container will not dispose of the dependencies automatically. This will cause a resource issue when the site goes into production. So what are folks doing to properly Dispose of resources injected into a filter? both interfaces are IDisposable but Dispose never gets called when the Action Filter goes out of scope and the container will continue to hold on to the implementation.

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

Upvotes: 1

Views: 1415

Answers (1)

Remo Gloor
Remo Gloor

Reputation: 32725

Attributes are created by the CLR on request:

If you want to construct an attribute object, you must call either GetCustomAttributes or GetCustomAttribute. Every time one of these methods is called, it constructs new instances of the specified attribute type and sets each of the instance’s fields and properties based on the values specified in the code.

This means they are not within the control of any IoC container. The only part of a system that could Dispose them is the one that is calling GetCustomAttribute or GetCustomAttributes. But nothing is explicitly doing this; as a result, Attributes shouldn't be Disposable.

Fortunately, there is another way. Don't use attributes for filters but instead implement an IActionFilter and register a IFilterProvider that returns a new instance of your filter (created by your IoC container) when required.

Have a look on how it is done using Ninject; the same approach should be portable to Windsor.

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

Upvotes: 6

Related Questions