Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebApi PushStreamContent Error Handling

What's the proper way to handle errors when using Pushstreamcontent? I use Pushstreamcontent to stream data directly from database to a client. On the client I use HttpCompletionOption.ResponseHeadersRead when recieving the result.

In the case the data is not available, I want to return a HttpStatusCode 404 (Not Found) for example. Currently I only detect that there is no data, during the execution of the lambda (CopyBinaryValueToResponseStream). At that point in time I cannot change the state of the HttpResponeMessage anymore.

So what is a proper way to handle such cases? I wanted to avoid an additional check in the database upfront, but right now that seems to be the only way to get it done?

    [Route("{id}")]
    public HttpResponseMessage GetImage(int id)
    {
        HttpResponseMessage resp = new HttpResponseMessage();

        // do I need to check here first if the data is available?
        // and return 404 if the data is not available
        // resp.StatusCode = HttpStatusCode.NotFound
        // or can I handle it later from within the lambda?

        resp.Content = new PushStreamContent(async (responseStream, content, context) =>
        {
            // what if an error happens in this function? who do I get that error to the client?
            await CopyBinaryValueToResponseStream(responseStream, id);
        });

        return resp;
    }
like image 584
DanielG Avatar asked Nov 10 '22 02:11

DanielG


1 Answers

You cannot fix it within the PushStreamContent action. By the time that action is executing, you have already started sending the response, and thus have already sent a 200. This is a drawback of PushStreamContent.

If you have some way to detect that the resource does not exist before streaming (for example, if some file does not exist), you can detect that first and return a 404, i.e. not using PushStreamContent at all in that case.

[Route("{id}")]
public HttpResponseMessage GetImage(int id)
{
    HttpResponseMessage resp = new HttpResponseMessage();

    if (File.Exists(@"c:\files\myfile.file"))
    {
        resp.StatusCode = HttpStatusCode.NotFound;
        return resp;
    }

    // file exists - try to stream it
    resp.Content = new PushStreamContent(async (responseStream, content, context) =>
    {
        // can't do anything here, already sent a 200.
        await CopyBinaryValueToResponseStream(responseStream, id);
    });

    return resp;
}
like image 112
James Avatar answered Nov 14 '22 22:11

James