What's the difference between the four File Results in ASP.NET MVC

FileResult is an abstract base class for all the others.

  • FileContentResult - you use it when you have a byte array you would like to return as a file
  • FilePathResult - when you have a file on disk and would like to return its content (you give a path)
  • FileStreamResult - you have a stream open, you want to return its content as a file

However, you'll rarely have to use these classes - you can just use one of Controller.File overloads and let ASP.NET MVC do the magic for you.


Great question...and deserves more details. I find myself here as a result of an interesting situation. We were delivering some pdf attachments via the MVC3/C# environment. Our code got released and we started getting some responses from our clients that the downloads were behaving strangely when they were using Chrome and the file type was being converted over to 'pdf-, attachment.pdf-, attachment'. Yup...you got it...the whole thing. So, one could rewrite it to just be 'pdf' and the file would still save intact, but what a mess!

So, to describe the initial situation, we were setting the 'Content-Disposition' header then returning a FileContentResult...

var cd = new System.Net.Mime.ContentDisposition
            {
                FileName = result.Attachment.FileName,
                Inline = false
            };
            Response.AppendHeader("Content-Disposition", cd.ToString());

return File(result.Attachment.Data, MimeExtensionHelper.GetMimeType(result.Attachment.FileName), result.Attachment.FileName);

Seemed good. Worked fine in IE. So I did some research and tried implementing FileStreamResult instead (keeping the Content-Disposition setter):

MemoryStream dataStream = new MemoryStream();
dataStream.Write(result.Attachment.Data, 0, result.Attachment.Data.Length);
dataStream.Position = 0;
return new FileStreamResult(dataStream, MimeExtensionHelper.GetMimeType(result.Attachment.FileName));

It fixed the issue in Chrome! Hmmm...but why in the heck should I have to take my perfectly good byte array and stream it and then return it via this to get the file name to work right?

Then came the Fiddler.

With FileContentResult, I got 2 Content-Dispositions in the header. With FileStreamResult, I got 1.

FileContentResult appends a Content-Disposition header when providing the File Name and Chrome considers multiples of this header as an error.

Odd reaction...but definitely one that's good to know.