воскресенье, 7 декабря 2014 г.

Обработка исключений при работе с WCF-сервисами

Наверняка вы сталкивались с ситуацией, когда в случае ошибки в WCF-сервисе нужно передать клиенту какие-либо данные либо, например, подробное описание что случилось. Очень часто встречаются реализации WCF- сервисов, использующие возвращаемые клиенту объекты с дополнительными, используемыми только в случае ошибки, полями, даже если реализация метода не требует возврата какого-либо результата клиенту. Так делают потому, что если просто выбросить исключение, то клиент не получит практически никакой информации о том, что случилось. Представьте, что у нас есть WCF сервис вот с таким простым контрактом и реализацией.


  
    //контракт
    [ServiceContract]
    public interface IDataService
    {        
        [OperationContract]        
        void TestError();
    }

    //реализация
    public void TestError()
    {
       throw new Exception("Error!");
    }


В если реализовать сервис именно так, то на клиент придет исключение, которое не дает никаких сведений о случившемся:

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