//контракт [ServiceContract] public interface IDataService { [OperationContract] void TestError(); } //реализация public void TestError() { throw new Exception("Error!"); }
В если реализовать сервис именно так, то на клиент придет исключение, которое не дает никаких сведений о случившемся:
Можно, конечно, как написано в ошибке, включить IncludeExceptionDetailInFaults, как написано в сообщении об ошибке. Но это свойство не рекомендуется использовать кроме как для отладки, так как при этом любой клиент в случае ошибки получить все данные о стеке вызовов и структуре вашего сервиса, что очень нехорошо с точки зрения безопасности.
Но, помимо варианта для отладки и архитектурно не самого лучшего варианта с дополнительным полем в результате вызова, есть и третий вариант - более удобный и более правильный.
Это использования FaultContract и FaultException. Давайте сделаем контракт и реализацию нашего сервиса с использованием этих возможностей WCF.
[ServiceContract] //контракт public interface IDataService { [OperationContract] [FaultContract(typeof(ServiceError))] void TestError(); } [DataContract] public class ServiceError { [DataMember] public int ErrorCode { get; set; } [DataMember] public string Message { get; set; } } //реализация public void TestError() { ServiceError srvError = new ServiceError(); srvError.ErrorCode = 123; srvError.Message = "Error!"; throw new FaultException<ServiceError>(srvError); }
Теперь, если ловить на клиенте не просто исключение а FaultException<>, то можно получить все те сведения, которые мы передали в сервисе.
using (TestService.TestServiceClient client = new TestService.TestServiceClient()) { try { client.TestError(); } catch (FaultException<TestService.ServiceError> ex) { //поля вашего класса, объявленного как FaultContract, будут находится в свойстве исключения Datail //в данном случае появится сообщение "123Error!"; MessageBox.Show(ex.Detail.ErrorCode.ToString()+ex.Detail.Message); } }
В принципе, все должно работать нормально, за одним исключением - при отладке в Visual Studio у вас может появляться странная ошибка System.ServiceModel.FaultException`1 was unhandled by user code на то месте в сервисе, где вы выбрасываете исключение:
Одни советы в интернете говорят, что чтобы починить это надо полностью отключить Exception assistant (после чего, вообще никакие ошибки не будет ловится студией), другие что в настройках этого самого ассистента вообще отключить все CLR Exceptions (что, в контексте разработки на .Net равнозначно предыдущему варианту). На самом деле, достаточно отключить одно это исключение и все будет работать. Идем в Debug -> Exception, открываем категорию Common Language Runtime Exceptions, затем System.ServiceModel и убираем галочку напротив System.ServiceModel.FaultException`1.
И все будет работать нормально.
Комментариев нет:
Отправить комментарий