Disposing resources at the end of Web API request

· 434 words · 3 minutes to read

Sometimes you have resources in your code that are implementing IDisposable, and that you’d like them to be disposed only at the end of the HTTP request. I have seen a solution to this problem rolled out by hand in a few code bases in the past - but in fact this feature is already built into Web API, which I don’t think a lot of people are aware of.

Let’s have a quick look.

RegisterForDispose 🔗

ASP.NET Web API contains an extension method for HttpRequestMessage that’s called RegisterForDispose - which allows you to pass in a single instance or a collection of instances of IDisposable.

What happens under the hood, is that Web API will simply store those object references in the properties dictionary of the request message (under HttpPropertyKeys.DisposableRequestResourcesKey key), and at the end of the Web API request lifetime, will iterate through those objects and call Dispose on them. This is the responsibility of the Web API host, so each of the existing hosting layers - Web Host (“classic” ASP.NET), self host (WCF based) and OWIN host (the Katana adapter) is explicitly implementing this feature. It is guaranteed to happen (for example, the Katana adapter uses a try/catch block around the entire Web API pipeline and performs the disposal in finally.

As a result you can do things like the code below. Imagine a message handler that opens a stream, writes to it, then saves the stream into request properties (so that other Web API components such as other message handlers, filters, controllers etc can use it too):

public class WriterHandler : DelegatingHandler  
{  
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)  
{  
var writer = new StreamWriter("c:\\file.txt", true);  
//save the writer for later use  
request.Properties["filewriter"] = writer;

await writer.WriteLineAsync("some important information");

request.RegisterForDispose(writer);  
return await base.SendAsync(request, cancellationToken);  
}  
}  

You don’t have to use a using statement here, as registering for disposal using Web API resource tracking feature will ensure that the stream writer is disposed of at the end of the request lifetime. This is very convenient, as other components during the HTTP request, can share the same resource.

It is also worth adding that resource tracking is also used if you ever use Web API GetDependencyScope feature - which allows you to resolve services from the registered dependency resolver:

var myService = request.GetDependencyScope().GetService(typeof(IMyService));  

In the above case, the instance of IMyService will be registered for disposal at the end of Web API request.

One final note - at any time you can also take a peek into the resources currently registered for disposal, using a GetResourcesForDisposal extension method on HttpRequestMessage.

About


Hi! I'm Filip W., a software architect from Zürich 🇨🇭. I like Toronto Maple Leafs 🇨🇦, Rancid and quantum computing. Oh, and I love the Lowlands 🏴󠁧󠁢󠁳󠁣󠁴󠁿.

You can find me on Github, on Mastodon and on Bluesky.

My Introduction to Quantum Computing with Q# and QDK book
Microsoft MVP