Почему Silverlight не вызывает AfterReceiveReply для поведения моего пользовательского канала ServiceModel.ClientBase <TChannel>? - PullRequest
8 голосов
/ 05 февраля 2011

У меня есть сервисная ссылка на сторонний API. Я использую собственный класс ChannelFactory для создания каналов ([WCF] типа System.ServiceModel.ClientBase) для этого API.

У меня есть собственный класс поведения (определенный ниже), который я присоединяю к этой конечной точке канала для обработки любых исключений, которые я получаю от API. В моем нормальном .NET-коде это работает нормально. Однако в Silverlight метод AfterReceiveReply вызывается только в том случае, если не было ошибки.

В этом случае вызывающий метод обнаруживает ошибку, когда вы пытаетесь сослаться на результат eventArgs: 'eventArgs.Result' threw an exception of type 'System.Reflection.TargetInvocationException'.

Внутреннее исключение имеет: InnerException = {System.ServiceModel.CommunicationException: The remote server returned an error: NotFound.

И я вижу вышеупомянутую ошибку независимо от РЕАЛЬНОЙ ошибки. В Fiddler я вижу реальную ошибку, возвращающуюся. В обработке каналов есть что-то, что скрывает это. Ниже приведен пример ответа SOAP с реальной ошибкой. (Некоторые значения были удалены.)

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Body>
    <soapenv:Fault>
      <faultcode><!-- REMOVED REAL CODE --></faultcode>
      <faultstring><!-- REMOVED REAL FAULT --></faultstring>
      <detail>
        <!-- REMOVED DETAILS -->
      </detail>
    </soapenv:Fault>
  </soapenv:Body>
</soapenv:Envelope>

Я уверен, что я еще не предоставил достаточно информации об этом, но я не знаю, что все относится к делу. Запросите дополнительную информацию в комментариях.

Как можно отладить это? Тот же код работает в .NET, но Silverlight плохо с этим справляется.

Ниже приведен соответствующий код.

Поведение:

public class ExceptionMapperBehavior : IClientMessageInspector, IEndpointBehavior
{
    public void AfterReceiveReply(ref Message reply, object correlationState)
    {
        //this is only called if there is no fault--not helpful!
        if (reply == null || !reply.IsFault)
            return;

        //todo: make the exception pretty
    }

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {
        //this is always called
        return null;
    }
}

Создание канала :

//...
var constructor = typeof(T).GetConstructor(new Type[] { typeof(Binding), typeof(EndpointAddress) });
var ret = (T)constructor.Invoke(new object[] { binding, endpointAddress });
ret.Endpoint.Behaviors.Add(new CredentialInserterEndpointBehavior(_authToken));
ret.Endpoint.Behaviors.Add(new ExceptionMapperBehavior());
return ret;

1 Ответ

5 голосов
/ 09 февраля 2011

Не знаю, помогает ли это / использует что-то.

По умолчанию silverlight выполняет HTTP-запросы (включая SOAP / REST) ​​через браузер.С этими вызовами все запросы HTTP / HTTPS будут обрабатываться сетевым стеком клиента silverlight.

bool httpResult = WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
bool httpsResult = WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
...