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, если это необходимо.

Информация об исключении должна регистрироваться в центральной службе ведения журнала и не передаваться обратно из службы.

Мысли? Комментарии? Идеи? Предложения?

Дополнительные пояснения по моему вопросу

Проблема, с которой я сталкиваюсь с контрактами на сбой, заключается в передаче бизнес-правил.

Например, если кто-то входит в систему, а его учетная запись заблокирована, как мне сообщить об этом? Их логин, очевидно, не удался, но не по причине «Аккаунт заблокирован».

So do I:

A) используйте логическое значение, бросьте Fault с заблокированной учетной записью сообщения

Б) вернуть AuthenticatedDTO с соответствующей информацией


person WebDude    schedule 17.09.2008    source источник


Ответы (3)


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

Вы сериализуете и десериализуете объекты в XML и отправляете их по медленной сети ... накладные расходы от создания исключения ничтожны по сравнению с этим.

Обычно я выбрасываю исключения, поскольку они явно сообщают, что что-то пошло не так, и все инструменты веб-сервисов имеют хорошие способы их обработки.

В вашем примере я бы выбросил исключение UnauthorizedAccessException с сообщением «Учетная запись заблокирована».

Пояснение. Службы .NET wcf по умолчанию переводят исключения в FaultContracts, но вы можете изменить это поведение. MSDN: определение и устранение ошибок в контрактах и ​​услугах

person Paul van Brenk    schedule 17.09.2008
comment
Я не согласен. Поскольку предполагается, что WCF не зависит от языка (по крайней мере, в какой-то форме), вы не можете гарантировать, что передача объекта Exception по сети не вызовет проблем с ошибкой, например, Клиенты Java. Тип объекта FaultContract может гарантировать взаимодействие, поскольку он является частью спецификаций OASIS. - person ZombieSheep; 17.09.2008
comment
.NET переводит исключения в контракты Fault. См. Ссылку, которую я добавил к своему ответу. - person Paul van Brenk; 17.09.2008
comment
У меня всегда было впечатление, что выброс исключения несет ненужные накладные расходы. Судя по вашему сообщению, я, к сожалению, ошибся. Прежде чем я помечу этот пост как ответ, я хочу получить еще несколько мнений. Но, учитывая ваш вклад, кажется, что контракт неисправности - лучший вариант - person WebDude; 17.09.2008
comment
Это отличный ответ. Возврат ошибки сохраняет ясность намерений, а также упрощает стандартизацию методов обработки ошибок в команде разработчиков (просто выбросьте чертово исключение). Если служба генерирует так много ошибок, что производительность является важным фактором, вероятно, существует серьезная проблема с кодом (либо для потока управления используются исключения, что является очень плохой практикой, либо имеется серьезная ошибка). - person DVK; 06.07.2017

Если вы думаете о вызове службы как о вызове любого другого метода, это может помочь увидеть ситуацию в перспективе. Представьте себе, если бы каждый вызванный вами метод возвращал статус, и вы должны были проверить, было ли оно истинным или ложным. Это было бы довольно утомительно.

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();
}

В то же время, возвращая результат, вы возлагаете на клиента больше ответственности. Вы можете хорошо знать, что нужно проверять ошибки в объекте результата, но Джон Доу входит и просто начинает звонить в вашу службу, не обращая внимания на то, что что-то не так, потому что исключение не генерируется. Еще одна сильная сторона исключений в том, что они дают нам хорошую пощечину, когда что-то не так и о чем нужно позаботиться.

person Despertar    schedule 25.09.2012

Я бы серьезно подумал об использовании объектов FaultContract и FaultException, чтобы обойти это. Это позволит вам передать значимые сообщения об ошибках обратно клиенту, но только при возникновении условия сбоя.

К сожалению, сейчас я прохожу курс обучения, поэтому не могу написать полный ответ, но, к счастью, я изучаю управление исключениями в приложениях WCF. Я отправлю ответ сегодня вечером с дополнительной информацией. (Извините, это слабый ответ)

person ZombieSheep    schedule 17.09.2008