biz00ka
biz00ka

Reputation: 25

A first chance exception of type "System.ArgumentException" occured in mscorlib.dll

  try
        {
            FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
            req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
            using (var resp = (FtpWebResponse)req.GetResponse())
            {
                Console.WriteLine(resp.WelcomeMessage);
            }
            FtpWebResponse res = (FtpWebResponse)req.GetResponse();
            Stream rs = res.GetResponseStream();
            StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A
            Console.WriteLine(read1.ReadToEnd());
            Console.WriteLine("Directory is compleate,status(0)",
            res.StatusDescription);
            read1.Close();
            rs.Close();
        }
        catch (Exception e1)
        {
            Console.WriteLine(e1.Message);
        }

I am trying to access ftp server via C#.

However, the code errors with an exception:
A first chance exception of type "System.ArgumentException" occured in mscorlib.dll. Stream was not readable.

Any help will be appreciated.

Upvotes: 2

Views: 17357

Answers (2)

schei1
schei1

Reputation: 2487

TLDR; The state of the FtpWebResponse object is disposed, therefore you cannot read the response stream. The stream is closed.

Disassembly of FtpWebResponse:

public override void Close()
        {
            if (Logging.On)
            {
                Logging.Enter(Logging.Web, this, "Close", "");
            }
            if (this.HttpProxyMode)
            {
                this.m_HttpWebResponse.Close();
            }
            else
            {
                Stream responseStream = this.m_ResponseStream;
                if (responseStream != null)
                {
                    responseStream.Close();
                }
            }
            if (Logging.On)
            {
                Logging.Exit(Logging.Web, this, "Close", "");
            }
        }

The reason you get the exception, is that you are reading the response:

using (var resp = (FtpWebResponse)req.GetResponse())
{
    Console.WriteLine(resp.WelcomeMessage);
}

and on the next line, you try to read the response again, into another variable: res

FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A

In that section, you also do a call to the res.GetResponseStream() twice, but that does not matter in terms of the error occuring. The error will occur even if you change it to:

FtpWebResponse res = (FtpWebResponse)req.GetResponse();
Stream rs = res.GetResponseStream();
StreamReader read1 = new StreamReader(rs);// prob A

Or:

FtpWebResponse res = (FtpWebResponse)req.GetResponse();
StreamReader read1 = new StreamReader(res.GetResponseStream());// prob A

The reason that the error occurs, is the state of the FtpWebResponse object, which is disposed; and has the StatusCode = ClosingData. When I try to read the stream in that state, I get the error you are experiencing. In the using block before, the StatusCode = OpeningData.

However, if you just change a couple of lines to:

using (var resp = (FtpWebResponse)req.GetResponse())
{
    Console.WriteLine(resp.WelcomeMessage);
    Stream rs = res.GetResponseStream();
    StreamReader read1 = new StreamReader(rs);// prob A
    Console.WriteLine(read1.ReadToEnd());
    Console.WriteLine("Directory is compleate,status(0)", res.StatusDescription);
}

When entering this using scope, the StatusCode = OpeningData, and stream is available and readable. When exiting the scope, the StatusCode = ClosingData, and stream will not be readable.

Hope this make some sense, and correct me if I'm wrong. :-)

With these small changes your code will run as expected. However you should look into the pattern @DmitryBychenko proposes. That way you will have access to the resources within the scope that they're needed, and disposed afterwards.

Upvotes: 0

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186803

Put all IDisposable resources within using(...) {...}. That technics prevents resource leaking/closed resources invoking:

try {
  FtpWebRequest req = (FtpWebRequest)WebRequest.Create("ftp path");
  req.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

  // Response: we're going to work wuth respose within "using" block only
  using (FtpWebResponse resp = (FtpWebResponse)req.GetResponse()) {
    Console.WriteLine(resp.WelcomeMessage);

    // Reader: once again reader's opened once and called within using only
    using (StreamReader reader = new StreamReader(resp.GetResponseStream())) {
      Console.WriteLine(reader.ReadToEnd());
      Console.WriteLine("Directory is complete, status(0)", resp.StatusDescription);
    }
  }
catch (Exception ex) { // <- Bad idea to catch all possible exceptions without "throw;"
  Console.WriteLine(ex.Message);
}

Upvotes: 2

Related Questions