Skip to content

AndroidMessageHandler disposes request MultipartFormDataContent inner JsonContent immediately after sending request #7086

Closed
@DenisLaky

Description

@DenisLaky

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

  1. Select AndroidClientHandler in Project options -> Android build -> HttpClientImplementation;
  2. Create MultipartFormDataContent and JsonContent;
  3. Create HttpRequestMessage and add MultipartFormDataContent to its content;
  4. Call HttpClient.SendAsync with created request;
  5. Call JsonContent ReadAsStringAsync();
  6. 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 

Metadata

Metadata

Assignees

Labels

Area: HTTPIssues with sockets / HttpClient.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions