дуплексная связь и передача исключений

#wcf #web-services

#wcf #веб-сервисы

Вопрос:

Я создал веб-службу WCF, которая подключается к службе XMPP с Jabber.net . Идея заключается в том, что служба будет выступать в качестве прокси-сервера для клиентов Silverlight для обмена сообщениями.

IMessagingClient.cs:

 [OperationContract(IsOneWay = true, AsyncPattern = true)]
IAsyncResult BeginError(Exception ex, AsyncCallback callback, object state);
void EndError(IAsyncResult result);
  

В моем серверном коде я подключил обработчик ошибок к JabberClient

 private void xmppClient_OnError(object sender, Exception ex)
{
    lock (xmppClient)
    {
        Debug.WriteLine("xmppClient_OnError: {0}", ex);
        // Let the client know there has been a problem
        client.BeginError(ex, OnSendErrorCompleted, client);
    }
}
  

Однако, когда возникает исключение SocketException, оно не передает исключение.

System.ServiceModel.CommunicationException: There was an error while trying to serialize parameter http://tempuri.org/:ex. The InnerException message was 'Type 'bedrock.net.AsyncSocketConnectionException' with data contract name 'AsyncSocketConnectionException:http://schemas.datacontract.org/2004/07/bedrock.net' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.'. Please see InnerException for more details.

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

Но каков наилучший способ сделать это? Должен ли я вообще отправлять такого рода исключения с сервера на клиент? Я видел несколько примеров использования `FaultContract’, но не так, как (или как это должно) применяться к pushing.

Ответ №1:

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

Вы не должны отправлять клиенту детали исключения такого типа, поскольку это может представлять угрозу безопасности или не имеет отношения к клиенту, вы должны стремиться абстрагировать потребителя от деталей исключения. Вы можете зарегистрировать исключение, а затем вызвать ошибку, возможно, что-то вроде new FaultException , сопоставив фактическое исключение с FaultReason или FaultCode, которые вы можете использовать позже для сопоставления исключения, возникшего в службе.

Комментарии:

1. Все это звучит разумно. Я просто не совсем понимаю, как вы отправляете ошибки через механизм push, который используется здесь.

2. @Firedragon и я не могу сейчас редактировать вышесказанное: < Проблема, с которой вы столкнулись, заключается в том, что контракты сбоев могут быть указаны только в атрибуте operation contract, который в приведенном выше примере будет доступен для клиента. BeginError(…) для отправки ошибки обратно на сервер, если во время обработки обработки BeginError произошла ошибка.<br/> Моим предложением было бы добавить тип контракта ошибки в определение BeginError (например, определить класс контракта ошибки и передать его обратно при обратном вызове. Это решит проблему сериализации.