Disposing Resources At the End of the Request Lifecycle in ASP.NET Web API

How to disposing resources at the end of the request lifecycle in ASP.NET Web API with the RegisterForDispose extension method for the HttpRequestMessage class
27 July 2012
3 minutes read

Related Posts

When we are working with ASP.NET Web API, we always deal with disposable resources and if we are using an IoC container, it deals with disposals in behalf of us.

However, when we are inside the extensibility points and we just want to create a resource there and dispose it as soon as we are done with it, it can be easily overwhelming because the asynchronous structure of the ASP.NET Web API. We should be very careful where to dispose our resources.

However, ASP.NET team has come up with this great idea that they allow us to register resources to be disposed by a host once the request is disposed. The RegisterForDispose extension method for the HttpRequestMessage class enables this feature. In fact, all it does is to keep track of all the registered resources inside a List<IDisposable> object. They stick this collection into the Properties property of the HttpRequestMessage (under the key of MS_DisposableRequestResources). Then, at the end of the request, these resources will be disposed along with the request.

The usage is also so simple. For example, the below code is for a message handler which serves as a timeout watcher.

public class TimeoutHandler : DelegatingHandler {

    private readonly int _milliseconds;
    private static readonly TimerCallback s_timerCallback = 
        new TimerCallback(TimerCallbackLogic);

    public TimeoutHandler(int milliseconds) {

        if (milliseconds < -1) {

            throw new ArgumentOutOfRangeException("milliseconds");
        }

        _milliseconds = milliseconds;
    }

    public int Timeout {

        get {
            return _milliseconds;
        }
    }

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken) {

        var cts = new CancellationTokenSource();
        var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
            cts.Token, cancellationToken
        );
        var linkedToken = linkedTokenSource.Token;
        var timer = new Timer(s_timerCallback, cts, -1, -1);

        request.RegisterForDispose(timer);
        request.RegisterForDispose(cts);
        request.RegisterForDispose(linkedTokenSource);

        timer.Change(_milliseconds, -1);

        return base.SendAsync(request, linkedToken).ContinueWith(task => {

            if (task.Status == TaskStatus.Canceled) {

                return request.CreateResponse(HttpStatusCode.RequestTimeout);
            }

            //TODO: Handle faulted task as well

            return task.Result;

        }, TaskContinuationOptions.ExecuteSynchronously);
    }

    private static void TimerCallbackLogic(object obj) {

        CancellationTokenSource cancellationTokenSource = 
            (CancellationTokenSource)obj;
            
        cancellationTokenSource.Cancel();
    }
}

You may see that there are still TODO notes inside the code which means I am still not done with the code, so don't use it in production!:) but it is a good example to illustrate the usage of RegisterForDispose extension method. Notice that I used two CancellationTokenSource objects and one Timer object (I need a Timer object here to request a cancellation because CancellationTokenSource does not have CancelAfter method in .NET v4.0 and I couldn’t find any other easier way to do this). All of these objects need to be disposed once they are no longer in use. However, it is really hard to keep track to figure out which one of them needs to be disposed where inside this handler. So, I just registered them to disposed at the end of the request lifetime.