Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ObjectDisposedException on HttpClient

I have a Windows Universal Project with multiple API calls. One method refuses to work eventhought my other calls work perfectly like this. I have tried the using keyword thought it would resolve the issue.

The function:

public async Task<User> GetNewUser(string user_guid, OAuthTokens OAuth)
{
    String userguidJSON = VALIDJSON_BELIEVE_ME;
    using (var httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", Encrypt(OAuth.Accesstoken));

        using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, BASE_URL + URL_USERS + "/data"))
        {
            req.Content = new StringContent(userguidJSON, Encoding.UTF8, "application/json");
            await httpClient.SendAsync(req).ContinueWith(respTask =>
            {
                Debug.WriteLine(req.Content.ReadAsStringAsync()); //Error is thrown ono this line
            });
            return null;
        }
    }
}

EDIT

public async Task<User> GetNewUser(string user_guid, OAuthTokens OAuth)
{
    String userguidJSON = VALIDJSON_BELIEVE_ME;
    using (var httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", Encrypt(OAuth.Accesstoken));

        using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, BASE_URL + URL_USERS + "/data"))
        {
            req.Content = new StringContent(userguidJSON, Encoding.UTF8, "application/json");
            await httpClient.SendAsync(req);
            var result = await req.Content.ReadAsStringAsync(); //Cannot access a disposed object. Object name: 'System.Net.Http.StringContent'.
            Debug.WriteLine(result);
            return null;
        }
    }
}

The stacktrace

 at System.Net.Http.HttpContent.CheckDisposed()
   at System.Net.Http.HttpContent.ReadAsStringAsync()
   at Roadsmart.Service.RoadsmartService.<GetNewUser>d__2e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at Roadsmart.ViewModel.SettingsPageViewModel.<SetNewProfilePicture>d__1e.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__3(Object state)
   at System.Threading.WinRTSynchronizationContext.Invoker.InvokeCore()
like image 817
timr Avatar asked Mar 31 '15 13:03

timr


3 Answers

ObjectDisposedException is thrown because you're disposing the HttpRequestMessage and HttpClient before req.Content.ReadAsStringAsync() finishes.

Note that req.Content.ReadAsStringAsync() is an asynchronous method. You need to wait for it to complete before disposing the HttpClient.

Also, you seem to be calling ReadAsStringAsync in req.Content, shouldn't that be response.Content?

using (HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Post, BASE_URL + URL_USERS + "/data"))
{
    req.Content = new StringContent(userguidJSON, Encoding.UTF8, "application/json");
    var response = await httpClient.SendAsync(req);
    var result = await response.Content.ReadAsStringAsync();//await it
    Debug.WriteLine(result);
    return null;
}

Almost there is no reason to use ContinueWith when dealing with async/await. All that is done by the compiler for you.

like image 59
Sriram Sakthivel Avatar answered Oct 24 '22 05:10

Sriram Sakthivel


The actual reason the ObjectDisposedException is thrown is because the HttpClient disposes the Content immediately after a completed request. Have a look at the docs.

So if you need to read a Request's content, for example in tests, make sure to read it before calling SendAsync.

like image 45
Philip Bijker Avatar answered Oct 24 '22 04:10

Philip Bijker


You are accessing the request Content, not the Response.

This

await httpClient.SendAsync(req);
var result = await req.Content.ReadAsStringAsync(); //Cannot access a disposed object. Object name: 'System.Net.Http.StringContent'.

should be

var response = httpClient.SendAsync(req);
var result = await response.Content.ReadAsStringAsync();
like image 6
Tseng Avatar answered Oct 24 '22 05:10

Tseng