Как правильно вернуть DTO без закрытия соединения в WCF - PullRequest
1 голос
/ 05 декабря 2011

Моя служба WCF в C # выглядит следующим образом.

[ServiceContract]
public class MySecretService
{
      [OperationContract]
      [FaultContract(typeof(ErrorMessage))]
      public MyDTO ReturnMyDTOMethod(int id, out string errorMessage)
      {
        try
        {
           //Do stuff...

           //Do some more stuff... pseudocode
          if (biz rule 1 && etc)
          {
            return MyDTO;
          }
          else if (biz rule 2 && etc)
          {
            return null;
          }
          else
          {
            throw new FaultException<ErrorMessage>(blah etc..)
          }
        }
        catch (Exception e) 
        {
            throw new FaultException<ErrorMessage>(blah etc...);
        }
     }//end-method
}//end-class

DTO, возвращаемый методом, выглядит следующим образом:

[DataContract]
public class MyDTO
{
  [DataMember]
  public XElement XmlRep
  {
    get
    {
        //do something within setter, etc...

    //error occurs prior to returnin from setter, where to i catch it?
    return _xmlRep
    }
    set
    {
    _xmlRep = value;

    }

  }
}

Типичные примеры, которые я обнаружил, показывают бросаниеFaultException изнутри метода;Но в моем случае мой метод не является ошибкой;Ошибка возникает в тот момент, когда объект возвращается клиенту / потребителю;т.е. когда сериализуется DataMember / Property XmlRep;

Так что я не могу поместить исключение FaultException в свой метод;Но я все еще хочу не получить «Базовое соединение было закрыто: соединение было неожиданно закрыто».и выдать правильную ошибку, которая возникает в геттере.

Я не пытался поместить try / catch в геттер MyDTO, НИКТО Я ХОЧУ, ПОТОМУ ЧТО я хочу, чтобы мой DTO был настолько простым, насколько это возможно, и знаю,ничего о FaultExceptions и вещах WCF.Любые другие идеи?

РЕДАКТИРОВАТЬ: просто чтобы прояснить это, я знаю, что ошибка происходит в Getter MyDto DataContract;Но где еще я мог бы выбросить FaultException, учитывая, что внутри Getter мне кажется изворотливым местом для его выброса?

EDIT # 2: я реализовал обработчик ошибок для всех целей на стороне службы, как это было предложеноТим ниже (используя IErrorHandler);это не работает в моем конкретном случае.Я думаю, что это потому, что ошибка не возникает в OperationContract ReturnMyDTOMethod (), а вместо этого в MyDto при сериализации;Другими словами, кажется, что лошадь заперта (метод успешно завершен), и IErrorHandler уже может оказаться полезным - в частности, ProvideFault () не запускается, но HandleError () запускается.Следовательно, я по-прежнему получаю сообщение о нарушении канала, которое требует от меня возврата на чертежную доску - т.е. убедитесь, что MyDto не делает ничего необычного, например, генерирует ошибку!

1 Ответ

1 голос
/ 05 декабря 2011

Я вижу два варианта:

  1. Похоже, что-то в вашем DataContract не может быть сериализовано.Я бы взглянул туда и определил, что это такое, почему он не сериализуется, и если есть какой-то другой способ, вы можете решить проблему в установщике.Вы можете сделать это без блока try-catch, в зависимости от того, что это такое.Не видя код или не зная, что является настоящей ошибкой, трудно дать что-то более конкретное.

  2. Реализация IErrorHandler Интерфейс в вашем сервисе.Это будет перехватывать любые необработанные исключения, и вы будете обрабатывать их в соответствии с вашими потребностями в обслуживании (например, сериализация сообщения об ошибке через FaultException).В Интернете есть множество примеров того, как это сделать - просто google IErrorHandler и WCF.

Мое личное предпочтение будет состоять в том, чтобы попробовать подход № 1 - возможно, есть определенная причина (илигруппа причин) ваш DTO не сериализуется, и я чувствую, что лучше решать эти проблемы в коде, а не полагаться на какой-то глобальный обработчик ошибок (что и есть # 2).

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

Добавлено после 2-го редактирования в вопросе

Документация для IErrorHandler гласит:

"Исключения могут возникать после вызова всех реализаций ProvideFault и передачи ответного сообщения в канал. Если возникает исключение канала (например, , трудности с сериализацией сообщения ) Объекты IErrorHandler не уведомляютсяВ этом случае вы должны убедиться, что ваша среда разработки перехватывает и отображает такие исключения для вас или использует трассировку для обнаружения проблемы ».(Акцент мой)

Знаете ли вы, что вызывает сбой сериализации?Если вы это сделаете, я думаю, вы могли бы решить это в самом коде.Вы включили трассировку?Мне кажется, вам нужно определить, почему ваш DTO не может сериализоваться.

...