2011-01-11 3 views
3

Ich habe gerade etwas Besonderes bemerkt. Ich habe einen internen Bestandsservice, der über basicHttpBinding veröffentlicht wird, und eine customBinding (http + binary), für die Metadaten aktiviert sind. Ich habe auch einen mex Endpunkt für http enthalten. Wir verwenden Visual Studio 2008 & VB.NETDie Verwendung eines benutzerdefinierten FaultContract-Objekts, das System.Exception enthält, führt dazu, dass 'Service-Referenz hinzufügen' fehlschlägt.

Erst vor kurzem haben wir festgestellt, dass wir in unseren anderen Projekten keine Service-Referenz zu diesem Service hinzufügen konnten. Alles, was es erzeugen würde, war die erste benutzerdefinierte Ausnahme, die wir durch einen FaultContract einschlossen (tatsächlich gab es nur einen Typ). Wenn ich eine einfache Webreferenz hinzufügen würde, würde es auch richtig funktionieren. Auch die WcfClient.exe hatte keine Probleme beim Laden der Dienste. Nur VS.NET Add Service Reference würde nicht funktionieren.

Im Service erbt diese Ausnahme von Exception und ist als serialisierbar gekennzeichnet. Das ist alles, was du tun sollst, nein?

Wie auch immer, das hat mich verblüfft. Wenn ich den FaultContract für diese benutzerdefinierte Ausnahme entferne, funktioniert alles einwandfrei. Ich kann eine Servicereferenz hinzufügen, kein Problem. Aber gibt es eine Möglichkeit, meine benutzerdefinierten Ausnahmen noch zu haben? Ist das ein bekanntes Problem?

+0

Sie erkennen natürlich, dass die Ausnahme für jede andere Plattform außer .NET sinnlos ist? –

+0

Nein, aber mein Eindruck davon war, dass die Ausnahme von Exception für das WCF-Framework benötigt wurde. Es ist auch etwas, von dem ich annahm, dass es richtig war, weil es immer in der Lage war, die korrekte Proxy-Klasse für die benutzerdefinierte Exception zu erstellen, die von Exception geerbt wurde. – SpoBo

Antwort

8

Ich lief heute selbst in diese. Die Lösung bestand darin, ein Objekt zu verwenden, das in FaultContract nicht von Exception erbte. Wenn Sie sich die MSDN-Dokumente für FaultException und FaultContract ansehen, werden Sie sehen, dass die offiziellen Beispiele einfache Klassen (mit DataContact-Attributen) anstelle von Klassen verwenden, die die Ausnahme für FaultException.Detail erweitern. Ich bin mir nicht sicher, warum Exception die Add Service Reference fehlschlägt, aber ich vermute, dass es mit der Serialisierung oder dem Abrufen der Typinformationen für benutzerdefinierte Ausnahmen zu tun hat. Ich habe vorher und nachher Beispielimplementierungen eingefügt, um den Arbeitsansatz zu demonstrieren.

Vor (nicht funktioniert):

[ServiceContract] 
public interface IMyService 
{ 
    [OperationContract] 
    [FaultContract(typeof(MyException))] 
    MyResults MyServiceOperation(string myParameter); 
} 

[Serializable] 
public class MyException : Exception 
{ 
    public string CustomData { get; set; } 
} 

[ErrorHandlerBehavior(typeof(MyErrorHandler))] 
public class MyService : IMyService 
{ 
    public MyResults MyServiceOperation(string myParameter) 
    { 
     ... 
     throw new MyModelException { CustomData = "42" }; 
     ... 
    } 
} 

public class MyErrorHandler : IErrorHandler 
{ 
    public bool HandleError(Exception error) { return false; } 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     try { throw error; } 
     catch (MyModelException ex) 
     { 
      var faultEx = new FaultException<MyException>(new MyException { CustomData = ex.CustomData }); 
      fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action); 
     } 
     catch { /* Supress all others */ } 
    } 
} 

Nach (arbeitete):

[ServiceContract] 
public interface IMyService 
{ 
    [OperationContract] 
    [FaultContract(typeof(MyFault))] 
    MyResults MyServiceOperation(string myParameter); 
} 

[DataContract] 
public class MyFault 
{ 
    [DataMember] 
    public string CustomData { get; set; } 
} 

[ErrorHandlerBehavior(typeof(MyErrorHandler))] 
public class MyService : IMyService 
{ 
    public MyResults MyServiceOperation(string myParameter) 
    { 
     ... 
     throw new MyModelException { CustomData = "42" }; 
     ... 
    } 
} 

public class MyErrorHandler : IErrorHandler 
{ 
    public bool HandleError(Exception error) { return false; } 

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault) 
    { 
     try { throw error; } 
     catch (MyModelException ex) 
     { 
      var faultEx = new FaultException<MyFault>(new MyFault { CustomData = ex.CustomData }); 
      fault = Message.CreateMessage(version, faultEx.CreateMessageFault(), faultEx.Action); 
     } 
     catch { /* Supress all others */ } 
    } 
} 

Quelle: Max Strini für die Nutzung seines Codes und helfen, die Lösung bei der Suche nach zu diesem Problem.

+0

thx :) Ich nahm immer an, dass WCF ein Objekt mit etwas, das von Ausnahme ist oder erbt, benötigt, um eine ordnungsgemäße FaultException zu erstellen. – SpoBo

+0

Das hat super funktioniert. Ich musste einen Dienst von einer WSDL mit Svcutil generieren und ich konnte nicht herausfinden, was mit den Ausnahmen zu tun ist. Diese Antwort hat mein Problem gelöst, danke dafür! – Zoidberg

0

Ich habe auch dieses Problem getroffen. Am Ende habe ich die Datei svcutil.exe verwendet, um den Proxy zu generieren, der anscheinend nicht das gleiche Problem hat.

+0

Die einzige echte Lösung besteht darin, keine von der Exception-Klasse abgeleiteten Modelle (oder wahrscheinlich ein beliebiges .NET Core-Klassenmodell) als DataMember zu verwenden. Beschränken Sie sich einfach auf POCOs und Ihr WCF-Vertrag wird korrekt, sauberer und kompatibler mit anderen Technologien sein. (Java, PHP, etc) – SpoBo

0

Ich hatte das gleiche Problem und löste es durch Generieren des Proxy mit SVCUTIL.exe. Ich hatte die benutzerdefinierte Fehlerkonfiguration genau so, wie MSDN es empfiehlt, aber "Dienstreferenz hinzufügen" enthielt den Fehlervertrag im Proxy nicht. Dann habe ich die SvcUtil und es funktionierte wie ein Zauber :)

+1

Es ist am besten, das Problem zu lösen, so dass Sie nur den Code in Visual Studio generieren können. Wos weiß, welche anderen Tools das gleiche Verhalten zeigen. + Jedes Mal, wenn jemand versucht, Ihren Dienst hinzuzufügen, wird dies zu einem Problem. Ich würde anfangen, Dateien nacheinander auszuschließen, neu zu kompilieren und zu versuchen, den Dienstverweis erneut hinzuzufügen. Dies gilt nur, wenn Sie den Dienst selbst schreiben. – SpoBo

1

ich den folgenden Artikel gefunden, wie man einen Fehler Vertrag erstellen mit von System.Exception geerbt widersprochen: http://blog.clauskonrad.net/2008/06/wcf-and-custom-exceptions.html

aber es hat nicht für mich arbeiten . Ich vermute, der Grund, warum es für mich nicht funktionierte, ist, dass ich eine BasicHttp-Bindung und keine .NET-.NET-Bindung verwende.

+0

Also empfehlen Sie eine Lösung, die nicht funktioniert hat ?! –

+0

Das folgende aus dem Artikel war der Schlüssel für mich: "Stellen Sie einen geschützten Konstruktor zur Verfügung, der den Serialisierungsprozess erlaubt, indem Sie SerializationInfo und StreamingContext als Argumente verwenden". Wenn ich diesen Konstruktor für meine benutzerdefinierte Ausnahme bereitgestellt habe, könnte ich die Vererbung System.Exception beibehalten. –

Verwandte Themen