web-dev-qa-db-fra.com

ObjectDisposedException sur HttpClient

J'ai un projet universel Windows avec plusieurs appels API. Une méthode refuse de fonctionner même si mes autres appels fonctionnent parfaitement comme ça. J'ai essayé le mot clé using, pensant que cela résoudrait le problème.

La fonction:

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;
        }
    }
}

MODIFIER

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;
        }
    }
}

Le 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()
16
tim

ObjectDisposedException est levée car vous supprimez HttpRequestMessage et HttpClient avant la fin de req.Content.ReadAsStringAsync().

Notez que req.Content.ReadAsStringAsync() est une méthode asynchrone. Vous devez attendre qu'il se termine avant de supprimer le HttpClient.

De plus, vous semblez appeler ReadAsStringAsync dans req.Content, cela ne devrait-il pas être 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;
}

Il n'y a presque aucune raison d'utiliser ContinueWith pour traiter async/wait. Tout cela est fait par le compilateur pour vous.

17
Sriram Sakthivel

La vraie raison pour laquelle le ObjectDisposedException est levé est que le HttpClient supprime le Content immédiatement après une requête terminée. Jetez un oeil à la docs .

Donc, si vous avez besoin de lire le contenu d'un Request, par exemple dans des tests, assurez-vous de le lire avant d'appeler SendAsync.

7
Philip Bijker

Vous accédez au contenu de la demande, pas à la réponse.

Ce

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

devrait être

var response = httpClient.SendAsync(req);
var result = await response.Content.ReadAsStringAsync();
5
Tseng