Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin Android httpwebrequest, Cannot access a disposed object

I have an android mobile app , and i want to send webrequest to server to post some data, but before posting the data i send an http get request to get some data, and then sending post request , first i receive get successfully but when i send the post request it throws bellow exception on this line of my code requestStream.Write(bytes, 0, bytes.Length);

the exception is :

System.ObjectDisposedException: Cannot access a disposed object. Object name: 'System.Net.Sockets.NetworkStream'.

and here is my get and post request code GET:

public void GetTokenInfo()
        {

            try
            {
                var uri = new Uri(string.Format(_host + "webserver/SesTokInfo", string.Empty));
                var webRequest = WebRequest.Create(uri);
                using (var response = webRequest.GetResponse() as HttpWebResponse)
                {
                    using (var requestStream = response.GetResponseStream())
                    {
                        using (var reader = new StreamReader(requestStream))
                        {
                            var content = reader.ReadToEnd();
                            XmlDocument xDocument = new XmlDocument();
                            xDocument.LoadXml(content);
                            XmlElement root = xDocument.DocumentElement;
                            if (IsResponseReturned(root))
                            {
                                GlobalConfig.SessionId = root.GetElementsByTagName("SesInfo")[0].InnerText;
                                GlobalConfig.Token = root.GetElementsByTagName("TokInfo")[0].InnerText;

                            }
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                Debug.WriteLine(exception);
            }
        }

with this code i get receive my result without any problem, and here is my POST:

 public WebResponse PostData(string body, string url)
        {
            WebResponse webResponse = null;
            try
            {
                var uri = new Uri(string.Format(_host + url, string.Empty));
                var webRequest = (HttpWebRequest)WebRequest.Create(uri);
                webRequest.Headers.Add("Cookie",
                    GlobalConfig.SessionId);
                webRequest.Headers.Add("_RequestVerificationToken", GlobalConfig.Token);
                webRequest.Method = "POST";
                webRequest.ContentType = "application/xml";
                byte[] bytes = Encoding.UTF8.GetBytes(body);
                webRequest.ContentLength = bytes.Length;
                Stream requestStream = webRequest.GetRequestStream();
                requestStream.Write(bytes, 0, bytes.Length);
                webResponse = webRequest.GetResponse();
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
            return webResponse;
        }

i have searched and tried ways but i did not get the solution , and plus when i comment the first function, and only run the second function it will work fine but when i run the first and then the second it throws the exception , does anything belong to dispose the stream and web response from first code? i think using statement is already disposes them.

any help appreciated.

like image 773
Younis Qadir Avatar asked Aug 16 '17 13:08

Younis Qadir


4 Answers

This may just be a case of making sure to use the correct using statements as they properly handle closing the outgoing and incoming streams when appropriate. See the below modified example, this should work for you:

public string PostData(string body, string url)
{
    string responseText = null;

    try
    {
        var uri = new Uri(string.Format(_host + url, string.Empty));
        var webRequest = WebRequest.Create(uri) as HttpWebRequest;

        webRequest.Headers.Add("Cookie", GlobalConfig.SessionId);
        webRequest.Headers.Add("_RequestVerificationToken", GlobalConfig.Token);
        webRequest.Method = "POST";
        webRequest.ContentType = "application/xml";

        using (Stream requestStream = webRequest.GetRequestStream())
        {
            using (StreamWriter writer = new StreamWriter(requestStream))
            {
                writer.Write(body);
            }
        }

        var webResponse = webRequest.GetResponse() as HttpWebResponse;

        using (Stream responseStream = webResponse.GetResponseStream())
        {
            using (StreamReader reader = new StreamReader(responseStream))
            {
                responseText = reader.ReadToEnd();
            }
        }
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception);
    }

    return responseText;
}

Note I have modified the return variable to a string body so that you are not potentially leaving a stream open.

Koda

like image 103
Kodaloid Avatar answered Oct 31 '22 16:10

Kodaloid


  • is your device/emulator connected to internet?

  • your application has required permission for connect to internet?

  • You have to close the request stream requestStream.Close() before call webRequest.GetResponse()

  • It is required to use using for IDisposable objects as in your GetTokenInfo() method, else you will have memory overuse problems

I just test you code and IT WORKS, this is my full test console application

using System;
using System.IO;
using System.Net;
using System.Text;

namespace test01
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            PostData("a", "/");
        }

        public static WebResponse PostData(string body, string url)
        {
            WebResponse webResponse = null;
            try
            {
                var uri = new Uri(string.Format("http://google.it" + url, string.Empty));
                var webRequest = (HttpWebRequest)WebRequest.Create(uri);
                webRequest.Headers.Add("Cookie","test");
                webRequest.Headers.Add("_RequestVerificationToken", "test");
                webRequest.Method = "POST";
                webRequest.ContentType = "application/xml";
                byte[] bytes = Encoding.UTF8.GetBytes(body);
                webRequest.ContentLength = bytes.Length;
                Stream requestStream = webRequest.GetRequestStream();
                requestStream.Write(bytes, 0, bytes.Length);
                webResponse = webRequest.GetResponse();
            }
            catch (Exception exception)
            {
                Console.WriteLine(exception);
            }
            return webResponse;
        }
    }
}
like image 25
Danilo Calzetta Avatar answered Oct 31 '22 17:10

Danilo Calzetta


just to be safe - try removing extra using - instead of

using (var requestStream = response.GetResponseStream()) { using (var reader = new StreamReader(requestStream))

use

using (var reader = new StreamReader(response.GetResponseStream())

See https://msdn.microsoft.com/library/ms182334.aspx for details.

like image 1
Mikl X Avatar answered Oct 31 '22 17:10

Mikl X


After trying many ways and read above answers and try them finally i get solved the problem by making the both code like the following , GET one:

                var uri = new Uri(string.Format(_host + "webserver/SesTokInfo", string.Empty));
                var webRequest = WebRequest.Create(uri);
                using (var response = webRequest.GetResponse() as HttpWebResponse)
                {
                    using (var reader = new StreamReader(response.GetResponseStream()))
                    {
                        var content = reader.ReadToEnd();
                        XmlDocument xDocument = new XmlDocument();
                        xDocument.LoadXml(content);
                        XmlElement root = xDocument.DocumentElement;
                        if (IsResponseReturned(root))
                        {
                            GlobalConfig.SessionId = root.GetElementsByTagName("SesInfo")[0].InnerText;
                            GlobalConfig.Token = root.GetElementsByTagName("TokInfo")[0].InnerText;

                        }
                    }
                }

and POST one:

                var uri = new Uri(string.Format(_host + url, string.Empty));
                var webRequest2 = (HttpWebRequest)WebRequest.Create(uri);


                webRequest2.Headers.Add("Cookie",
                    GlobalConfig.SessionId);
                webRequest2.Headers.Add("_RequestVerificationToken", GlobalConfig.Token);
                webRequest2.Method = "POST";
                webRequest2.ContentType = "application/xml";

                byte[] bytes = Encoding.UTF8.GetBytes(body);
                webRequest2.ContentLength = bytes.Length;
                StreamWriter writer = new StreamWriter(webRequest2.GetRequestStream());
                writer.Write(bytes);
                webResponse = webRequest2.GetResponse();

when i use the request stream inside using block it will still throw the exception but with out using block it will work :)

like image 1
Younis Qadir Avatar answered Oct 31 '22 18:10

Younis Qadir