Silverlight Communication Exception : WebService Not Found Error
Der wohl gefürchtetste Fehler in Silverlight 3 und personifizierte Feind aller Entwickler ist wohl folgende Fehlermeldung:

„CommunicationException wurde nicht von Benutzercode behandelt.
Der Remoteserver hat einen Fehler zurückgegeben: NotFound.“
Diese häufig in Zusammenhang mit einem Webservice und Klassenserialisierung auftretende Fehlermeldung ist oftmals ein Rätsel, dessen Lösung in den häufigsten Fällen einiges an kostbarer Entwicklerarbeit verschlingt.
Da sie bei meiner Arbeit mit Silverlight ein treuer Begleiter ist, möchte ich sie ihnen gerne persönlich vorstelleun und ihre mir bekannten Ursachen genauer darstellen, um vielleicht die ein oder andere verzweifelte Suche nach der Ursache zu verkürzen und zu vereinfachen.
Auftreten tut dieser Fehler bei der Nutzung eines Silverlight-fähigen WCF Services, der Daten zwischen der Silverlight Anwendung und dem Server hin- und herschickt.
Die Ursache des Fehler ist schnell erklärt: Der Webservice enthält einen Fehler.
Doch damit ist noch niemandem geholfen. Die Suche des Fehlers ist zwar auf das Webservice Projekt eingeschränkt, jedoch ist die Quelle des Fehlers noch weit gestreut.
Da der Fehler meistens durch ein Problem bei der Serialisierung von Klassen auftritt, sollten die grundlegenden Voraussetzungen für die Serialisierung von Klassen überprüft werden, als da wären:
- Jede zu serialisierende Klasse muss im Projekt des Webservices enthalten sein
- Jede zu serialisierende Klasse muss mit dem „<DataContract ()> _“ Attribut über ihrer Definition versehen sein.
- Jede zu serialisierende Eigenschaft der Klasse muss mit dem „<DataMember()> _“ Attribut über ihrer Definition versehen sein
- Jegliche Programmlogik die über die Getter bzw. Setter Logik ( Return propertyvalue bzw. propertyvalue= value) hinausgeht wird von der generierten Proxyklasse vollkommen ignoriert
- Ausnahme davon sind passenderweise Exceptions. Eine im Getter oder Setter einer zu serialisierenden Eigenschaft geworfene Exception führt zum Programmabsturz und muss entfernt werden.
Jegliche Programmlogik muss vom Client abgehandelt werden!
Imports System.Runtime.Serialization
<DataContract()> _
Public Class SerialisierungsKlasseA
Private myFirstProperty As String
<DataMember()> _
Public Property FirstProperty() As String
Get
Return myFirstProperty
End Get
Set(ByVal value As String)
myFirstProperty = value
End Set
End Property
End Class
Weiterhin haben der Silverlight-fähige WCF Service sowie die nach seinem Vorbild generierte Proxy-Klasse einige Sonderwünsche. Welche das sind, sehen Sie hier:
- Es können keine ReadOnly oder WriteOnly Properties serialisiert werden
- Sollten Sie eine Funktion ohne einen gewissen RückgabeTyp (z.B. Public Function Foo()) deklariert haben und den RückgabeTyp ändern wollen (wobei Ihnen Option Strict dabei schon auf die Finger hauen sollte), empfiehlt es sich die ganze Funktion auszukommentieren, den Dienstverweis zu aktualisieren, den Rückgabetyp zu ändern (z.B. Public Function Foo() as String) und den Dienstverweis erneut zu aktualisieren. Andernfalls kann es sein dass es Komplikationen gibt weil die Proxyklasse nicht richtig aktualisiert wird.
- Sollten Sie verzweifelt nach einem Fehler suchen, schauen Sie z.B. durch Einfügen einer neuen Funktion ob die Proxyklasse überhaupt noch aktualisiert wird durch das Aktualisieren des Dienstverweises.
- Sollten der WCF-Service und der Dienstverweis aus unerklärlichen Gründen Streit haben aktualisiert sich die Proxyklasse nicht mehr. Da hilft nur Löschen des Dienstverweises und erneutes Einfügen.
Weiter mögliche Fehlerquellen:
- möglicherweise schachtelt eine serialisierbare Klasse oder Eigenschaft eine andere Klasse. Überprüfen Sie alle noch so weit verschachtelten Unterklassen auf fehlende Attribute für die Serialisierung.
- Findet der Client eine zu serialisierende Klasse aus dem Webservice Projekt nicht, so kann das daran liegen, dass sie weder selbst im Webservice genannt ist, noch als geschachtelte Klasse in einer anderen Klasse im Webservice genannt ist.
o Klasse B hat alle Serialisierungsattribute und wird nicht im Webservice genutzt. Klasse B wird in Klasse A geschachtelt, die vom Webservice genutzt wird.. Klasse B wird vom Client erkannt.
o Klasse C hat alle Serialisierungsattribute und wird im Webservice benutzt: der Client findet sie
o Klasse D hat alle Serialisierungsattribute, wird aber nie im Webservice benutzt und auch von keiner Klasse genutzt die im Webservice benutzt wird. Klasse D hat also gar nichts mit dem Webservice zu tun. Der Client findet sie nicht.
àAlle Klassen müssen in irgendeiner Form im Webservice vorkommen
Einige Tipps und Tricks zum Finden des Fehlers:
- Lassen Sie jeden übergebenen Parameter einmal weg. Haben Sie also folgende Funktion:
<OperationContract()> _
Public Function Foo(ByVal a As KlasseA, ByVal b As KlasseB, _
ByVal c As KlasseC) As String
'implement your logic here
Return "Foo: Work done!"
End Function
lassen sie abwechselnd die Paramater a,b und c weg, um zu schauen in welcher Klasse der Fehler auftritt.
- Kommentieren Sie in der fehlerhaften Klasse nach und nach alles mal aus um zu schauen an welcher Stelle es hakt
Vergessen Sie dabei das Aktualisiern des Dienstverweises nicht!
- Schreiben Sie eine Funktion mit ihrer Klasse als Rückgabetyp in den Webservice und aktualisieren Sie den Dienstverweis. Gibt es einen Fehler, stimmt mit der Klasse etwas nicht.
Mit diesen Informationen haben Sie hoffentlich schon einige Tricks mehr auf Lager wie sie sich mit dieser Excpetion anfreunden können ohne allzuviele graue Haare zu kriegen.
Enjoy!