Search code examples
c#.netdispose

Dispose of File.Open or StreamContent


Is the below line for content.Add going to leave an object from being disposed correctly? If so what is the correct way to handle this.

 public string UploadGameToWebsite(string filename, string url, string method = null)
        {
            var client = new HttpClient();
            var content = new MultipartFormDataContent();
            content.Add(new StreamContent(File.Open(filename, FileMode.Open, FileAccess.Read)), "Game", "Game.txt");
            var task = client.PutAsync(url, content);
            var result = task.Result.ToString();
            return result;
        }

Solution

    1. Make your method asynchronous if you are going to be calling an async operation in your method.
    2. Dispose your file stream and also the client. In the example below by disposing the StreamContent it also disposes the underlying FileStream.
    3. I prefer a finally block for disposing multiple disposable objects, its also perfectly fine to have nested using statements.
    4. Not sure why you are returning the ToString on the HttpResponseMessage, maybe status code would be more useful or see if StatusCode = 200 and return boolean (true/false)?

    Code:

    public async Task<string> UploadGameToWebsiteAsync(string filename, string url, string method = null)
    {
        HttpClient client = null;
        StreamContent fileStream = null;
        try
        {
            client = new HttpClient();
            fileStream = new StreamContent(System.IO.File.Open(filename, FileMode.Open, FileAccess.Read))
            var content = new MultipartFormDataContent();
            content.Add(fileStream, "Game", "Game.txt");
            HttpResponseMessage result = await client.PutAsync(url, content);
            return result.ToString();
        }
        finally 
        {
            // c# 6 syntax
            client?.Dispose();
            fileStream?.Dispose(); // StreamContent also disposes the underlying file stream
        }
    }
    

    Code version #2 using using blocks.

    public async Task<string> UploadGameToWebsiteAsync(string filename, string url, string method = null)
    {
        using (var client = new HttpClient())
        {
            using (var fileStream = new StreamContent(System.IO.File.Open(filename, FileMode.Open, FileAccess.Read)))
            {
                var content = new MultipartFormDataContent();
                content.Add(fileStream, "Game", "Game.txt");
                HttpResponseMessage result = await client.PutAsync(url, content);
                return result.ToString();
            }
        }
    }