为什么Silverlight不会为我的自定义ServiceModel.ClientBase <TChannel>频道的行为调用AfterReceiveReply?

End*_*ssa 8 .net silverlight wcf

我有对第三方API的服务引用.我使用自定义ChannelFactory类来为此API构建通道(System.ServiceModel.ClientBase类型的[WCF]).

我有一个自定义行为类(在下面定义),我附加到此通道端点,以处理从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.

无论REAL错误如何,我都会看到上述错误.在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>
Run Code Online (Sandbox Code Playgroud)

我确信我还没有提供足够的相关信息,但我不知道所有相关内容.在评论中询问更多信息.

我该如何调试呢?相同的代码适用于.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

频道创作:

//...
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;
Run Code Online (Sandbox Code Playgroud)

小智 5

不知道这有助于/使用某些东西.

默认情况下,silverlight通过浏览器执行HTTP请求(包括SOAP/REST).通过这些调用,所有HTTP/HTTPS请求都将由silverlight-client网络堆栈处理.

bool httpResult = WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
bool httpsResult = WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
Run Code Online (Sandbox Code Playgroud)