5

I'm having a very weird problem right now... I am trying to return a file from my web api but i'm getting a HTTP ERROR 500 even though the stream is working and no errors are thrown in the code.

var doc = DocX.Load(...);
// ...

var ms = new MemoryStream();
doc.SaveAs(ms);
doc.Dispose();

return File(ms, "application/octet-stream");

The stream becomes of size 22kb but when I navigate to the api's url I get a HTTP 500, why?

Thank you.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
Haytam
  • 4,643
  • 2
  • 20
  • 43
  • Use your debugger, its what its there for – maccettura Sep 18 '18 at 20:53
  • 1
    There is an exception being thrown at run time, you are just not catching it in the debugger. (I assume you are using the debugger based on "stream is working and no errors are thrown..."). Make sure you are breaking on *all* CLR exceptions (ctrl+alt+e). – Igor Sep 18 '18 at 20:53
  • Consider following this for returning your stream as an HttpResponseMessage instead of as a File? https://stackoverflow.com/questions/26038856/how-to-return-a-file-filecontentresult-in-asp-net-webapi – ASattar Sep 18 '18 at 21:06
  • 1
    You need to reset the position of your memorystream before trying to send it to the client : `ms.Position = 0;`. You can write your document directly to the Request.Body stream. And return an EmptyResult. – Kalten Sep 18 '18 at 21:12
  • @Kalten Indeed that was the issue, I forgot to seek the beginning of the stream. Should you answer this topic or should I just close it?. – Haytam Sep 18 '18 at 21:53

1 Answers1

9

You forgot to reset the memorystream position to the begining.

var doc = DocX.Load(...);
// ...

var ms = new MemoryStream();
doc.SaveAs(ms);
doc.Dispose();
ms.Position = 0;

return File(ms, "application/octet-stream");

You can also avoid the temporary MemoryStream

var doc = DocX.Load(...);
// ...

doc.SaveAs(Request.Body);
doc.Dispose();

return new EmptyResult();

Or implement a custom ActionResult

public class DocXResult : IActionResult
{
    private DocX _doc;

    public DocXResult(DocX doc) { _doc = doc); }

    public Task ExecuteResultAsync(ActionContext context)
    {
        var response = context.HttpContext.Response;
        response.ContentType = "application/octet-stream";
        _doc.SaveAs(response.Body);

        return Task.CompletedTask;
    }
}

public IActionResult SendDocX()
{
    DocX doc = null; // do your stuff
    this.Response.RegisterForDispose(doc);
    return new DocXResult(docX);
}
Kalten
  • 4,092
  • 23
  • 32