title: FtpWebRequest WebException: "Unable to connect to the remote server"
body: <p>
  I have code in a Windows Service that successfully connects to an FTP server when I run it locally through a test harness (with the FTP server being on another machine on the local network).</p>
  
  <p>When I install it in the production hosting environment, though, I get the dreaded WebException "Unable to connect to the remote server". It doesn't seem to matter whether I'm using <a href="http://en.wikipedia.org/wiki/File_Transfer_Protocol#Protocol_overview" rel="nofollow noreferrer"><code>ACTV</code> or <code>PASV</code> FTP</a>, all I get it this WebException. If I try to FTP from the Windows command line, however, it works perfectly well (so it's not the firewall at fault).</p>
  
  <p>The code I'm using (adapted from <a href="https://stackoverflow.com/questions/3298922/how-to-list-directory-contents-with-ftp-in-c">How to List Directory Contents with FTP in C#?</a>) reads:</p>
  
  <pre class="lang-cs prettyprint-override"><code>private static readonly string __ftpSourceServer = "ftp://"
    + ConfigurationManager.AppSettings["FtpServer"] + "/";
  private static readonly NetworkCredential __ftpCreds = new NetworkCredential(
    ConfigurationManager.AppSettings["Username"],
    ConfigurationManager.AppSettings["Password"]);
  
  // And now the method MediaSyncDaemon.GetFilesToFetch:
  bool usePassive = Boolean.TryParse(ConfigurationManager.AppSettings["UsePassive"]
    , out usePassive) &amp;&amp; usePassive;
  
  Uri ftpSrv = new Uri(__ftpSourceServer + Uri.EscapeUriString(
    ConfigurationManager.AppSettings["FtpPath"]));
  Logger.Debug("Connecting to FTP server at " + ftpSrv + "; PASV? " + usePassive);
  
  FtpWebRequest listRequest = (FtpWebRequest) WebRequest.Create(ftpSrv);
  listRequest.Method = WebRequestMethods.Ftp.ListDirectory;
  listRequest.Credentials = __ftpCreds;
  listRequest.UsePassive = usePassive;
  listRequest.UseBinary = false;
  
  using (FtpWebResponse listResponse = (FtpWebResponse) listRequest.GetResponse())
  {
      // ReSharper disable AssignNullToNotNullAttribute
      return new StreamReader(listResponse.GetResponseStream())
          .ReadToEnd().Split(new[] { '\n', '\r' },
              StringSplitOptions.RemoveEmptyEntries)
          .Where(s =&gt; s.EndsWith(".zip", true, CultureInfo.InvariantCulture))
          .ToList();
      // ReSharper restore AssignNullToNotNullAttribute
  }
  </code></pre>
  
  <p>The exception is thrown at the <code>FtpWebRequest.GetResponse()</code> call in the <code>using</code> line (outside the <code>return</code> statement), with nothing else in the stack trace:</p>
  
  <blockquote>
    <p><code>System.Net.WebException</code>: Unable to connect to the remote server<br>
       at <code>System.Net.FtpWebRequest.GetResponse()</code><br>
       at (that line number in that file)</p>
  </blockquote>
  
  <p>The only real difference between my test harness (which works) and the production environment (which doesn't) is the presence of a firewall in the production environment — all four servers are on slightly different subnets:</p>
  
  <pre class="lang-none prettyprint-override"><code>Dev client    10.16.6.155     subnet 255.255.255.128
  Dev server    10.16.7.242     subnet 255.255.255.0
  Prod client   192.168.102.107 subnet 255.255.255.0
  Prod server   192.168.203.110 subnet 255.255.255.0
  </code></pre>
  
  <p>but the firewall can't be the problem is I can FTP from Prod client to Prod server interactively, just not programmatically.</p>
  
  <p>I've tried changing the <code>bool</code> appSettings value for <code>UsePassive</code> and that makes no difference and, in every case, nothing shows up in the FTP server log (so it's not getting that far).</p>
  
  <p>Now I'm not expecting anyone to be able to debug the hardware infrastructure of my hosting environment, but I'm struggling to think of what else I could vary to get this to work. I've seen it work locally in my test harness, calling the same method. In case it helps, the test harness code reads as follows:</p>
  
  <pre class="lang-cs prettyprint-override"><code>[NUnit.Framework.Test]
  public void FtpFileListTest()
  {
      ICollection&lt;string&gt; files = MediaSyncDaemon.GetFilesToFetch();
      Assert.IsNotNull(files);
      Assert.Greater(files.Count, 0);
  }
  </code></pre>
  
  <p>Does anyone have any ideas of what else I could try, please?</p>
  
  <p>Thanks!</p>
  
  <hr>
  
  <h2>Update</h2>
  
  <p>Having had some suggestions of places to look in the comments, I can update this a little further:</p>
  
  <ol>
  <li><p>The problem does not appear to be user permissions — the service is running in the context of the Local System account (which <a href="https://stackoverflow.com/a/510225/205245">has more permissions than Administrator</a> does)</p></li>
  <li><p>The problem does not appear to be code-access security. I've added a <a href="http://msdn.microsoft.com/en-gb/library/system.net.socketpermission(v=vs.100).aspx" rel="nofollow noreferrer"><code>SocketPermission</code></a><code>.</code><a href="http://msdn.microsoft.com/en-gb/library/system.security.codeaccesspermission.demand(v=vs.100).aspx" rel="nofollow noreferrer"><code>Demand</code></a> call to the entry method for this chunk of code:</p>
  
  <pre class="lang-cs prettyprint-override"><code>System.Security.CodeAccessPermission socketPermission;
  socketPermission = new SocketPermission(NetworkAccess.Connect,
    TransportType.Tcp, ConfigurationManager.AppSettings["FtpServer"], 20);
  socketPermission.Demand();
  socketPermission = new SocketPermission(NetworkAccess.Connect,
    TransportType.Tcp, ConfigurationManager.AppSettings["FtpServer"], 21);
  socketPermission.Demand();
  </code></pre>
  
  <p>And I'm not seeing any <a href="http://msdn.microsoft.com/en-gb/library/system.security.securityexception(v=vs.100).aspx" rel="nofollow noreferrer">SecurityException</a> being thrown as a result; I'm still getting the same WebException, at the new line number for that same code position.</p></li>
  </ol>
  
  <p>Does anyone have any further suggestions of what I could try?</p>