2010-03-25 10 views
8

Ich habe einen REST-Dienst, der von einem .Net-WCF-Client verwendet wird.Fehlerdetails von WCF-REST abrufen

Wenn ein Fehler auftritt, gibt der REST-Service eine HTTP 400 Bad Request mit dem Antworthauptteil zurück, der die serialisierten JSON-Details enthält.

Wenn ich die Anfrage mit Fiddler, Javascript oder direkt aus C# ausführen, kann ich einfach auf den Antworttext zugreifen, wenn ein Fehler auftritt.

Allerdings verwende ich eine WCF mit 6 recht komplexen Schnittstellen. Die Ausnahme, die von diesem Proxy ausgelöst wird, ist immer ein ProtocolException, ohne nützliche Details.

Gibt es eine Möglichkeit, den Antworttext zu erhalten, wenn dieser Fehler auftritt?


aktualisiert

Mir ist klar, dass eine Last von verschiedenen Möglichkeiten gibt es, dies mit .Net zu tun, und dass es andere Möglichkeiten, um die Fehlerreaktion zu erhalten. Sie sind nützlich zu wissen, aber beantworten Sie diese Frage nicht.

Die REST-Dienste, die wir verwenden, ändern sich und wenn sie das tun, werden die komplexen Schnittstellen aktualisiert. Die Verwendung der mit den neuen Schnittstellen bedeutet, dass wir Ausnahmen zur Kompilierungszeit (statt zur Laufzeit) bekommen und diese viel einfacher pflegen und den Code aktualisieren.

Gibt es eine Möglichkeit, den Antworttext für einen Fehler HTTP-Status bei WCF-Kanälen zu erhalten?

+0

Wenn Sie Ihre Erklärung lesen, klingt es so, als hätten Sie keine Kontrolle über den REST-Dienst selbst. Ist das korrekt? –

+0

Eigentlich tun wir das in diesem Fall, aber es ist schwer zu ändern. Unser Problem ist Komplexität - die WCF ChannelFactory bietet eine wirklich gute Möglichkeit, dies mit Schnittstellen zu verwalten. Die lästige Sache ist, dass es den Antwortkörper wegwirft, wenn der HTTP-Header-Status etwas anderes als 200 ist. Wenn wir einen Fehler vom REST-Dienst erhalten, gibt er einen HTTP 400- oder 500-Status mit Details im Hauptteil zurück. – Keith

Antwort

1

Verwenden Sie keine ChannelFactory :-) Ernsthaft aber. Warum würden Sie eine REST-Schnittstelle erstellen und dann den WCF-Client-Proxy verwenden? Welchen Vorteil bietet der REST-Service? Warum nicht einfach wsHttpBinding verwenden? Mit der HttpClient-Klasse aus dem REST-Starterkit können Sie Standard-HTTP-Anforderungen erstellen und anschließend die Antwort mithilfe von DataContractSerializer deserialisieren.

z.

var httpClient = new HttpClient(); 
var content = httpClient.Get("http://example.org/customer/45").Content; 
var customer = content.ReadAsDataContract<Customer>() 
+2

Ich mag Ihren Simple-Is-Better-Ansatz, aber wir haben eine große Anzahl von Schnittstellen, und fast alle Methoden erfordern komplexe POST-Inhalte. Die Code-Einfachheit der 'ChannelFactory'-Proxy-Implementierung erspart uns eine Menge Code-Komplexität. Ich weiß, dass es auf Ihre Art gemacht werden kann, aber was ich wirklich wissen möchte, ist: Können wir das Fehlerdetail bekommen, wenn wir es auf "ChannelFactory" Weise machen? – Keith

3

Sie könnten versuchen, eine WebProtocolException aus dem Dienst zu werfen. Auf diese Weise sollten die Fehlerdetails im Hauptteil der HTTP-Antwort enthalten sein. Werfen Sie einen Blick auf diesen Artikel:

Effective Error Handling with WCF & REST

+0

Das ist genau das, was der Dienst tut - die Details wie JSON serialisiert im Hauptteil der HTTP-Antwort. Das Problem ist, dass die ChannelFactory eine Ausnahme ohne diese Details für einen anderen HTTP-Header-Status als 200 auslöst. Der Dienst funktioniert, die Client-Implementierung von WCF ist das Problem. – Keith

1

Meine zwei Cent ist, dass WCF gut ist die gleiche Klasse mit vielen verschiedenen Bindungen an auszusetzen. Verwenden Sie bei der Kommunikation mit C# eine SOAP-Bindung, die für Ausnahmeinformationen geeignet ist. Wenn Sie die REST-Stilbindung verwenden müssen, können Sie eine einfache WebRequest verwenden, um den Service aufzurufen, und den JSON-Serializer zum Deserialisieren der Ergebnisse verwenden. Dadurch erhalten Sie auch direkten Zugriff auf den Antwortcode.

4

Sie können die Ausnahme Detail abrufen wie folgt:

   Exception innerException = exception.InnerException; 
       WebException webException = innerException as WebException; 
       HttpWebResponse response = webException.Response as HttpWebResponse; 
       string statusDescription = response.StatusDescription; 
       HttpStatusCode statusCode = response.StatusCode; 
1

Der Ansatz von user653761 beschrieben funktioniert für mich; nach Zugang zum HttpWebResponse Objekt hat, kann ich die DataContractSerializer Klasse wie folgt verwenden:

var serializer = new DataContractSerializer(typeof(MyDataContractType)); 
var deserialized = 
    (serializer.ReadObject(httpWebResponse.GetResponseStream()) as MyDataContractType); 

// ... 

ich das denke, für alles funktionieren würde, die WCF serialisiert werden können, wenn Sie die richtige Serializer verwenden, nicht für die Leistung nicht getestet (noch) .

3

Die InnerException der ProtocolException wird eine WebException sein. Sie können die HttpWebResponse von diesem erhalten und GetResponseStream aufrufen, um den tatsächlichen Antwortkörper zu lesen. (Denken Sie daran, vor dem Lesen den Anfang des Streams zu suchen).

var webException = (WebException) protocolException.InnerException; 
var response = (HttpWebResponse) webException.Response; 
var responseStream = response.GetResponseStream() 
responseStream.Seek(0, SeekOrigin.Begin); 
var reader = new StreamReader(responseStream); 
var responseContent = reader.ReadToEnd();