0

I have an MVC controller action to which I am posting a file stream: -

public ActionResult Upload()
{
    try
    {
        HttpPostedFileBase files = Request.Files[0];
        Stream fileStream = files.InputStream;

        String url = ConfigurationManager.AppSettings[ConfigurationParams.ServiceGatewayURI];

        HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);

        request.Method = "POST";
        request.AllowWriteStreamBuffering = false; 
        request.Timeout = 86400000; 
        request.ContentType = "application/json";
        request.ContentLength = fileStream.Length;
        Stream outputStream = request.GetRequestStream(); 
        int BYTELENGTH = 1024;
        byte[] chunk = new byte[BYTELENGTH];                

        while (fileStream.Position < fileStream.Length)
        {
            int len = fileStream.Read(chunk, 0, BYTELENGTH); 
            outputStream.Write(chunk, 0, len);
        }

        fileStream.Close();
        fileStream.Dispose();
        outputStream.Close();
        outputStream.Dispose();

        return Json("");
    }
    catch (Exception ex)
    {
        return Json(new { error = String.Format("Exception when streaming to back end, {0}"),ex.Message });
    }
}   

The inputStream is then POSTed to an API controller method as per the address in the url variable. The stream is then then saved to disk via another method for the object context.

API controller method: -

public String Post(string documentName)
{
    return context.SaveFile(documentName, Request.Content.ReadAsStreamAsync().Result);
}


public string SaveFile(documentName, Stream inputStream)
{   
        // Exception happens here!
}

The challenge I am facing is that when an exception happens in the SaveFile method, it does not flow back up to the Upload controller call. The Upload controller remains blissfully unaware that something went wrong when saving the file.

I can see two separate streams when debugging with Fiddler, including an HTTP 500 error from the SaveFile method.

My question is how can I throw an exception from the SaveFile method to the Upload controller? I have tried closing the inputStream on the back end when an exception is raised, but that did not return a 500 for the Upload call.

Thanks.

Meeple
  • 156
  • 4
  • "The inputStream is then POSTed to an API controller method"...how are you doing that then? And how are you handling exceptions or HTTP error codes resulting from it? That seems to be the key thing, and yet you've left that code out of your question. If the API is returning a 500 error correctly, then it all comes down to how you handle that in your Upload() method. We can see you writing to `outputStream`, but I don't believe that would actually trigger the HTTP request to start, or does it? – ADyson May 09 '18 at 14:36
  • Thanks for the comment ADyson. Using Fiddler to debug, I can see the HTTP connection from the browser to the Upload controller method opening as soon as the first curly brace is hit. On stepping through the code and reaching Stream outputStream = request.GetRequestStream(); the connection for the POST to the API controller opens. The Upload controller connection finishes with a 200 and the API connection finishes with a 500. I would have though the try and catch would handle any exceptions as the outputStream line is within them. – Meeple May 09 '18 at 20:38
  • No problem...can you answer my query? – ADyson May 09 '18 at 20:40
  • Of course, see above. – Meeple May 10 '18 at 22:55
  • I haven't used this particular library for making HTTP requests but I think you probably need to be listening for the response using GetResponse: https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse(v=vs.110).aspx - according to the docs it will throw a WebException if an error occurs – ADyson May 11 '18 at 07:34

1 Answers1

0

Thanks, that did the trick. It seems that you can't get a handle on the exception without invoking GetResponse. As soon as I added the line, the exception was caught by the main try-catch.

I'll have to read the ResponseStream to get the full details, but for now this solution works well enough.

try
{
    HttpWebResponse theResponse = (HttpWebResponse)request.GetResponse();
    theResponse.Close();
}

catch (WebException wex)
{
    return Json(new { error = wex.Message});
}
Meeple
  • 156
  • 4