Извлечение деталей из ответа WCF FaultException
Я успешно работаю со сторонним мыльным сервисом. Я добавил сервисную ссылку на мыльный веб-сервис, который автоматически генерирует классы.
При возникновении ошибки возвращается мыльный ответ, подобный следующему:
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Client</faultcode>
<faultstring xsi:type="xsd:string">Error while reading parameters of method 'Demo'</faultstring>
<detail xsi:type="xsd:string">Invalid login or password. Connection denied.</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Я могу поймать ошибку, но не извлечь детали. Я пробовал следующий код:
catch (FaultException ex)
{
MessageFault msgFault = ex.CreateMessageFault();
var elm = msgFault.GetDetail<string>();
//throw Detail
}
Однако это ошибка со следующим узлом детализации не является объектом:
Expecting element 'string' from namespace 'http://schemas.datacontract.org/2004/07/MyDemoNamespace'.. Encountered 'Text' with name '', namespace ''.
Это сторонний API, поэтому я не могу изменить ответ.
5 ответов
Предполагается, что подробный узел сообщения об ошибке содержит XML. GetDetail десериализует этот XML в заданный объект.
Поскольку содержимое не является XML, можно было использовать этот метод.
Однако вы можете получить доступ к XML и прочитать значение innerXml:
MessageFault msgFault = ex.CreateMessageFault();
var msg = msgFault.GetReaderAtDetailContents().Value;
Это подошло сработало.
Вот несколько методов, которые я нашел для извлечения подробной информации об исключении из FaultExceptions
Получение строкового содержимого одного элемента
catch (FaultException e)
{
var errorElement = XElement.Parse(e.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
var errorDictionary = errorElement.Elements().ToDictionary(key => key.Name.LocalName, val => val.Value);
var errorMessage = errorDictionary?["ErrorMessage"];
}
Пример вывода:
Организации не существует.
Получите строковое содержимое всех деталей как одну строку
catch (FaultException e)
{
var errorElement = XElement.Parse(e.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
var errorDictionary = errorElement.Elements().ToDictionary(key => key.Name.LocalName, val => val.Value);
var errorDetails = string.Join(";", errorDictionary);
}
Пример вывода:
[ErrorMessage, Организация не существует.];[EventCode, 3459046134826139648];[Параметры, ]
Получите строковое содержимое объекта Everything в виде строки XML
var errorElement = XElement.Parse(e.CreateMessageFault().GetReaderAtDetailContents().ReadOuterXml());
var xmlDetail = (string)errorElement;
Пример вывода:
<FaultData xmlns="http://schemas.datacontract.org/2004/07/Xata.Ignition.Common.Contract" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <ErrorMessage>Organization does not exist.</ErrorMessage> <EventCode>3459046134826139648</EventCode> <Parameters i:nil="true" xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"></Parameters> </FaultData>
Следующее должно дать вам значение элемента detail FaultException.
var faultMessage = faultException.CreateMessageFault();
if(faultMessage.HasDetail){
Console.Write(faultMessage.GetDetail<XElement>().Value);
}
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
if (reply.IsFault)
{
// Create a copy of the original reply to allow default WCF processing
MessageBuffer buffer = reply.CreateBufferedCopy(Int32.MaxValue);
Message copy = buffer.CreateMessage(); // Create a copy to work with
reply = buffer.CreateMessage(); // Restore the original message
MessageFault faultex = MessageFault.CreateFault(copy, Int32.MaxValue); //Get Fault from Message
FaultCode codigo = faultex.Code;
//if (faultex.HasDetail)... //More details
buffer.Close();
Ты можешь поймать FaultException<TDetail>
, который дает вам подробную информацию бесплатно.
catch (FaultException<string> ex)
{
string yourDetail = ex.Detail;
}