Search code examples
c#try-catchusingusing-statement

Try/catch Image.FromStream() without catching the rest of the using statement?


Image.FromStream throws an InvalidArgumentException when you upload something that is not an image.

Therefore I have code similar to this:

public void ActionMethod()
{
    try
    {
        using ( var image = Image.FromStream(httpPostedFileBase.InputStream) )
        {
            MoreStuffToDo(image);
        }
    }
    catch (InvalidArgumentException e)
    {
        ModelState.AddModelError( "", "File is not a valid image" );
    }
}

Problem is that InvalidArgumentException also catches stuff that has nothing to do with Image.FromStream, i.e. in MoreStuffToDo()

The only solution I can think of is to remove the using statement. But this also sounds like a bad decission.

What is the right way to do this? So we have both a try/catch around the Image.FromStream() method and that the are sure that the image is being properly disposed in all cases?


Solution

  • It's not the using that's important... it's the call to IDisposable.Dispose(). using makes that call for you, behind the scenes, allowing you to simply write this:

    using(var x = new X())
    {
        // do stuff with x
    }
    

    ... instead of this:

    X x = null;
    try
    {
        x = new X();
        // do stuff with x
    }
    finally
    {
        if(x != null)
        {
            x.Dispose(); // clean up resources
        }
    }
    

    It's a nice way to skip a bunch of boiler-plate code but you're by no means forced to use it. You can explicitly call IDisposable.Dispose() and leave yourself with more control over what happens where:

    public void ActionMethod()
    {
        // declare image...
        Image image = null;
    
        try
        {
            // attempt to load image from stream...
            image = Image.FromStream(httpPostedFileBase.InputStream)
        }
        catch
        {
            // failed to load image from stream...
            ModelState.AddModelError( "", "File is not a valid image" );
            // exit
            return;
        }
    
        try
        {
            // perform additional processing...
            MoreStuffToDo(image);
        }
        catch
        {
            // handle errors from MoreStuffToDo()
        } 
        finally
        {
            // clean up image...
            image.Dispose();
        }
    }