Description
ObjectDisposedException when retrying POST request using AndroidClientHandler
Steps to Reproduce
- Implement AndroidClientHandler that will retry the same request
public class NativeClientHandler : AndroidClientHandler
{
bool retry = true;
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = await BaseSendAsync(request, cancellationToken);
if (retry)
{
retry = !retry;
return await SendAsync(request, cancellationToken);
}
return response;
}
internal Task<HttpResponseMessage> BaseSendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken);
}
}
Notice that same implementation above for HttpClientHandler works just fine
public class ManagedClientHandler : HttpClientHandler
{
bool retry = true;
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpResponseMessage response = await BaseSendAsync(request, cancellationToken);
if (retry)
{
retry = !retry;
return await SendAsync(request, cancellationToken);
}
return response;
}
internal Task<HttpResponseMessage> BaseSendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken);
}
}
- Send POST request that will be re-sent
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.
EventHandler clickedHandler = async (a, b) =>
{
var dialog = new Android.App.AlertDialog.Builder(this);
try
{
if (a == button)
{
var client = new System.Net.Http.HttpClient(new NativeClientHandler());
var response = await client.PostAsync(new Uri("http://httpbin.org/post"), new System.Net.Http.FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("f", "json") }));
}
if (a == button1)
{
var client = new System.Net.Http.HttpClient(new ManagedClientHandler());
var response = await client.PostAsync(new Uri("http://httpbin.org/post"), new System.Net.Http.FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("f", "json") }));
dialog.SetMessage(await response.Content.ReadAsStringAsync());
}
dialog.SetTitle("Success!");
}
catch (Exception error)
{
Exception ex = error;
if (ex is AggregateException)
{
ex = ((AggregateException)ex).GetBaseException();
}
dialog.SetTitle(ex.GetType().Name);
dialog.SetMessage(ex.Message);
}
RunOnUiThread(() => dialog.Show());
};
button.Click += clickedHandler;
button1.Click += clickedHandler
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.