Ich habe dies soeben auf einem unserer Entwicklungsserver getestet, und es wird tatsächlich ein CWD von der .NET FtpWebRequest ausgegeben:
new connection from 172.16.3.210 on 172.16.3.210:21 (Explicit SSL)
hostname resolved : devpc
sending welcome message.
220 Gene6 FTP Server v3.10.0 (Build 2) ready...
USER testuser
testuser, 331 Password required for testuser.
testuser, PASS \*\*\*\*
testuser, logged in as "testuser".
testuser, 230 User testuser logged in.
testuser, OPTS utf8 on
testuser, 501 Please CLNT first.
testuser, PWD
**testuser, 257 "/" is current directory.
testuser, CWD /
testuser, change directory '/' -> 'D:\\testfolder' --> Access allowed.
testuser, 250 CWD command successful. "/" is current directory.**
testuser, TYPE I
testuser, 200 Type set to I.
testuser, PORT 172,16,3,210,4,127
testuser, 200 Port command successful.
testuser, NLST
testuser, 150 Opening data connection for directory list.
testuser, 226 Transfer ok.
testuser, 421 Connection closed, timed out.
testuser, disconnected. (00d00:05:01)
Dies geschah, ohne dass bei der Erstellung des FtpWebRequest-Objekts '/' in der Uri angegeben wurde.
Wenn Sie den Quellcode debuggen oder durchsuchen, kommt eine Klasse namens 'FtpControlStream' ins Spiel. Siehe Aufrufstapel:
System.dll!System.Net.FtpControlStream.BuildCommandsList(System.Net.WebRequest req) Line 555 C#
System.dll!System.Net.CommandStream.SubmitRequest(System.Net.WebRequest request =
{System.Net.FtpWebRequest}, bool async = false, bool readInitalResponseOnConnect = true) Line 143 C#
System.dll!System.Net.FtpWebRequest.TimedSubmitRequestHelper(bool async) Line 1122 + 0x13 bytes C#
System.dll!System.Net.FtpWebRequest.SubmitRequest(bool async = false) Line 1042 + 0xc bytes C#
System.dll!System.Net.FtpWebRequest.GetResponse() Line 649 C#
Es gibt eine Methode namens BuildCommandsList(), die aufgerufen wird. BuildCommandsList() erstellt eine Liste von Befehlen, die an den FTP-Server gesendet werden. Diese Methode enthält den folgenden Codeschnipsel:
if (m_PreviousServerPath != newServerPath) {
if (!m_IsRootPath
&& m_LoginState == FtpLoginState.LoggedIn
&& m_LoginDirectory != null)
{
newServerPath = m_LoginDirectory+newServerPath;
}
m_NewServerPath = newServerPath;
commandList.Add(new PipelineEntry(FormatFtpCommand("CWD", newServerPath), PipelineEntryFlags.UserCommand));
}
Bei der ersten Verbindung zum Server ist m_PreviousServerPath immer null, der Wert von newServerPath ist "/" und wird von einer Funktion namens GetPathAndFileName() berechnet (die einige Zeilen vor diesem Codeblock aufgerufen wird). GetPathAndFileName() berechnet newServerPath als "/", wenn kein Pfad angegeben wird oder wenn "/" explizit an das Ende der 'ftp://....' uri angehängt wird.
Dies führt natürlich letztendlich dazu, dass der CWD-Befehl der Befehlspipeline hinzugefügt wird, da null != "/".
Kurz gesagt kann man dieses Verhalten leider nicht außer Kraft setzen, da es im Quelltext eingebrannt ist.