2010-11-24 7 views
2

Ich habe C# Code, der einen POST zu einem OData Webservice durchführt, der einen Datensatz führt, der in eine Datenbank eingefügt wird. Wenn eine Ausnahme vorliegt, z. B. eine primäre Schlüsselverletzung, möchte ich die Fehlermeldung erfassen und protokollieren. Die Nachricht ist jedoch in XML enthalten. Hier ist meine Exception-Handler:Wie man internalexception von der WebException Antwort analysiert

catch (WebException ex) 
{ 
    if (ex.Status == WebExceptionStatus.ProtocolError) 
    { 
     string responseText = string.Empty; 

     using (Stream responseStream = ((HttpWebResponse)ex.Response).GetResponseStream()) 
     { 
      using (StreamReader streamReader = new StreamReader(responseStream)) 
      { 
       responseText = streamReader.ReadToEnd(); 
      } 
     } 
     Debug.WriteLine(responseText); 
     return responseText; 
    } 
    else 
    { 
     Debug.WriteLine(ex.Message.ToString()); 
     return ex.Message.ToString(); 
    } 
} 

Hier ist, was ich in response erhalten:

<?xml version="1.0" encoding="utf-8" standalone="yes"?> 
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata"> 
    <code></code> 
    <message xml:lang="en-US">An error occurred while processing this request.</message> 
    <innererror> 
    <message>An error occurred while updating the entries. See the inner exception for details.</message> 
    <type>System.Data.UpdateException</type> 
    <stacktrace> at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)&#xD; 
    at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)&#xD; 
    at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)&#xD; 
    at System.Data.Services.Providers.ObjectContextServiceProvider.SaveChanges()&#xD; 
    at System.Data.Services.DataService 1.HandleNonBatchRequest(RequestDescription description)&#xD; 
    at System.Data.Services.DataService 1.HandleRequest()</stacktrace> 
    <internalexception> 
     <message>Violation of PRIMARY KEY constraint 'PK_Customer_CustomerId'. Cannot insert duplicate key in object 'VertexBilling.Customer'.&#xD; 
The statement has been terminated.</message> 
     <type>System.Data.SqlClient.SqlException</type> 
     <stacktrace> at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)&#xD; 
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)&#xD; 
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()&#xD; 
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)&#xD; 
    at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()&#xD; 
    at System.Data.SqlClient.SqlDataReader.get_MetaData()&#xD; 
    at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)&#xD; 
    at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)&#xD; 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)&#xD; 
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)&#xD; 
    at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)&#xD; 
    at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)&#xD; 
    at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)&#xD; 
    at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary 2 identifierValues, List 1 generatedValues)&#xD; 
    at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)</stacktrace> 
    </internalexception> 
    </innererror> 
</error> 

Ich brauche die Nachricht aus dem internalexception aus dem innererror zu bekommen. Was ist der einfachste Weg das zu tun?

+0

BTW, ex.Message ist bereits eine Zeichenfolge. Sie müssen '.ToString()' –

Antwort

0

Der einfachste Weg ist wahrscheinlich einen regulären Ausdruck wie die die Zeichenfolge zwischen "<message>" und "</message>" zu extrahieren folgenden zu verwenden:

<message>(.+)</message> 

Das ist nicht sehr robust, und es ist nicht im Sinne von XML, aber Es sollte funktionieren, es sei denn, die XML variiert stark. Und wenn Sie XML-Tools nicht bereits in Ihrer App verwenden, möchten Sie diese nicht unbedingt nur zum Extrahieren dieser Zeichenfolge auffrischen.

+0

nicht verwenden Das Problem ist, dass es eine innerhalb der innerhalb der , die ich will, und eine innerhalb der die ich nicht habe. –

+0

@Mark: guter Punkt. Aus diesem Grund sollten Sie regexps nicht zur Verarbeitung von XML verwenden, es sei denn, es handelt sich um einen * sehr * einfachen Fall. :-) Versuchen Sie die Antwort des anderen Mannes, außer ändern Sie das Anfangs "//" zu "/" für bessere Leistungsfähigkeit. – LarsH

1

Sie XML-Toolkit verwenden sollten, haben Sie es bereits zu Ihrer Verfügung in .net und es beseitigt Probleme Mehrdeutigkeit, wenn xml als Text (es ist ein Alptraum, haben Sie zwei Nachrichten-Knoten in der obigen xml passieren warten) Behandlung

  1. Last Zeichenfolge XmlDocument
  2. Verwendung // Fehler/innerError/internalexception/message XPath extrahieren die benötigten Knoten

alternativ können Sie ein kleines Stück Code bauen, würde extrahieren/deserialisieren die innerexception in ein Exceptio n Instanz und kann sie für andere Aufrufe wiederverwenden.

Wenn Sie nicht wissen, wie das geht, Heuler, werde ich etwas aufschlagen.

+0

Ich habe versucht, mit "docNav = new XPathDocument (responseText);" aber ich bekomme eine "Illegale Zeichen im Pfad" ArgumentException. Ich habe versucht, die einfachen Anführungszeichen zuerst durch String.Empty zu ersetzen, aber das hat nicht geholfen. Wenn Sie etwas rauh knallen könnten, um dieses Durcheinander in eine .Net-Ausnahme umzuwandeln, die ich werfen könnte, wäre das sehr hilfreich. –

+0

eigentlich, bevor Sie das getan, welche lib haben Sie verwendet, um odata zuzugreifen? Hast du solche von http://odata.codeplex.com/ benutzt? – mmix

+0

Ich verwende nur, was in VS 2010 /. Net 4. –