locked
WCF und System.IO.FileSystemInfo RRS feed

  • Frage

  • Hallo,

    ich habe einen WCF Dienst über NamedPipes angebunden. Im Grunde eine Art Client-Server-Anwendung. Der Client soll das lokale Dateisystem des Servers anzeigen können. Dazu habe ich Funktionen in der Schnittstelle bereitgestellt, die gleich System.IO.FileSystemInfo zurückliefern. Was mir das einfachste schien.

    Jedenfalls bekomme ich nun eine Exception vom WCF:

    [System.ServiceModel.CommunicationException]    {"Fehler beim Lesen aus der Pipe: Die Pipe wurde beendet. (109, 0x6d)."}    System.ServiceModel.CommunicationException

    Das Problem hatte ich schonmal, was an der Serialisierung der Klasse liegt. Damals hatte ich bei meinen Klassen einfach alle Attribute und die Klasse selbst mit [DataMember] usw. markiert und es hat geklappt.

    FileSystemInfo kann ich ja nicht anpassen.
    So meine Frage: Gibt es eine Möglichkeit, dass ich so eine FileSystemInfo-Klasse über WCF weitergebe? Oder muss ich die selber nochmal implementieren und dann mit den entsprechenden WCF-Attributen markieren?

    Vielen Dank und MFG,
    Ronny

    Montag, 12. Juli 2010 06:27

Antworten

  • Hallo Ronny,

    ich habe das kurz mal im Beispiel: ...\Basic\Contract\Data\DataContractSerializer\CS\client\client.cs
    in folgenden Beispiel-Projekten: [Download details: WCF WF Samples for .NET Framework 4]
    [One-Time Setup Procedure for the Windows Communication Foundation Samples]
    wie folgt (auf einem lokalen Rechner) getestet: 

     [DataContract(Namespace = "http://Microsoft.Samples.DataContractSerializer")]
     [KnownType(typeof(DirectoryInfo))] // neu
     internal class Record
     {
      private double n1;
      private double n2;
      private string operation;
      private double result;
      private FileSystemInfo fsi; // neu
    
      internal Record(double n1, double n2, string operation, double result)
      {
       this.n1 = n1;
       this.n2 = n2;
       this.operation = operation;
       this.result = result;
       
       this.fsi = new DirectoryInfo("c:\\Test"); // neu
      }
    
      [DataMember] // neu
      internal FileSystemInfo DateiInfo
      {
       get { return fsi; }
       set { fsi = value; }
      }
    
    bei mir klappt es.

    ciao Frank
    Dienstag, 13. Juli 2010 20:30

Alle Antworten

  • Hallo,

    danke erstmal für die Links, aber die Probleme scheinen es nicht zu sein.

    Was die bekannten Datentypen angeht, hatte ich probiert FileSystemInformation als ServiceKnownType zu deklarieren, was jedoch keine Änderung mit sich brachte.

    Was das Timeout angeht, hab ich mal die Menge der Daten (es wird eine List: List<FileSystemInformation> zurückgeliefert) auf einen einzigen Eintrag also List.Count() == 1 reduziert. Jedoch hatte auch dies kei Effekt. Also nehm ich an, daran liegts wohl nicht?

    Kann ich die FileSystemInformation-Klasse nicht irgendwie explizit der Serialisierung hinzufügen? Oder irgendwie markieren?

    Mir ist aufgefallen, dass ich eigene Typen (struct) verwende die ich ebenfalls als List<struct> zurückgebe. Diese structs sind überhaupt nicht als DataMember markiert und dort funktioniert es problemlos.

    Irgendwie weiß ich nicht weiter. ;-)

    Danke

    Montag, 12. Juli 2010 08:53
  • Es liegt IMHO eher nicht an den NamedPipes, sondern an der Serialisierung.
    Hier ggf. Möglichkeiten:

    [Sending a FileInfo object to client]
    http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/f947cba9-89b9-4932-b60d-cab28c7e657f

     


    ciao Frank
    Montag, 12. Juli 2010 09:23
  • Hallo,

    danke. Hab mir den Beitrag durchgelesen. Klingt vielversprechend, aber ich bekoms nicht hin. ;-)

    Die haben das gelöst, indem sie die svutil manuell ausführen. Bei mir übernimmt das VS 2010. Ich kann dort auch keine Parameter übergeben und das Häckchen bei "Reuse types in all referenced assemblies" ist an.

    Hab mir aber den Hinweis mit dem Trace Viewer angenommen und bekomm nun zumindest vom WCF Service eine genauere Meldung über das Problem.

    Fehler beim Deserialisieren von Parameter http://tempuri.org/:getFSChildrenOfVolume
    Result. Die InnerException-Nachricht war "Der Typ "System.IO.DirectoryInfo" mit dem Datenvertragsnamen "DirectoryInfo:http://schemas.datacontract.org/2004/07/System.IO" wurde nicht erwartet. Fügen Sie alle statisch nicht bekannten Typen der Liste der bekannten Typen hinzu. Verwenden Sie dazu z. B. das Attribut "KnownTypeAttribute", oder fügen Sie die Typen der an DataContractSerializer übergebenen Liste von bekannten Typen hinzu.". Weitere Details finden Sie unter "InnerException".

    InnerException:
    Der Typ "System.IO.DirectoryInfo" mit dem Datenvertragsnamen "DirectoryInfo:http://schemas.datacontract.org/2004/07/System.IO" wurde nicht erwartet. Fügen Sie alle statisch nicht bekannten Typen der Liste der bekannten Typen hinzu. Verwenden Sie dazu z. B. das Attribut "KnownTypeAttribute", oder fügen Sie die Typen der an DataContractSerializer übergebenen Liste von bekannten Typen hinzu.

    Das Problem ist, dass ich "KnownType" ja eigentlich in der FileSystemInfo-Klasse hinzufügen müsste. Die liegt jedoch im Namespace von .NET. Wenn ich bei mir vor den [OperationContract] der die Klasse verwendet einfach [ServiceKnownType(typeof(FileSystemInfo))] einsetze, ändert das nichts an dem Fehler.

    Hat noch jemand eine Idee?

    Vielen Dank,

    Ronny

    Montag, 12. Juli 2010 11:32
  • Hallo Ronny,

    ich habe das kurz mal im Beispiel: ...\Basic\Contract\Data\DataContractSerializer\CS\client\client.cs
    in folgenden Beispiel-Projekten: [Download details: WCF WF Samples for .NET Framework 4]
    [One-Time Setup Procedure for the Windows Communication Foundation Samples]
    wie folgt (auf einem lokalen Rechner) getestet: 

     [DataContract(Namespace = "http://Microsoft.Samples.DataContractSerializer")]
     [KnownType(typeof(DirectoryInfo))] // neu
     internal class Record
     {
      private double n1;
      private double n2;
      private string operation;
      private double result;
      private FileSystemInfo fsi; // neu
    
      internal Record(double n1, double n2, string operation, double result)
      {
       this.n1 = n1;
       this.n2 = n2;
       this.operation = operation;
       this.result = result;
       
       this.fsi = new DirectoryInfo("c:\\Test"); // neu
      }
    
      [DataMember] // neu
      internal FileSystemInfo DateiInfo
      {
       get { return fsi; }
       set { fsi = value; }
      }
    
    bei mir klappt es.

    ciao Frank
    Dienstag, 13. Juli 2010 20:30
  • Hallo,

    danke für die Antwort.

    Bei dir klappt es wohl, weil du das FileSystemInfo innerhalb einer Klasse Record verwendet, welche du wiederum als DataContract deklarierst. Ich habe aber keine Klasse die FileSystemInfo als Teil verwendet, sondern möchte FileSystemInfo direkt verwenden. Sprich als Rückgabetyp für Methoden u.ä.

    Ich kann es natürlich nochmal in einer Dummy-Klasse kapseln, weiß aber nicht ob das so die schönste Lösung ist. :-)

    Wie bekomm ich FileSystemInfo direkt in die WCF?

    Mittwoch, 14. Juli 2010 05:38
  • Hallo,

    Du musst ja Deinen Kontrakt sowieso benennen (über Attribute wie [DataContract] etc.). Eine direkte Übergabe wäre eh unsauber, da das .NET Typen sind und somit bzgl. der Interoperabilität sowas schon unschön wäre. Auch sind Klassen wie DirectoryInfo sealed.

    Nein, das Benutzen einer Eigenschaft (wie bei mir DateiInfo) ist schon die sauberste Lösung.

     


    ciao Frank
    Mittwoch, 14. Juli 2010 06:47
  • Ok, vielen Dank!
    Donnerstag, 15. Juli 2010 06:13