How to parse internalexception from WebException Response
I have C# code that does a POST to an OData web service, which results in a record being inserted into a database. If there is an exception, such as a primary key violation, I want to capture and log the error message. However, the message is contained within XML. Here is my exception handler:
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();
}
}
Here is what I get in responseText:
<?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)
at System.Data.EntityClient.EntityAdapter.Update(IEntityStateManager entityCache)
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Services.Providers.ObjectContextServiceProvider.SaveChanges()
at System.Data.Services.DataService 1.HandleNonBatchRequest(RequestDescription description)
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'.
The statement has been terminated.</message>
<type>System.Data.SqlClient.SqlException</type>
<stacktrace> at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)&开发者_JS百科#xD;
at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Mapping.Update.Internal.DynamicUpdateCommand.Execute(UpdateTranslator translator, EntityConnection connection, Dictionary 2 identifierValues, List 1 generatedValues)
at System.Data.Mapping.Update.Internal.UpdateTranslator.Update(IEntityStateManager stateManager, IEntityAdapter adapter)</stacktrace>
</internalexception>
</innererror>
</error>
I need to get the message out of the internalexception out of the innererror. What's the easiest way to do that?
You should use XML toolkit, you already have it at your disposal in .net and it removes ambiguity problems when treating xml as text (its a nightmare waiting to happen, in the above xml you have two message nodes)
- Load string to XmlDocument
- use //error/innerError/internalexception/message xpath to extract the needed node
alternatively you can build a small piece of code which would extract/deserialize the innerException into an Exception instance and can reuse it for other calls.
If you don't know how to do this, howler, I'll bang something up.
The easiest way is probably to use a regular expression like the following to extract the string between "<message>"
and "</message>"
:
<message>(.+)</message>
That's not extremely robust, and it's not in the spirit of XML, but it should work unless the XML varies much. And if you're not already using XML tools in your app, you don't necessarily want to rev them up just to extract this string.
精彩评论