2009-02-10 10 views
8

Ich habe ein Problem mit der .NET Uri-Implementierung. Es scheint, dass, wenn das Schema "ftp" ist, der Abfrageteil nicht als Abfrage geparst wird, sondern als Teil des Pfades.Alternative zu .NET Uri-Implementierung?

Nehmen Sie den folgenden Code beispielsweise:

Uri testuri = new Uri("ftp://user:[email protected]/?passive=true"); 
Console.WriteLine(testuri.Query); // Outputs an empty string 
Console.WriteLine(testuri.AbsolutePath); // Outputs "/%3Fpassive=true" 

Es scheint mir, dass die Uri-Klasse zu Unrecht die Abfrage Teil als Teil des Pfades analysiert. Doch das System zu ändern, um HTTP, wird das Ergebnis als erwartet:

Uri testuri = new Uri("http://user:[email protected]/?passive=true"); 
Console.WriteLine(testuri.Query); // Outputs "?passive=true" 
Console.WriteLine(testuri.AbsolutePath); // Outputs "/" 

Hat jemand eine Lösung für dieses Problem hat, oder weiß von einer alternativen Uri-Klasse, die wie erwartet funktioniert?

Antwort

4

Nun, das Problem ist nicht, dass ich nicht in der Lage bin eine FTP-Verbindung zu schaffen, sondern dass URIs werden accoding RFC nicht analysiert 2396.

Was wollte ich eigentlich tun Es sollte eine Factory erstellt werden, die Implementierungen einer generischen Dateiübertragungsschnittstelle (die get- und put-Methoden enthält) basierend auf einem gegebenen Verbindungs-URI bereitstellt. Der URI definiert das Protokoll, die Benutzerinformationen, den Host und den Pfad. Alle Eigenschaften, die übergeben werden müssen, sollten über den Abfrageteil des URI übergeben werden (z. B. die Passive-Modus-Option für die FTP-Verbindung).

Allerdings erwies sich dies mit der .NET Uri-Implementierung als schwierig, da es den Abfrageteil von URIs basierend auf dem Schema unterschiedlich zu analysieren scheint.

So hatte ich gehofft, dass jemand einen Workaround zu diesem oder einer Alternative zu der scheinbar gebrochenen .NET Uri-Implementierung kannte. Wäre schön zu wissen, bevor ich Stunden damit verbringe, meine eigenen zu implementieren.

1

Sie müssen eine bestimmte Klasse für FTP-Protokoll wie FtpWebRequest verwenden, die eine Uri-Eigenschaft wie RequestUri hat.

Sie sollten in diesen Klassen nach einem Uri-Parser suchen, denke ich.

2

Sie sollten die Klassen FtpWebRequest und FtpWebResponse verwenden, es sei denn, Sie haben einen bestimmten Grund nicht.

FtpWebRequest.fwr = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://uri")); 
fwr.ftpRequest.Method = WebRequestMethods.Ftp.UploadFile; 
fwr.ftpRequest.Credentials = new NetworkCredential("user", "pass"); 


FileInfo ff = new FileInfo("localpath"); 
byte[] fileContents = new byte[ff.Length]; 

using (FileStream fr = ff.OpenRead()) 
{ 
    fr.Read(fileContents, 0, Convert.ToInt32(ff.Length)); 
} 

using (Stream writer = fwr.GetRequestStream()) 
{ 
    writer.Write(fileContents, 0, fileContents.Length); 
} 

FtpWebResponse frp = (FtpWebResponse)fwr.GetResponse(); 
Response.Write(frp.ftpResponse.StatusDescription); 

Ref1Ref2

2

Ich habe mit dem gleichen Problem für eine Weile gekämpft. Der Versuch, den vorhandenen UriParser für das "ftp" -Schema zu ersetzen, indem UriParser.Register verwendet wird, löst einen InvalidOperationException aus, weil das Schema bereits registriert ist.

Die Lösung, die ich mir ausgedacht habe, beinhaltet die Verwendung von Reflection, um den vorhandenen FTP-Parser so zu modifizieren, dass er die Abfragezeichenfolge erlaubt. Dies basiert auf einer Problemumgehung zu another UriParser bug.

MethodInfo getSyntax = typeof(UriParser).GetMethod("GetSyntax", System.Reflection.BindingFlags.Static 
                   | System.Reflection.BindingFlags.NonPublic); 
FieldInfo flagsField = typeof(UriParser).GetField("m_Flags", System.Reflection.BindingFlags.Instance 
                  | System.Reflection.BindingFlags.NonPublic); 
if (getSyntax != null && flagsField != null) 
{ 
    UriParser parser = (UriParser)getSyntax.Invoke(null, new object[] { "ftp"}); 
    if (parser != null) 
    { 
     int flagsValue = (int)flagsField.GetValue(parser); 

     // Set the MayHaveQuery attribute 
     int MayHaveQuery = 0x20; 
     if ((flagsValue & MayHaveQuery) == 0) flagsField.SetValue(parser, flagsValue | MayHaveQuery); 
    } 
} 

Run, die irgendwo in der Initialisierung und Ihr ftp Uris wird die Query-String gehen in den Query Parameter haben, wie man erwarten würde, statt Path.