Eventually WCF duplex Silverlight 4 client start getting 404 Not Found
errors for poll messages, immediately after poll was send from WCF service to Silverlight client, sometimes this happens for second poll sometimes connectivity works hours or even days, but mostly fails on first minutes.
! And what is interesting the issue is like known Silverlight 4 bug when using MaxMessagesPerPoll
duplex mode and solution is described here and here but I'm using SingleMessagePerPoll
mode. ANyway I tried using ClientStack
as suggested but nothing changed.
General flow:
- SL client executes WCF service method, received response
- Then immediately SL client start sending poll messages to service and then getting exception for second or N-s poll message
System.Net.WebException: The remote server returned an error: NotFound
- Fiddler show only empty
404
response for a poll message - Then client Channel Faulted event raised
I'm trying to reconnect SL client after such a fault, single reconnect retry flow:
- Handle
Faulted
event - Unsubscribe all channel events like
Closed/Closing/Opened/Opening
- Close channel in a right way using
try { close } catch { abort }
- All below in a new thread poll thread:(I foudn this works slightly stable - see this article)
- Wait 45-70 seconds
- Using the same
DuplexChannelFactory<T>
instance create a new channel, subscribe to all channel events just for logging purposes - Execute WCF service method
After 1-10 retries (~1-10 minutes) client eventually connect to a server and continue normal polling.
In WCF service log I see it get all cleint request, processed without any exception, so it seems something happens on Silverlight Client side.
General info:
- .NET Framework 4.0
- PollingDuplex
- Async WCF methods
- IIS 6.0 hosted WCF service
- Silverligth 4 client
- Client OS: Windows XP SP2
- Server OS: Windows 2003 R2 SP2
- NTLM Authentication
- DuplexMode: SingleMessagePerPoll
- There is an other WCF service which does Request/Reply before my service start working, it not uses Duplex connectivity
- On SL client service I'm logging everything into the UI so see all events flow and have time for each particular event
- No errors in IIS logs, server event logs
Client:
var binaryBinding = new BinaryMessageEncodingBindingElement();
binaryBinding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
var httpbindingElement = new HttpTransportBindingElement
{
MaxReceivedMessageSize = 131072
};
var pollingDuplexBindingElement = new PollingDuplexBindingElement
{
ClientPollTimeout = new TimeSpan(0, 0, 1, 30),
InactivityTimeout = new TimeSpan(0, 8, 0, 0),
};
_binding = new CustomBinding(
pollingDuplexBindingElement,
binaryBinding,
httpbindingElement)
{
SendTimeout = new TimeSpan(0, 0, 0, 45),
CloseTimeout = new TimeSpan(0, 0, 0, 25),
ReceiveTimeout = new TimeSpan(0, 8, 0, 0),
OpenTimeout = new TimeSpan(0, 0, 0, 45)
};
httpbindingElement.AuthenticationScheme = AuthenticationSchemes.Negotiate;
var endpoint = new EndpointAddress(_endpointAddress);
_channelFactory = new DuplexChannelFactory<TWebService>(
new InstanceContext(instanceOfClientServiceClass),
_binding,
endpoint);
// then this factory used to create a new channels
// Also for a new channel I'm setting OpTimeout
var contextChannel = newChannel as IContextChannel;
if (contextChannel != null)
{
contextChannel.OperationTimeout = TimeSpan.FromSeconds(45);
}
Server:
- WCF, PerSession, multithreaded
- Everything is thread safe
- No server service exceptions while execution
- A lot of logging so I see what is going on on a service
- All WCF Traces are enabled with switchValue
All
, nothing suspicious
<binding name="customName"
sendTimeout="00:01:00"
receiveTimeout="08:00:00"
openTimeout="00:01:00"
closeTimeout="00:00:35">
<pollingDuplex
inactivityTimeout="08:00:00"
serverPollTimeout="00:01:00" />
<binaryMessageEncoding />
<httpTransport authenticationScheme="Ntlm"
maxReceivedMessageSize="131072">
</httpTransport>
</binding>
<behavior name="customBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceThrottling
maxConcurrentCalls = "500"
maxConcurrentSessions = "500"
maxConcurrentInstances = "500" />
</behavior>