question

JAL-9381 avatar image
0 Votes"
JAL-9381 asked ryanchill commented

.Net Core Web Api. Can't Write Bytes to the Response Stream


I coded and maintained a .Net Core web api for over a year now. After a year of success, I now get an error when running the web api locally at https://localhost:42123 (but no such error on the deployed version in Azure App Services). I need it to continue to work locally because I have always relied on local debugging.

The error seen locally is: "Error while copying content to a stream. Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."


After an entire day of trying suggestions on the internet (various combinations of TLS settings, Keep-Alive, ConnectionLimit, HttpVersion, ServicePointManager.Expect100Continue, etc), I finally pinpointed two lines of code triggering the error. The API-response is returning basically three items to the consumer:
...StatusCode <---- no problem here
...ReasonPhrase <---- no problem here
...Content (Body) <---- triggers the error

For the Body, it is manually writing out bytes to the response stream via 2 lines of code shown below. Commenting out those 2 lines clears the error. I don't see any C# exception happening there - the next line of code executes just fine.

Why did those 2 line of code suddenly stop working locally after a year? And why does it continue to work fine in Azure App Services?

 public static IActionResult GoodRequest(ControllerBase This, int statusCode, string strReasonPhrase, string strContent)   {
  HttpStatusCode httpStatusCode = (HttpStatusCode)statusCode;
  strReasonPhrase = $"{httpStatusCode}. {strReasonPhrase}";
  if (strReasonPhrase.Length > 510) strReasonPhrase = strReasonPhrase.Substring(0, 510);
  This.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = strReasonPhrase;
  This.HttpContext.Features.Get<IHttpResponseFeature>().StatusCode = statusCode;
  byte[] bytes = System.Text.Encoding.UTF8.GetBytes(strContent);
  This.HttpContext.Features.Get<IHttpResponseBodyFeature>().Writer.WriteAsync(bytes).GetAwaiter().GetResult();
  return new StatusCodeResult(statusCode);
  }

BTW, I am running the queries from a .Net 4.72 winforms application, via httpClient and Azure AD token. Even during local debugging, I am using an AD token to authenticate.

dotnet-aspnet-core-webapi
· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I just added a line to flush the stream, but it didn't help. My latest version is this:

  byte[] bytes = System.Text.Encoding.UTF8.GetBytes(strContent);
             Task.Run(async () => await This.HttpContext.Features.Get<IHttpResponseBodyFeature>().Writer.WriteAsync(bytes)).Wait();
             Task.Run(async () => await This.HttpContext.Features.Get<IHttpResponseBodyFeature>().Writer.FlushAsync()).Wait();            
             return new StatusCodeResult(statusCode);
0 Votes 0 ·

Earlier today I experimented with a version that used a slightly different syntax to write to the output stream, something like this:
....Stream outputStream = Request.Body;
....outputStream.Write(bytes, 0, bytes.length);

but got the same error.

0 Votes 0 ·

Have you tried changing your .NET Core version @JAL-9381? Does the API reproduce the error if you call it with http REPL or Postman?

0 Votes 0 ·

1 Answer

JAL-9381 avatar image
0 Votes"
JAL-9381 answered JAL-9381 edited

Ok made some progress. Seems to work locally if I do:
....return new EmptyResult();
because I think the server is objecting to adding a status code to a stream already written bytes to. Still have no idea why the Azure web server never raised this objection - it is only arises locally.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.