Why does Silverlight not call AfterReceiveReply for my custom ServiceModel.ClientBase<TChannel> channel's behavior?
I have a service reference to a third-party API. I use a custom ChannelFactory class to build channels ([WCF] of type System.ServiceModel.ClientBase) to this API.
I have a custom behavior class (defined below) that I attach to this channel endpoint in order to handle any exceptions that I get back from the API. In my normal .NET code, this works fine. In Silverlight, however, the AfterReceiveReply method is only called if there was NO error.
In this case, the calling method encounters an error when you try to reference the result of the eventArgs: 'eventArgs.Result' threw an exception of type 'System.Reflection.TargetInvocationException'
.
开发者_运维百科The inner exception has: InnerException = {System.ServiceModel.CommunicationException: The remote server returned an error: NotFound.
And I see the above error regardless of the REAL error. In Fiddler, I can see the real error coming back. There is just something about the channel processing that hides it. Below is an example of the SOAP response that has the real error. (Some values were removed.)
<?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>
I'm sure that I haven't provided enough information about this yet, but I don't know what all is relevant. Ask for more info in the comments.
How can I go about debugging this? The same code works in .NET, but Silverlight doesn't handle it well.
Some relevant code is below.
Behavior:
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;
}
}
Channel Creation:
//...
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;
Don't know if this helps/uses something.
By default silverlight performs HTTP-Requests (include SOAP/REST) through the browser. With these calls all HTTP/HTTPS requests will handled by silverlight-client network stack.
bool httpResult = WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
bool httpsResult = WebRequest.RegisterPrefix("https://", WebRequestCreator.ClientHttp);
精彩评论