La clase System.Net.FtpWebRequest se comporta de forma diferente .NET Framework 4 vs .NET Framework 3.5

Este artículo le ayuda a corregir el error FTP 5xx que se produce al usar la clase en Microsoft .NET Framework 4 para realizar System.Net.FtpWebRequest el FTP o el STOR RETR comando.

Versión del producto original:   .NET Framework
Número KB original:   2134299

Síntomas

Cuando se usa la clase en .NET Framework 4 para realizar el FTP o el comando, la clase produce un System.Net.FtpWebRequest STOR error FTP RETR 5xx, por ejemplo:

Error de sintaxis 501: falta el remitente o el receptor.

Sin embargo, esta clase funciona bien .NET Framework 3.5 y no genera el mismo error.

Causa

La causa de este problema se debe a un cambio de comportamiento en la System.Net.FtpWebRequest clase en .NET Framework 4. Se ha realizado un cambio en la clase de .NET Framework 3.5 a .NET Framework 4 para simplificar el uso de System.Net.FtpWebRequest los CWD comandos de protocolo. La nueva implementación de la clase impide el envío de comandos adicionales antes de emitir el comando real, que el usuario solicitó y en su lugar envía directamente System.Net.FtpWebRequest CWD el comando solicitado. En el caso de los servidores FTP totalmente compatibles con RFC, no debería ser un problema, pero en el caso de los servidores que no cumplen totalmente con RFC, verá estos tipos de errores.

Solución

Para resolver este problema, es necesario forzar al comando a volver al comportamiento antiguo de cómo funcionaba en System.Net.FtpWebRequest .NET Framework 2.0 o 3.5 y emitir el comando adicional antes de emitir el CWD comando real.

El siguiente código debe colocarse antes de invocar cualquier instancia de System.Net.FtpWebRequest la clase.

El código siguiente solo debe llamarse una vez, ya que cambia la configuración de todo el dominio de la aplicación.

private static void SetMethodRequiresCWD ()
{
    Type requestType = typeof (FtpWebRequest);
    FieldInfo methodInfoField = requestType.GetField ("m_MethodInfo", BindingFlags.NonPublic | BindingFlags.Instance);
    Type methodInfoType = methodInfoField.FieldType;
    FieldInfo knownMethodsField = methodInfoType.GetField ("KnownMethodInfo", BindingFlags.Static | BindingFlags.NonPublic);
    Array knownMethodsArray = (Array) knownMethodsField.GetValue (null);
    FieldInfo flagsField = methodInfoType.GetField ("Flags", BindingFlags.NonPublic | BindingFlags.Instance);
    int MustChangeWorkingDirectoryToPath = 0x100;
    foreach (object knownMethod in knownMethodsArray)
    {
        int flags = (int) flagsField.GetValue (knownMethod);
        flags |= MustChangeWorkingDirectoryToPath;
        flagsField.SetValue (knownMethod, flags);
    }
}

Cambios en el comportamiento de FtpWebRequest

El comportamiento de la System.Net.FtpWebRequest clase ha cambiado en .NET Framework 4 vs .NET Framework 3.5.

En .NET Framework 3.5, un archivo cargado en un servidor mediante la clase siguió un intercambio típico de System.Net.FtpWebRequest los siguientes comandos FTP:

  • USE
  • PASS
  • OPTS
  • PWD
  • CWD
  • STOR

Sin embargo, .NET Framework 4, una carga de archivos típica pasa por la siguiente secuencia de comandos:

  • USER
  • PASS
  • OPTS
  • PWD
  • STOR

La diferencia entre los dos comportamientos es que en la versión 3.5, la carga se produce realizando un comando para cambiar el directorio actual al directorio previsto, seguido del comando con solo el nombre de CWD STOR archivo.

Sin embargo, .NET Framework implementación de 4 impide el envío del comando CWD adicional y envía el comando directamente al directorio de destino con la STOR estructura de directorios completa.

Para servidores FTP totalmente compatibles con RFC, no sería un problema, pero para otros, este comportamiento puede interrumpir el funcionamiento de las aplicaciones existentes con .NET Framework 4.

Para dicha comunicación del servidor, verá que el servidor responde con un código de error FTP: 5xx, como 501 Error de sintaxis: falta el remitente o el receptor, mientras que el mismo código funcionará para la clase cuando se usa con System.Net.FtpWebRequest el .NET Framework 3.5.