Repository navigation
ObjectDisposedException when retrying POST request using AndroidClientHandler #2901
Description
Activity
Any update on this as I am also facing this issue and it needs to be resolved asap on Prod env.
I also started to have the same issue after upgrading.
from Visual Studio Enterprise 2019 16,2,4 (Xamarin.Andoid 9.4.1.1)
to Visual Studio Enterprise 2019 16,4.12 (Xamarin.Android 10.1.4.0 (d16-4/e44d1ae) )We are doing the similar logic, when the first request failed we retry sending the same request, and now getting the ObjectDisposedException - cannot access closed stream.
This is the stacktrace.
at System.IO.StreamHelpers.ValidateCopyToArgs (System.IO.Stream source, System.IO.Stream destination, System.Int32 bufferSize) [0x0003a] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/Common/src/CoreLib/System/IO/StreamHelpers.CopyValidation.cs:26
at System.IO.MemoryStream.CopyToAsync (System.IO.Stream destination, System.Int32 bufferSize, System.Threading.CancellationToken cancellationToken) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/external/corefx/src/Common/src/CoreLib/System/IO/MemoryStream.cs:531
at Xamarin.Android.Net.AndroidClientHandler.WriteRequestContentToOutput (System.Net.Http.HttpRequestMessage request, Java.Net.HttpURLConnection httpConnection, System.Threading.CancellationToken cancellationToken) [0x00089] in /Users/builder/azdo/_work/204/s/xamarin-android/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs:352
at Xamarin.Android.Net.AndroidClientHandler.DoProcessRequest (System.Net.Http.HttpRequestMessage request, Java.Net.URL javaUrl, Java.Net.HttpURLConnection httpConnection, System.Threading.CancellationToken cancellationToken, Xamarin.Android.Net.AndroidClientHandler+RequestRedirectionState redirectState) [0x002aa] in /Users/builder/azdo/_work/204/s/xamarin-android/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs:424
at Xamarin.Android.Net.AndroidClientHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x0027d] in /Users/builder/azdo/_work/204/s/xamarin-android/src/Mono.Android/Xamarin.Android.Net/AndroidClientHandler.cs:286It would be great if anyone can tell me when the fix is planned. Thank you!
Did anyone get anywhere with this? @jNery-zz ? @yma44 @IndexOutOfLimit
Ok I think I have a fix for this:
@jNery-zz ? @yma44 @IndexOutOfLimit
Basically, if it's a retry, clone the HttpRequestMessage before resending it, this will reset the stream position to 0. HttpRequestMessages by design can only be used once.
For your example:
if (retry) { retry = !retry; request = CloneHttpRequestMessageAsync(request); return await SendAsync(request, cancellationToken); }public static async Task<HttpRequestMessage> CloneHttpRequestMessageAsync(HttpRequestMessage req) { HttpRequestMessage clone = new HttpRequestMessage(req.Method, req.RequestUri); // Copy the request's content (via a MemoryStream) into the cloned object var ms = new MemoryStream(); if (req.Content != null) { await req.Content.CopyToAsync(ms).ConfigureAwait(false); ms.Position = 0; clone.Content = new StreamContent(ms); // Copy the content headers if (req.Content.Headers != null) foreach (var h in req.Content.Headers) clone.Content.Headers.Add(h.Key, h.Value); } clone.Version = req.Version; foreach (KeyValuePair<string, object> prop in req.Properties) clone.Properties.Add(prop); foreach (KeyValuePair<string, IEnumerable<string>> header in req.Headers) clone.Headers.TryAddWithoutValidation(header.Key, header.Value); return clone; }Also as an aside, AndroidClientHandler is now marked as obsolete in the source code with an instruction to use AndroidMessageHandler instead. I've done just that and it works great. It has the same overridable SendAsync method.
- addedArea: HTTPIssues with sockets / HttpClient.Issues with sockets / HttpClient.
on Sep 6, 2022 FYI similar thing happens on iOS with NSUrlSessionHandler (no error thrown, but it just posts empty content to the server). However SocketsHttpHandler, HttpClientHandler, WebRequestHandler and other .NET ones are not affected and works fine.
HttpRequestMessages by design can only be used once.
.NET's HttpHandlers seem to disagree. Also if I created them, why can't I decide when to dispose them? It seems more efficient to be able to reuse your http content, than having to recreate it over and over again for repeated requests.
- added a commit that references this issue
on Feb 27, 2024 - added a commit that references this issue
on Mar 11, 2024 - locked and limited conversation to collaborators
on Mar 29, 2024
ObjectDisposedException when retrying POST request using AndroidClientHandler
Steps to Reproduce
Notice that same implementation above for HttpClientHandler works just fine
Use case: server may respond with JSON error so client can challenge for credential; thus, sending the same POST request with authorization header or parameter.
Expected Behavior
Following request should have succeeded.
Actual Behavior
Following request fails with ObjectDisposedException "Cannot access a closed Stream"
Version Information
Microsoft Visual Studio Enterprise 2017
Version 15.9.9
VisualStudio.15.Release/15.9.9+28307.518
Microsoft .NET Framework
Version 4.7.03190
Mono Debugging for Visual Studio 4.13.12-pre (9bc9548)
Support for debugging Mono processes with Visual Studio.
VisualStudio.Mac 1.0
Mac Extension for Visual Studio
Xamarin 4.12.3.80 (d15-9@914127c74)
Visual Studio extension to enable development for Xamarin.iOS and Xamarin.Android.
Xamarin Designer 4.16.13 (45a16efd4)
Visual Studio extension to enable Xamarin Designer tools in Visual Studio.
Xamarin Templates 1.1.128 (6f5ebb2)
Templates for building iOS, Android, and Windows apps with Xamarin and Xamarin.Forms.
Xamarin.Android SDK 9.1.7.0 (HEAD/ba9da7a76)
Xamarin.Android Reference Assemblies and MSBuild support.
Xamarin.iOS and Xamarin.Mac SDK 12.2.1.15 (d60abd1)
Xamarin.iOS and Xamarin.Mac Reference Assemblies and MSBuild support.
Log File