WCF — ошибки/исключения в сравнении с сообщениями
Вопрос
В настоящее время мы обсуждаем, лучше ли выдавать ошибки по каналу WCF, а не передавать сообщение, указывающее состояние, или ответ от службы.
Ошибки имеют встроенную поддержку со стороны WCF, где вы можете использовать встроенные обработчики ошибок и реагировать соответствующим образом.Однако это влечет за собой накладные расходы, поскольку создание исключений в .NET может быть весьма дорогостоящим.
Сообщения могут содержать необходимую информацию для определения того, что произошло с вашим вызовом службы, без дополнительных затрат на создание исключения.Однако для анализа сообщения и определения действий по его содержимому требуется несколько строк повторяющегося кода.
Мы попытались создать универсальный объект сообщения, который можно было бы использовать в наших сервисах, и вот что у нас получилось:
public class ReturnItemDTO<T>
{
[DataMember]
public bool Success { get; set; }
[DataMember]
public string ErrorMessage { get; set; }
[DataMember]
public T Item { get; set; }
}
Если все мои вызовы службы возвращают этот элемент, я могу постоянно проверять свойство «Успех», чтобы определить, все ли прошло хорошо.Затем у меня есть строка сообщения об ошибке в событии, указывающая, что что-то пошло не так, и общий элемент, содержащий Dto, если это необходимо.
Информация об исключении должна быть зарегистрирована в центральной службе журналирования, а не передана обратно из службы.
Мысли?Комментарии?Идеи?Предложения?
Некоторые дополнительные разъяснения по моему вопросу
Проблема, с которой я сталкиваюсь при использовании контрактов с ошибками, заключается в передаче бизнес-правил.
Например, если кто-то входит в систему и его учетная запись заблокирована, как мне сообщить об этом?Их вход в систему явно не удался, но он не удался по причине «Учетная запись заблокирована».
Я тоже:
А) используйте логическое значение, выдайте ошибку с заблокированной учетной записью сообщения
Б) вернуть AuthenticatedDTO с соответствующей информацией
Решение
Однако это влечет за собой накладные расходы, поскольку создание исключений в .NET может быть весьма дорогостоящим.
Вы сериализуете и десериализуете объекты в XML и отправляете их по медленной сети.накладные расходы на создание исключения незначительны по сравнению с этим.
Обычно я придерживаюсь исключений, поскольку они ясно сообщают, что что-то пошло не так, и все наборы инструментов веб-сервисов имеют хороший способ справиться с ними.
В вашем примере я бы выдал исключение UnauthorizedAccessException с сообщением «Учетная запись заблокирована».
Уточнение: Службы .NET wcf по умолчанию преобразуют исключения в FaultContracts, но вы можете изменить это поведение. MSDN:Определение и устранение ошибок в контрактах и службах
Другие советы
Если вы думаете о вызове службы так же, как о вызове любого другого метода, это может помочь взглянуть на ситуацию со стороны.Представьте себе, что каждый метод, который вы вызвали, возвращает статус, и вам нужно было проверить, истинно оно или ложно.Это будет довольно утомительно.
result = CallMethod();
if (!result.Success) handleError();
result = CallAnotherMethod();
if (!result.Success) handleError();
result = NotAgain();
if (!result.Success) handleError();
Это одна из сильных сторон структурированной системы обработки ошибок: вы можете отделить реальную логику от обработки ошибок.Вам не нужно постоянно проверять: вы знаете, что все прошло успешно, если не было создано никаких исключений.
try
{
CallMethod();
CallAnotherMethod();
NotAgain();
}
catch (Exception e)
{
handleError();
}
В то же время, возвращая результат, вы возлагаете на клиента больше ответственности.Возможно, вы знаете, что нужно проверить наличие ошибок в объекте результата, но приходит Джон Доу и просто начинает звонить в вашу службу, не обращая внимания на то, что что-то не так, поскольку исключение не генерируется.Еще одна сильная сторона исключений заключается в том, что они дают нам хорошую пощечину, когда что-то не так и об этом нужно позаботиться.
Я бы серьезно рассмотрел возможность использования объектов FaultContract и FaultException, чтобы обойти эту проблему.Это позволит вам передавать значимые сообщения об ошибках обратно клиенту, но только при возникновении неисправности.
К сожалению, я сейчас прохожу курс обучения, поэтому не могу написать полный ответ, но, по счастливой случайности, я изучаю управление исключениями в приложениях WCF.Я отвечу сегодня вечером с дополнительной информацией.(Извините, это слабый ответ)