FaultException. Деталь возвращается пустой - PullRequest
9 голосов
/ 08 сентября 2010

Я пытаюсь поймать данное исключение FaultException на клиенте WCF. Мне в основном нужно извлечь внутреннее описание из класса ошибок, чтобы затем я мог упаковать его в другое исключение, чтобы верхние уровни делали что угодно.

Я сделал это успешно несколько раз, но на этот раз он отличается тем, что ошибка объявляется как массив, как вы можете видеть из атрибута ссылки на службу, объявленного поверх метода, который выдает исключение:

[System.ServiceModel.FaultContractAttribute(typeof(FaultClass[]), Action = "http://whatever/", Name = "whateverBusinessFault")] 

Это мой код:

try
{
  // call service here
}
catch (FaultException<FaultClass[]> ex)
{
  if (ex.Detail != null && ex.Detail.Length > 0)
  {
    throw new CustomException(ex.Detail[0].description);
  }
  else
  {
    throw;
  }
}

Проблема в Сведения (это массив) всегда возвращаются пустыми в коде, даже если я вижу данные (поле описания и т. Д.) В ответе SOAP от трассировки WCF.

Так что мне нужно определенно возвращаться, но по какой-то причине оно не десериализовано или я не могу добраться до него из кода.

Любая помощь приветствуется!

UPDATE

Попытка с предложением @Darin, но не повезло, строка, которую я извлекаю из XmlReader: "/ r / n":

var sb = new StringBuilder();

using (XmlReader reader = fault.GetReaderAtDetailContents())
{
  while (reader.Read())
     sb.AppendLine(reader.ReadOuterXml()); 
}

var detail = sb.ToString();

Похоже, что подробный раздел вообще не подходит!

Ответы [ 5 ]

8 голосов
/ 15 сентября 2016

Я нашел решение на форуме UPS:

https://developerkitcommunity.ups.com/index.php/Special:AWCforum/st/id371

"Проблема заключалась в том, что Visual Studio не совсем правильно отобразила объекты ErrorDetail. Узел ErrorDetail называется«ErrorDetail», но сгенерированный для него тип - «ErrorDetailType». Я отредактировал класс reference.cs, сгенерированный для каждого используемого мной сервиса, и добавил TypeName: «

5 голосов
/ 22 сентября 2010

Трудно сказать, где проблема, но я подозреваю, что курящий пистолет - это веб-сервис этой оси, который не генерирует стандартное сообщение.Один из способов обойти это - самостоятельно проанализировать XML:

try
{
    proxy.CallSomeMethod();
}
catch (FaultException ex)
{
    var fault = ex.CreateMessageFault();
    using (XmlReader reader = fault.GetReaderAtDetailContents())
    {
        // TODO: read the XML fault and extract the necessary information.
    }
}
2 голосов
/ 24 августа 2016

Мне потребовалось много времени, чтобы понять, как получить сообщение с полной информацией из FaultException в виде строки.В конце концов я понял это и написал этот метод расширения:

public static string GetDetail(this FaultException faultException)
{
    if (faultException == null)
        throw new ArgumentNullException(nameof(faultException));

    MessageFault messageFault = faultException.CreateMessageFault();
    if (messageFault.HasDetail) {
        using (XmlDictionaryReader reader = messageFault.GetReaderAtDetailContents()) {
            return reader.ReadContentAsString();
        }
    }
    return null;
}

Первоначально я использовал reader.Value, но это появилось только в возвращении первой строки многострочного подробного сообщения.reader.ReadContentAsString(), кажется, получил все, включая новые строки, что я и хотел.

2 голосов
/ 17 сентября 2010

Я придумал самый простой тестовый пример, какой только мог. Я надеюсь, что это поможет вам. Сторона сервера:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    [FaultContract(typeof(FaultClass[]))]
    string Crash();
}

public class Service1 : IService1
{
    public string Crash()
    {
        var exception = new FaultException<FaultClass[]>(new FaultClass[] { new FaultClass { Data = "TEST" } }, new FaultReason("Boom"));

        throw exception;
    }
}

[DataContract]
public class FaultClass
{
    [DataMember]
    public string Data { get; set; }
}

Клиентская сторона:

try
{
    using (var client = new Service1Client())
    {
        client.Crash();
    }
}
catch(FaultException<FaultClass[]> e)
{
    //Break here
}
1 голос
/ 25 апреля 2011

У меня была похожая ситуация при попытке передать данные с ошибками (в частности, трассировка стека). См. этот вопрос . В итоге я решил ее, создав собственную сериализуемую трассировку стека и включив ее в производный класс FaultException.

...