Closed
Description
Android application type
Classic Xamarin.Android (MonoAndroid12.0, etc.)
Affected platform version
VS for Mac 8.10.23 (build 7)
Description
AndroidMessageHandler disposes HttpContents buffered streams after request content was written to HttpConnection.OutputStream
var multipartFormDataContent = new MultipartFormDataContent();
var jsonContent = JsonContent.Create(stringValue);
multipartFormDataContent.Add(jsonContent,
"Name");
var request = new HttpRequestMessage(HttpMethod.Post, $"{httpClient.BaseAddress}{SEND_REQUEST_URI}")
{
Content = multipartFormDataContent,
};
_ = await httpClient.SendAsync(request);
// Throws exception
var contentValue = await jsonContent.ReadAsStringAsync();
Steps to Reproduce
- Select AndroidClientHandler in Project options -> Android build -> HttpClientImplementation;
- Create MultipartFormDataContent and JsonContent;
- Create HttpRequestMessage and add MultipartFormDataContent to its content;
- Call HttpClient.SendAsync with created request;
- Call JsonContent ReadAsStringAsync();
- ObjectDisposed exception is raised;
Did you find any workaround?
Override AndroidClientHandler WriteRequestContentToOutput method. This allows us to prevent content buffered stream from disposing after writing to httpConnection.OutputStream:
public class CustomAndroidHandler : AndroidClientHandler
{
protected override async Task WriteRequestContentToOutput(HttpRequestMessage request, HttpURLConnection httpConnection, CancellationToken cancellationToken)
{
var stream = await request.Content.ReadAsStreamAsync().ConfigureAwait(false);
await stream.CopyToAsync(httpConnection.OutputStream!, 4096, cancellationToken).ConfigureAwait(false);
if (stream.CanSeek)
{
_ = stream.Seek(0, SeekOrigin.Begin);
}
}
}
AndroidClientHandler getting disposed HttpRequestMessage.Content immediately after sending
Relevant log output
at System.IO.MemoryStream.EnsureNotClosed () [0x00008] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/Common/src/CoreLib/System/IO/MemoryStream.cs:121
at System.IO.MemoryStream.get_Length () [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/Common/src/CoreLib/System/IO/MemoryStream.cs:333
at System.Net.Http.HttpContent.ReadBufferedContentAsString () [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpContent.cs:175
at System.Net.Http.HttpContent+<>c.<ReadAsStringAsync>b__36_0 (System.Net.Http.HttpContent s) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpContent.cs:168
at System.Net.Http.HttpContent.WaitAndReturnAsync[TState,TResult] (System.Threading.Tasks.Task waitTask, TState state, System.Func`2[T,TResult] returnFunc) [0x0006b] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/System.Net.Http/src/System/Net/Http/HttpContent.cs:727