简体   繁体   中英

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()

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.

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 .

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM